@formant/data-sdk 0.0.116 → 0.0.118

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.
@@ -19230,659 +19230,831 @@ const envLocal = urlParams$2.get("formant_local");
19230
19230
  if (envLocal) {
19231
19231
  FORMANT_API_URL = "https://api.formant.local";
19232
19232
  }
19233
- class App {
19234
- static sendAppMessage(message) {
19235
- window.parent.postMessage(message, "*");
19233
+ function delay(ms) {
19234
+ return new Promise((resolve) => setTimeout(resolve, ms));
19235
+ }
19236
+ class DataChannel {
19237
+ constructor(dataChannel) {
19238
+ __publicField(this, "ready", false);
19239
+ __publicField(this, "listeners", []);
19240
+ __publicField(this, "openListeners", []);
19241
+ __publicField(this, "closeListeners", []);
19242
+ __publicField(this, "errorListeners", []);
19243
+ __publicField(this, "binaryListeners", []);
19244
+ __publicField(this, "error");
19245
+ __publicField(this, "decoder", new TextDecoder());
19246
+ this.dataChannel = dataChannel;
19247
+ this.dataChannel.binaryType = "arraybuffer";
19248
+ this.dataChannel.onopen = () => {
19249
+ this.ready = true;
19250
+ this.openListeners.forEach((listener) => listener());
19251
+ };
19252
+ this.dataChannel.onclose = () => {
19253
+ this.ready = false;
19254
+ this.closeListeners.forEach((listener) => listener());
19255
+ };
19256
+ this.dataChannel.onerror = (e) => {
19257
+ console.error(e);
19258
+ this.error = "An error occurred in DataChannel";
19259
+ this.errorListeners.forEach((listener) => listener(e));
19260
+ };
19261
+ this.dataChannel.onmessage = (m) => {
19262
+ this.listeners.forEach((_) => {
19263
+ const d = new Uint8Array(m.data);
19264
+ const s = this.decoder.decode(d);
19265
+ _(s);
19266
+ });
19267
+ this.binaryListeners.forEach((_) => {
19268
+ _(new Uint8Array(m.data));
19269
+ });
19270
+ };
19236
19271
  }
19237
- static getCurrentModuleContext() {
19238
- let urlParams2 = new URLSearchParams("");
19239
- if (typeof window !== "undefined") {
19240
- urlParams2 = new URLSearchParams(window.location.search);
19241
- }
19242
- const moduleName2 = urlParams2.get("module");
19243
- return moduleName2;
19272
+ addOpenListener(listener) {
19273
+ this.openListeners.push(listener);
19244
19274
  }
19245
- static async getCurrentModuleConfiguration() {
19246
- let urlParams2 = new URLSearchParams("");
19247
- if (typeof window !== "undefined") {
19248
- urlParams2 = new URLSearchParams(window.location.search);
19249
- }
19250
- const configurationId = urlParams2.get("configuration");
19251
- if (configurationId === null || configurationId.trim() === "") {
19252
- return void 0;
19253
- }
19254
- const response = await fetch(
19255
- `${FORMANT_API_URL}/v1/admin/module-configurations/` + configurationId,
19256
- {
19257
- headers: {
19258
- "Content-Type": "application/json",
19259
- Authorization: "Bearer " + Authentication.token
19260
- }
19261
- }
19262
- );
19263
- const moduleConfiguration = await response.json();
19264
- return moduleConfiguration.configuration;
19275
+ removeOpenListener(listener) {
19276
+ this.openListeners = this.openListeners.filter((_) => _ !== listener);
19265
19277
  }
19266
- static isModule() {
19267
- return this.getCurrentModuleContext() !== null;
19278
+ addCloseListener(listener) {
19279
+ this.closeListeners.push(listener);
19268
19280
  }
19269
- static goToTime(date) {
19270
- this.sendAppMessage({
19271
- type: "go_to_time",
19272
- time: date.getTime()
19273
- });
19281
+ removeCloseListener(listener) {
19282
+ this.closeListeners = this.closeListeners.filter((l) => l !== listener);
19274
19283
  }
19275
- static goToDevice(deviceId) {
19276
- this.sendAppMessage({
19277
- type: "go_to_device",
19278
- deviceId
19279
- });
19284
+ addErrorListener(listener) {
19285
+ this.errorListeners.push(listener);
19280
19286
  }
19281
- static showMessage(message) {
19282
- this.sendAppMessage({ type: "show_message", message });
19287
+ removeErrorListener(listener) {
19288
+ this.errorListeners = this.errorListeners.filter((l) => l !== listener);
19283
19289
  }
19284
- static requestModuleData() {
19285
- const moduleName2 = this.getCurrentModuleContext();
19286
- if (!moduleName2) {
19287
- throw new Error("No module context");
19290
+ async waitTilReady() {
19291
+ if (this.ready) {
19292
+ return true;
19288
19293
  }
19289
- this.sendAppMessage({
19290
- type: "request_module_data",
19291
- module: moduleName2
19294
+ const p = new Promise((resolve, reject) => {
19295
+ let a2 = window.setInterval(() => {
19296
+ if (this.ready) {
19297
+ window.clearInterval(a2);
19298
+ resolve(true);
19299
+ }
19300
+ if (this.error) {
19301
+ reject(this.error);
19302
+ }
19303
+ }, 10);
19292
19304
  });
19305
+ return p;
19293
19306
  }
19294
- static setModuleDateTimeRange(beforeInMilliseconds, afterInMilliseconds) {
19295
- const moduleName2 = this.getCurrentModuleContext();
19296
- if (!moduleName2) {
19297
- throw new Error("No module context");
19307
+ send(data) {
19308
+ if (!this.ready) {
19309
+ throw new Error("Connection has been closed");
19298
19310
  }
19299
- this.sendAppMessage({
19300
- type: "set_module_data_time_range",
19301
- module: moduleName2,
19302
- before: beforeInMilliseconds,
19303
- after: afterInMilliseconds || 0
19304
- });
19311
+ this.dataChannel.send(data);
19305
19312
  }
19306
- static refreshAuthToken() {
19307
- const moduleName2 = this.getCurrentModuleContext();
19308
- if (!moduleName2) {
19309
- throw new Error("No module context");
19313
+ sendBinary(data) {
19314
+ if (!this.ready) {
19315
+ throw new Error("Connection has been closed");
19310
19316
  }
19311
- this.sendAppMessage({
19312
- type: "refresh_auth_token",
19313
- module: moduleName2
19314
- });
19317
+ this.dataChannel.send(data);
19315
19318
  }
19316
- static sendChannelData(channel, data) {
19317
- const moduleName2 = this.getCurrentModuleContext();
19318
- if (!moduleName2) {
19319
- throw new Error("No module context");
19319
+ addListener(listener) {
19320
+ this.listeners.push(listener);
19321
+ }
19322
+ removeListener(listener) {
19323
+ const i = this.listeners.indexOf(listener);
19324
+ if (i === -1) {
19325
+ throw new Error("Could not find data channel listener to remove");
19320
19326
  }
19321
- this.sendAppMessage({
19322
- type: "send_channel_data",
19323
- source: moduleName2,
19324
- channel,
19325
- data
19326
- });
19327
+ if (this.error) {
19328
+ throw new Error(this.error);
19329
+ }
19330
+ this.listeners.splice(i, 1);
19327
19331
  }
19328
- static setupModuleMenus(menus) {
19329
- const moduleName2 = this.getCurrentModuleContext();
19330
- if (!moduleName2) {
19331
- throw new Error("No module context");
19332
+ addBinaryListener(listener) {
19333
+ this.binaryListeners.push(listener);
19334
+ }
19335
+ removeBinaryListener(listener) {
19336
+ const i = this.binaryListeners.indexOf(listener);
19337
+ if (i === -1) {
19338
+ throw new Error("Could not find data channel listener to remove");
19332
19339
  }
19333
- this.sendAppMessage({
19334
- type: "setup_module_menus",
19335
- module: moduleName2,
19336
- menus
19337
- });
19340
+ if (this.error) {
19341
+ throw new Error(this.error);
19342
+ }
19343
+ this.binaryListeners.splice(i, 1);
19338
19344
  }
19339
- static addMenuListener(handler) {
19340
- window.addEventListener("message", (event) => {
19341
- const msg = event.data;
19342
- if (msg.type === "module_menu_item_clicked") {
19343
- handler(msg.menu);
19344
- }
19345
- });
19345
+ }
19346
+ class CaptureStream {
19347
+ constructor(captureSession) {
19348
+ __publicField(this, "token");
19349
+ this.captureSession = captureSession;
19346
19350
  }
19347
- static addAccessTokenRefreshListener(handler) {
19348
- window.addEventListener("message", (event) => {
19349
- const msg = event.data;
19350
- if (msg.type === "auth_token") {
19351
- handler(msg.token);
19351
+ async ingestJSON(value) {
19352
+ if (!this.token) {
19353
+ const result = await fetch(
19354
+ `${FORMANT_API_URL}/v1/admin/capture-sessions/${this.captureSession.code}/authenticate`,
19355
+ {
19356
+ method: "POST"
19357
+ }
19358
+ );
19359
+ const authInfo = await result.json();
19360
+ this.token = authInfo.token;
19361
+ }
19362
+ await fetch(`${FORMANT_API_URL}/v1/ingest`, {
19363
+ method: "POST",
19364
+ body: JSON.stringify({
19365
+ deviceId: this.captureSession.deviceId,
19366
+ name: this.captureSession.streamName,
19367
+ type: "json",
19368
+ points: [[Date.now(), JSON.stringify(value)]]
19369
+ }),
19370
+ headers: {
19371
+ "Content-Type": "application/json",
19372
+ Authorization: "Bearer " + this.token
19352
19373
  }
19353
19374
  });
19354
19375
  }
19355
- static addModuleDataListener(handler) {
19356
- const moduleName2 = this.getCurrentModuleContext();
19357
- if (moduleName2) {
19358
- this.sendAppMessage({ type: "request_module_data", module: moduleName2 });
19359
- }
19360
- window.addEventListener("message", (event) => {
19361
- const msg = event.data;
19362
- if (msg.type === "module_data") {
19363
- handler({
19364
- streams: msg.streams,
19365
- time: msg.time,
19366
- queryRange: msg.queryRange
19376
+ }
19377
+ class Manipulator {
19378
+ constructor(device, config) {
19379
+ __publicField(this, "currentListeners", []);
19380
+ __publicField(this, "onRealtimeMessage", (_peerId, message) => {
19381
+ if (message.payload.jointState) {
19382
+ this.currentListeners.forEach((listener) => {
19383
+ if (message.payload.jointState)
19384
+ listener(message.payload.jointState);
19367
19385
  });
19368
19386
  }
19369
19387
  });
19388
+ this.device = device;
19389
+ this.config = config;
19370
19390
  }
19371
- static addModuleConfigurationListener(handler) {
19372
- window.addEventListener("message", (event) => {
19373
- const msg = event.data;
19374
- if (msg.type === "module_configuration") {
19375
- handler(msg);
19376
- }
19377
- });
19391
+ async synchronize() {
19392
+ this.device.addRealtimeListener(this.onRealtimeMessage);
19393
+ this.device.startListeningToRealtimeDataStream(
19394
+ this.config.currentJointStateStream
19395
+ );
19378
19396
  }
19379
- static addChannelDataListener(channel, handler) {
19380
- window.addEventListener("message", (event) => {
19381
- const msg = event.data;
19382
- if (msg.type === "channel_data" && msg.channel === channel) {
19383
- handler({
19384
- source: msg.source,
19385
- data: msg.data
19386
- });
19387
- }
19388
- });
19397
+ async desynchronize() {
19398
+ this.device.removeRealtimeListener(this.onRealtimeMessage);
19399
+ this.device.stopListeningToRealtimeDataStream(
19400
+ this.config.currentJointStateStream
19401
+ );
19389
19402
  }
19390
- static requestOverviewDevices(handler) {
19391
- this.sendAppMessage({ type: "request_devices" });
19392
- window.addEventListener("message", (event) => {
19393
- const msg = event.data;
19394
- handler(msg);
19395
- });
19403
+ async addCurrentJointStateListener(listener) {
19404
+ this.currentListeners.push(listener);
19396
19405
  }
19397
19406
  }
19398
- const _Authentication = class {
19399
- static async login(email, password) {
19400
- try {
19401
- const result = await fetch(`${FORMANT_API_URL}/v1/admin/auth/login`, {
19402
- method: "POST",
19403
- body: JSON.stringify({ email, password }),
19404
- headers: {
19405
- "Content-Type": "application/json"
19406
- }
19407
- });
19408
- const auth = await result.json();
19409
- if (result.status !== 200) {
19410
- throw new Error(auth.message);
19411
- }
19412
- await _Authentication.loginWithToken(
19413
- auth.authentication.accessToken,
19414
- auth.authentication.refreshToken
19415
- );
19416
- return auth.authentication;
19417
- } catch (e) {
19418
- _Authentication.waitingForAuth.forEach((_) => _(false));
19419
- _Authentication.waitingForAuth = [];
19420
- return Promise.reject(e);
19407
+ class RequestDataChannel {
19408
+ constructor(device, channel_name, timeout) {
19409
+ __publicField(this, "channel");
19410
+ __publicField(this, "requestIdToResponseMap", /* @__PURE__ */ new Map());
19411
+ this.device = device;
19412
+ this.channel_name = channel_name;
19413
+ this.timeout = timeout;
19414
+ }
19415
+ addOpenListener(listener) {
19416
+ defined(this.channel, "channel not initalized").addOpenListener(listener);
19417
+ }
19418
+ removeOpenListener(listener) {
19419
+ defined(this.channel, "channel not initalized").removeOpenListener(
19420
+ listener
19421
+ );
19422
+ }
19423
+ addCloseListener(listener) {
19424
+ defined(this.channel, "channel not initalized").addCloseListener(listener);
19425
+ }
19426
+ removeCloseListener(listener) {
19427
+ defined(this.channel, "channel not initalized").removeCloseListener(
19428
+ listener
19429
+ );
19430
+ }
19431
+ addErrorListener(listener) {
19432
+ defined(this.channel, "channel not initalized").addErrorListener(listener);
19433
+ }
19434
+ removeErrorListener(listener) {
19435
+ defined(this.channel, "channel not initalized").removeErrorListener(
19436
+ listener
19437
+ );
19438
+ }
19439
+ }
19440
+ class BinaryRequestDataChannel extends RequestDataChannel {
19441
+ constructor() {
19442
+ super(...arguments);
19443
+ __publicField(this, "RESPONSE_SUCCESS_BYTE", 0);
19444
+ __publicField(this, "decoder", new TextDecoder());
19445
+ }
19446
+ generateBinaryId() {
19447
+ const id = new Uint8Array(16);
19448
+ for (let i = 0; i < id.length; i++) {
19449
+ id[i] = Math.floor(Math.random() * 256);
19421
19450
  }
19451
+ return id;
19422
19452
  }
19423
- static async loginWithToken(token, refreshToken) {
19424
- const tokenData = JSON.parse(atob(token.split(".")[1]));
19425
- try {
19426
- let userId;
19427
- _Authentication.isShareToken = tokenData["formant:claims"] && tokenData["formant:claims"].type == "share";
19428
- if (tokenData["formant:claims"]) {
19429
- _Authentication.currentOrganization = tokenData["formant:claims"].organizationId;
19430
- }
19431
- if (tokenData["custom:organization_id"]) {
19432
- _Authentication.currentOrganization = tokenData["custom:organization_id"];
19453
+ async initialize() {
19454
+ this.channel = await this.device.createCustomDataChannel(this.channel_name);
19455
+ this.channel.addBinaryListener((message) => {
19456
+ const binaryId = message.slice(0, 16);
19457
+ const id = binaryId.toString();
19458
+ if (id.length === 0) {
19459
+ throw new Error("Invalid response");
19433
19460
  }
19434
- if (!_Authentication.isShareToken) {
19435
- userId = tokenData.sub;
19461
+ const response = message.slice(16);
19462
+ if (response.length === 0) {
19463
+ throw new Error("Invalid response");
19436
19464
  }
19437
- if (tokenData["formant:claims"] && tokenData["formant:claims"].userId) {
19438
- userId = tokenData["formant:claims"].userId;
19465
+ if (this.requestIdToResponseMap.has(id)) {
19466
+ this.requestIdToResponseMap.set(id, response);
19439
19467
  }
19440
- if (userId) {
19441
- const result = await fetch(
19442
- `${FORMANT_API_URL}/v1/admin/users/${userId}`,
19443
- {
19444
- method: "GET",
19445
- headers: {
19446
- "Content-Type": "application/json",
19447
- Authorization: "Bearer " + token
19448
- }
19468
+ });
19469
+ }
19470
+ async request(data) {
19471
+ if (!this.channel) {
19472
+ await this.initialize();
19473
+ }
19474
+ if (!this.channel) {
19475
+ throw new Error("Failed to create channel");
19476
+ }
19477
+ const { channel, requestIdToResponseMap, timeout } = this;
19478
+ await channel.waitTilReady();
19479
+ const binaryId = this.generateBinaryId();
19480
+ const id = binaryId.toString();
19481
+ requestIdToResponseMap.set(id, true);
19482
+ channel.sendBinary(new Uint8Array([...binaryId, ...data]));
19483
+ const start = new Date().getTime();
19484
+ while (new Date().getTime() < start + timeout) {
19485
+ await delay(50);
19486
+ if (requestIdToResponseMap.has(id)) {
19487
+ const response = requestIdToResponseMap.get(id);
19488
+ if (response !== true) {
19489
+ requestIdToResponseMap.delete(id);
19490
+ const success = response[0] === this.RESPONSE_SUCCESS_BYTE;
19491
+ const payload = response.slice(1);
19492
+ if (success) {
19493
+ return payload;
19494
+ } else {
19495
+ console.error({
19496
+ name: "AdapterError",
19497
+ message: this.decoder.decode(payload)
19498
+ });
19499
+ throw new Error("Binary request datachannel adapter error");
19449
19500
  }
19450
- );
19451
- const data = await result.json();
19452
- if (result.status !== 200) {
19453
- throw new Error(data.message);
19454
19501
  }
19455
- _Authentication.currentUser = data;
19456
19502
  }
19457
- _Authentication.token = token;
19458
- _Authentication.waitingForAuth.forEach((_) => _(true));
19459
- } catch (e) {
19460
- console.error(e);
19461
- _Authentication.waitingForAuth.forEach((_) => _(false));
19462
- }
19463
- _Authentication.waitingForAuth = [];
19464
- if (refreshToken) {
19465
- _Authentication.refreshToken = refreshToken;
19466
- setInterval(async () => {
19467
- if (_Authentication.refreshToken) {
19468
- const result = await fetch(
19469
- `${FORMANT_API_URL}/v1/admin/auth/refresh`,
19470
- {
19471
- method: "POST",
19472
- headers: {
19473
- "Content-Type": "application/json"
19474
- },
19475
- body: JSON.stringify({
19476
- refreshToken: _Authentication.refreshToken
19477
- })
19478
- }
19479
- );
19480
- const refreshData = await result.json();
19481
- _Authentication.token = refreshData.authentication.accessToken;
19482
- }
19483
- }, 1e3 * 60 * 60);
19484
19503
  }
19504
+ requestIdToResponseMap.delete(id);
19505
+ console.error({
19506
+ name: "TimeoutError",
19507
+ message: `Request timed out after ${timeout / 1e3} seconds`
19508
+ });
19509
+ throw new Error("Binary request data channel request timed out");
19485
19510
  }
19486
- static isAuthenticated() {
19487
- return _Authentication.token !== void 0;
19511
+ }
19512
+ class TextRequestDataChannel extends RequestDataChannel {
19513
+ generateTextId() {
19514
+ return Math.random().toString(36).substring(2) + "-" + Math.random().toString(36).substring(2);
19488
19515
  }
19489
- static getCurrentUser() {
19490
- return _Authentication.currentUser;
19516
+ async initialize() {
19517
+ this.channel = await this.device.createCustomDataChannel(this.channel_name);
19518
+ this.channel.addListener((message) => {
19519
+ const response = JSON.parse(message);
19520
+ const { id, data, error } = response;
19521
+ if (!id) {
19522
+ throw new Error("Invalid response");
19523
+ }
19524
+ if (!data && !error) {
19525
+ throw new Error("Invalid response");
19526
+ }
19527
+ if (this.requestIdToResponseMap.has(id)) {
19528
+ this.requestIdToResponseMap.set(id, response);
19529
+ }
19530
+ });
19491
19531
  }
19492
- static async waitTilAuthenticated() {
19493
- if (_Authentication.token !== void 0) {
19494
- return true;
19495
- } else {
19496
- return new Promise((resolve) => {
19497
- _Authentication.waitingForAuth.push(function(result) {
19498
- resolve(result);
19499
- });
19500
- });
19532
+ async request(data) {
19533
+ if (!this.channel) {
19534
+ await this.initialize();
19501
19535
  }
19502
- }
19503
- static async listenForRefresh() {
19504
- App.addAccessTokenRefreshListener((token) => {
19505
- this.loginWithToken(token);
19536
+ if (!this.channel) {
19537
+ throw new Error("Failed to create channel");
19538
+ }
19539
+ const { channel, requestIdToResponseMap, timeout } = this;
19540
+ await channel.waitTilReady();
19541
+ const id = this.generateTextId();
19542
+ requestIdToResponseMap.set(id, true);
19543
+ channel.send(
19544
+ JSON.stringify({
19545
+ id,
19546
+ data
19547
+ })
19548
+ );
19549
+ const start = new Date().getTime();
19550
+ while (new Date().getTime() < start + timeout) {
19551
+ await delay(50);
19552
+ if (requestIdToResponseMap.has(id)) {
19553
+ const response = requestIdToResponseMap.get(id);
19554
+ if (response !== true) {
19555
+ requestIdToResponseMap.delete(id);
19556
+ const { data: data2, error } = response;
19557
+ if (data2) {
19558
+ return data2;
19559
+ }
19560
+ if (error) {
19561
+ console.error({
19562
+ name: "AdapterError",
19563
+ message: error
19564
+ });
19565
+ throw new Error("Text request datachannel adapter error");
19566
+ }
19567
+ }
19568
+ }
19569
+ }
19570
+ requestIdToResponseMap.delete(id);
19571
+ console.error({
19572
+ name: "TimeoutError",
19573
+ message: `Request timed out after ${timeout / 1e3} seconds`
19506
19574
  });
19507
- setInterval(async () => {
19508
- App.refreshAuthToken();
19509
- }, 1e3 * 60 * 60);
19575
+ throw new Error("Text request datachannel request timed out");
19510
19576
  }
19511
- };
19512
- let Authentication = _Authentication;
19513
- __publicField(Authentication, "token");
19514
- __publicField(Authentication, "refreshToken");
19515
- __publicField(Authentication, "currentUser");
19516
- __publicField(Authentication, "currentOrganization");
19517
- __publicField(Authentication, "isShareToken", false);
19518
- __publicField(Authentication, "defaultDeviceId");
19519
- __publicField(Authentication, "waitingForAuth", []);
19520
- function delay(ms) {
19521
- return new Promise((resolve) => setTimeout(resolve, ms));
19522
19577
  }
19523
- class DataChannel {
19524
- constructor(dataChannel) {
19525
- __publicField(this, "ready", false);
19526
- __publicField(this, "listeners", []);
19527
- __publicField(this, "openListeners", []);
19528
- __publicField(this, "closeListeners", []);
19529
- __publicField(this, "errorListeners", []);
19530
- __publicField(this, "binaryListeners", []);
19531
- __publicField(this, "error");
19532
- __publicField(this, "decoder", new TextDecoder());
19533
- this.dataChannel = dataChannel;
19534
- this.dataChannel.binaryType = "arraybuffer";
19535
- this.dataChannel.onopen = () => {
19536
- this.ready = true;
19537
- this.openListeners.forEach((listener) => listener());
19538
- };
19539
- this.dataChannel.onclose = () => {
19540
- this.ready = false;
19541
- this.closeListeners.forEach((listener) => listener());
19542
- };
19543
- this.dataChannel.onerror = (e) => {
19544
- console.error(e);
19545
- this.error = "An error occurred in DataChannel";
19546
- this.errorListeners.forEach((listener) => listener(e));
19547
- };
19548
- this.dataChannel.onmessage = (m) => {
19549
- this.listeners.forEach((_) => {
19550
- const d = new Uint8Array(m.data);
19551
- const s = this.decoder.decode(d);
19552
- _(s);
19553
- });
19554
- this.binaryListeners.forEach((_) => {
19555
- _(new Uint8Array(m.data));
19556
- });
19557
- };
19558
- }
19559
- addOpenListener(listener) {
19560
- this.openListeners.push(listener);
19561
- }
19562
- removeOpenListener(listener) {
19563
- this.openListeners = this.openListeners.filter((_) => _ !== listener);
19578
+ const urlParams$1 = new URLSearchParams(window.location.search);
19579
+ const rtcClientVersion = urlParams$1.get("rtc_client");
19580
+ const SessionType = {
19581
+ Teleop: 1,
19582
+ Observe: 3
19583
+ };
19584
+ class Device {
19585
+ constructor(id, name, organizationId) {
19586
+ __publicField(this, "rtcClient");
19587
+ __publicField(this, "remoteDevicePeerId");
19588
+ __publicField(this, "realtimeListeners", []);
19589
+ __publicField(this, "handleMessage", (peerId, message) => {
19590
+ this.realtimeListeners.forEach((_) => _(peerId, message));
19591
+ });
19592
+ this.id = id;
19593
+ this.name = name;
19594
+ this.organizationId = organizationId;
19564
19595
  }
19565
- addCloseListener(listener) {
19566
- this.closeListeners.push(listener);
19596
+ async getLatestTelemetry() {
19597
+ const data = await fetch(
19598
+ `${FORMANT_API_URL}/v1/queries/stream-current-value`,
19599
+ {
19600
+ method: "POST",
19601
+ body: JSON.stringify({
19602
+ deviceIds: [this.id]
19603
+ }),
19604
+ headers: {
19605
+ "Content-Type": "application/json",
19606
+ Authorization: "Bearer " + Authentication.token
19607
+ }
19608
+ }
19609
+ );
19610
+ const telemetry = await data.json();
19611
+ return telemetry.items;
19567
19612
  }
19568
- removeCloseListener(listener) {
19569
- this.closeListeners = this.closeListeners.filter((l) => l !== listener);
19613
+ async getConfiguration() {
19614
+ let result = await fetch(`${FORMANT_API_URL}/v1/admin/devices/${this.id}`, {
19615
+ method: "GET",
19616
+ headers: {
19617
+ "Content-Type": "application/json",
19618
+ Authorization: "Bearer " + Authentication.token
19619
+ }
19620
+ });
19621
+ const device = await result.json();
19622
+ if (!device.state.reportedConfiguration) {
19623
+ throw new Error(
19624
+ "Device has no configuration, has it ever been turned on?"
19625
+ );
19626
+ }
19627
+ const version = device.state.reportedConfiguration.version;
19628
+ result = await fetch(
19629
+ `${FORMANT_API_URL}/v1/admin/devices/${this.id}/configurations/${version}`,
19630
+ {
19631
+ method: "GET",
19632
+ headers: {
19633
+ "Content-Type": "application/json",
19634
+ Authorization: "Bearer " + Authentication.token
19635
+ }
19636
+ }
19637
+ );
19638
+ const config = await result.json();
19639
+ return config.document;
19570
19640
  }
19571
- addErrorListener(listener) {
19572
- this.errorListeners.push(listener);
19641
+ async getFileUrl(fileId) {
19642
+ const result = await fetch(`${FORMANT_API_URL}/v1/admin/files/query`, {
19643
+ method: "POST",
19644
+ body: JSON.stringify({
19645
+ fileIds: [fileId]
19646
+ }),
19647
+ headers: {
19648
+ "Content-Type": "application/json",
19649
+ Authorization: "Bearer " + Authentication.token
19650
+ }
19651
+ });
19652
+ const files = await result.json();
19653
+ return files.fileUrls;
19573
19654
  }
19574
- removeErrorListener(listener) {
19575
- this.errorListeners = this.errorListeners.filter((l) => l !== listener);
19655
+ getRealtimeStatus() {
19656
+ if (this.rtcClient && this.remoteDevicePeerId) {
19657
+ return this.rtcClient.getConnectionStatus(this.remoteDevicePeerId);
19658
+ } else {
19659
+ throw new Error(`Realtime connection hasn't been started for ${this.id}`);
19660
+ }
19576
19661
  }
19577
- async waitTilReady() {
19578
- if (this.ready) {
19579
- return true;
19662
+ getRealtimePing() {
19663
+ if (this.rtcClient && this.remoteDevicePeerId) {
19664
+ return this.rtcClient.getPing(this.remoteDevicePeerId);
19665
+ } else {
19666
+ throw new Error(`Realtime connection hasn't been started for ${this.id}`);
19580
19667
  }
19581
- const p = new Promise((resolve, reject) => {
19582
- let a2 = window.setInterval(() => {
19583
- if (this.ready) {
19584
- window.clearInterval(a2);
19585
- resolve(true);
19586
- }
19587
- if (this.error) {
19588
- reject(this.error);
19668
+ }
19669
+ async startRealtimeConnection(sessionType) {
19670
+ if (!this.rtcClient) {
19671
+ let rtcClient;
19672
+ if (rtcClientVersion === "1") {
19673
+ rtcClient = new dist.exports.RtcClientV1({
19674
+ signalingClient: new dist.exports.RtcSignalingClient(
19675
+ FORMANT_API_URL + "/v1/signaling"
19676
+ ),
19677
+ getToken: async () => defined(
19678
+ Authentication.token,
19679
+ "Realtime when user isn't authorized"
19680
+ ),
19681
+ receive: this.handleMessage
19682
+ });
19683
+ } else {
19684
+ rtcClient = new dist.exports.RtcClient({
19685
+ signalingClient: new dist.exports.SignalingPromiseClient(
19686
+ FORMANT_API_URL,
19687
+ null,
19688
+ null
19689
+ ),
19690
+ getToken: async () => {
19691
+ return defined(
19692
+ Authentication.token,
19693
+ "Realtime when user isn't authorized"
19694
+ );
19695
+ },
19696
+ receive: this.handleMessage,
19697
+ sessionType
19698
+ });
19699
+ }
19700
+ if (rtcClient.isReady) {
19701
+ while (!rtcClient.isReady()) {
19702
+ await delay(100);
19589
19703
  }
19590
- }, 10);
19591
- });
19592
- return p;
19593
- }
19594
- send(data) {
19595
- if (!this.ready) {
19596
- throw new Error("Connection has been closed");
19704
+ }
19705
+ const peers = await rtcClient.getPeers();
19706
+ const devicePeer = peers.find((_) => _.deviceId === this.id);
19707
+ if (!devicePeer) {
19708
+ throw new Error("Cannot find peer, is the robot offline?");
19709
+ }
19710
+ this.remoteDevicePeerId = devicePeer.id;
19711
+ await rtcClient.connect(this.remoteDevicePeerId);
19712
+ while (rtcClient.getConnectionStatus(this.remoteDevicePeerId) !== "connected") {
19713
+ await delay(100);
19714
+ }
19715
+ this.rtcClient = rtcClient;
19716
+ } else {
19717
+ throw new Error(
19718
+ `Already created realtime connection to device ${this.id}`
19719
+ );
19597
19720
  }
19598
- this.dataChannel.send(data);
19599
19721
  }
19600
- sendBinary(data) {
19601
- if (!this.ready) {
19602
- throw new Error("Connection has been closed");
19603
- }
19604
- this.dataChannel.send(data);
19722
+ async sendRealtimeMessage(message, config = {
19723
+ channelLabel: "stream.reliable"
19724
+ }) {
19725
+ const client = defined(
19726
+ this.rtcClient,
19727
+ "Realtime connection has not been started"
19728
+ );
19729
+ const devicePeer = await this.getRemotePeer();
19730
+ client.send(defined(devicePeer).id, message, config);
19605
19731
  }
19606
- addListener(listener) {
19607
- this.listeners.push(listener);
19732
+ addRealtimeListener(listener) {
19733
+ this.realtimeListeners.push(listener);
19608
19734
  }
19609
- removeListener(listener) {
19610
- const i = this.listeners.indexOf(listener);
19735
+ removeRealtimeListener(listener) {
19736
+ const i = this.realtimeListeners.indexOf(listener);
19611
19737
  if (i === -1) {
19612
- throw new Error("Could not find data channel listener to remove");
19613
- }
19614
- if (this.error) {
19615
- throw new Error(this.error);
19738
+ throw new Error("Could not find realtime listener to remove");
19616
19739
  }
19617
- this.listeners.splice(i, 1);
19618
- }
19619
- addBinaryListener(listener) {
19620
- this.binaryListeners.push(listener);
19740
+ this.realtimeListeners.splice(i, 1);
19621
19741
  }
19622
- removeBinaryListener(listener) {
19623
- const i = this.binaryListeners.indexOf(listener);
19624
- if (i === -1) {
19625
- throw new Error("Could not find data channel listener to remove");
19742
+ async getRealtimeAudioStreams() {
19743
+ var _a, _b, _c, _d, _e, _f;
19744
+ const document2 = await this.getConfiguration();
19745
+ const streams = [];
19746
+ for (const _ of (_b = (_a = document2.teleop) == null ? void 0 : _a.hardwareStreams) != null ? _b : []) {
19747
+ if (_.rtcStreamType === "audio-chunk") {
19748
+ streams.push({
19749
+ name: _.name
19750
+ });
19751
+ }
19626
19752
  }
19627
- if (this.error) {
19628
- throw new Error(this.error);
19753
+ for (const _ of (_d = (_c = document2.teleop) == null ? void 0 : _c.rosStreams) != null ? _d : []) {
19754
+ if (_.topicType == "audio_common_msgs/AudioData") {
19755
+ streams.push({
19756
+ name: _.topicName
19757
+ });
19758
+ }
19629
19759
  }
19630
- this.binaryListeners.splice(i, 1);
19631
- }
19632
- }
19633
- class CaptureStream {
19634
- constructor(captureSession) {
19635
- __publicField(this, "token");
19636
- this.captureSession = captureSession;
19760
+ for (const _ of (_f = (_e = document2.teleop) == null ? void 0 : _e.customStreams) != null ? _f : []) {
19761
+ if (_.rtcStreamType === "audio-chunk") {
19762
+ streams.push({
19763
+ name: _.name
19764
+ });
19765
+ }
19766
+ }
19767
+ return streams;
19637
19768
  }
19638
- async ingestJSON(value) {
19639
- if (!this.token) {
19640
- const result = await fetch(
19641
- `${FORMANT_API_URL}/v1/admin/capture-sessions/${this.captureSession.code}/authenticate`,
19642
- {
19643
- method: "POST"
19644
- }
19645
- );
19646
- const authInfo = await result.json();
19647
- this.token = authInfo.token;
19769
+ async getRealtimeVideoStreams() {
19770
+ var _a, _b, _c, _d, _e, _f;
19771
+ const document2 = await this.getConfiguration();
19772
+ const streams = [];
19773
+ for (const _ of (_b = (_a = document2.teleop) == null ? void 0 : _a.hardwareStreams) != null ? _b : []) {
19774
+ if (_.rtcStreamType === "h264-video-frame") {
19775
+ streams.push({
19776
+ name: _.name
19777
+ });
19778
+ }
19648
19779
  }
19649
- await fetch(`${FORMANT_API_URL}/v1/ingest`, {
19650
- method: "POST",
19651
- body: JSON.stringify({
19652
- deviceId: this.captureSession.deviceId,
19653
- name: this.captureSession.streamName,
19654
- type: "json",
19655
- points: [[Date.now(), JSON.stringify(value)]]
19656
- }),
19657
- headers: {
19658
- "Content-Type": "application/json",
19659
- Authorization: "Bearer " + this.token
19780
+ for (const _ of (_d = (_c = document2.teleop) == null ? void 0 : _c.rosStreams) != null ? _d : []) {
19781
+ if (_.topicType == "formant/H264VideoFrame") {
19782
+ streams.push({
19783
+ name: _.topicName
19784
+ });
19660
19785
  }
19661
- });
19662
- }
19663
- }
19664
- class Manipulator {
19665
- constructor(device, config) {
19666
- __publicField(this, "currentListeners", []);
19667
- __publicField(this, "onRealtimeMessage", (_peerId, message) => {
19668
- if (message.payload.jointState) {
19669
- this.currentListeners.forEach((listener) => {
19670
- if (message.payload.jointState)
19671
- listener(message.payload.jointState);
19786
+ }
19787
+ for (const _ of (_f = (_e = document2.teleop) == null ? void 0 : _e.customStreams) != null ? _f : []) {
19788
+ if (_.rtcStreamType === "h264-video-frame") {
19789
+ streams.push({
19790
+ name: _.name
19672
19791
  });
19673
19792
  }
19674
- });
19675
- this.device = device;
19676
- this.config = config;
19793
+ }
19794
+ return streams;
19677
19795
  }
19678
- async synchronize() {
19679
- this.device.addRealtimeListener(this.onRealtimeMessage);
19680
- this.device.startListeningToRealtimeDataStream(
19681
- this.config.currentJointStateStream
19682
- );
19796
+ async getRealtimeManipulators() {
19797
+ var _a;
19798
+ const document2 = await this.getConfiguration();
19799
+ const manipulators = [];
19800
+ for (const _ of (_a = document2.teleop.rosStreams) != null ? _a : []) {
19801
+ if (_.topicType == "sensor_msgs/JointState") {
19802
+ manipulators.push(
19803
+ new Manipulator(this, {
19804
+ currentJointStateStream: { name: _.topicName },
19805
+ plannedJointStateStream: _.plannedTopic ? { name: _.plannedTopic } : void 0,
19806
+ planValidStream: _.planValidTopic ? { name: _.planValidTopic } : void 0,
19807
+ endEffectorStream: _.endEffectorTopic ? { name: _.endEffectorTopic } : void 0,
19808
+ endEffectorLinkName: _.endEffectorLinkName,
19809
+ baseReferenceFrame: _.baseReferenceFrame,
19810
+ localFrame: _.localFrame
19811
+ })
19812
+ );
19813
+ }
19814
+ }
19815
+ return manipulators;
19683
19816
  }
19684
- async desynchronize() {
19685
- this.device.removeRealtimeListener(this.onRealtimeMessage);
19686
- this.device.stopListeningToRealtimeDataStream(
19687
- this.config.currentJointStateStream
19817
+ async startListeningToRealtimeVideo(stream) {
19818
+ const client = defined(
19819
+ this.rtcClient,
19820
+ "Realtime connection has not been started"
19688
19821
  );
19822
+ const devicePeer = await this.getRemotePeer();
19823
+ client.controlRemoteStream(defined(devicePeer).id, {
19824
+ streamName: stream.name,
19825
+ enable: true,
19826
+ pipeline: "rtc"
19827
+ });
19689
19828
  }
19690
- async addCurrentJointStateListener(listener) {
19691
- this.currentListeners.push(listener);
19692
- }
19693
- }
19694
- class RequestDataChannel {
19695
- constructor(device, channel_name, timeout) {
19696
- __publicField(this, "channel");
19697
- __publicField(this, "requestIdToResponseMap", /* @__PURE__ */ new Map());
19698
- this.device = device;
19699
- this.channel_name = channel_name;
19700
- this.timeout = timeout;
19829
+ async stopListeningToRealtimeVideo(stream) {
19830
+ const client = defined(
19831
+ this.rtcClient,
19832
+ "Realtime connection has not been started"
19833
+ );
19834
+ const devicePeer = await this.getRemotePeer();
19835
+ client.controlRemoteStream(defined(devicePeer).id, {
19836
+ streamName: stream.name,
19837
+ enable: false,
19838
+ pipeline: "rtc"
19839
+ });
19701
19840
  }
19702
- addOpenListener(listener) {
19703
- defined(this.channel, "channel not initalized").addOpenListener(listener);
19841
+ async startListeningToRealtimeDataStream(stream) {
19842
+ const client = defined(
19843
+ this.rtcClient,
19844
+ "Realtime connection has not been started"
19845
+ );
19846
+ const devicePeer = await this.getRemotePeer();
19847
+ client.controlRemoteStream(defined(devicePeer).id, {
19848
+ streamName: stream.name,
19849
+ enable: true,
19850
+ pipeline: "rtc"
19851
+ });
19704
19852
  }
19705
- removeOpenListener(listener) {
19706
- defined(this.channel, "channel not initalized").removeOpenListener(
19707
- listener
19853
+ async stopListeningToRealtimeDataStream(stream) {
19854
+ const client = defined(
19855
+ this.rtcClient,
19856
+ "Realtime connection has not been started"
19708
19857
  );
19858
+ const devicePeer = await this.getRemotePeer();
19859
+ client.controlRemoteStream(defined(devicePeer).id, {
19860
+ streamName: stream.name,
19861
+ enable: false,
19862
+ pipeline: "rtc"
19863
+ });
19709
19864
  }
19710
- addCloseListener(listener) {
19711
- defined(this.channel, "channel not initalized").addCloseListener(listener);
19865
+ async enableRealtimeTelemetryPriorityIngestion(streamName) {
19866
+ const client = defined(
19867
+ this.rtcClient,
19868
+ "Realtime connection has not been started"
19869
+ );
19870
+ const devicePeer = await this.getRemotePeer();
19871
+ client.controlRemoteStream(defined(devicePeer).id, {
19872
+ streamName,
19873
+ enablePriorityUpload: true,
19874
+ pipeline: "telemetry"
19875
+ });
19712
19876
  }
19713
- removeCloseListener(listener) {
19714
- defined(this.channel, "channel not initalized").removeCloseListener(
19715
- listener
19877
+ async changeStreamAudioType(streamName, newFormat) {
19878
+ const client = defined(
19879
+ this.rtcClient,
19880
+ "Realtime connection has not been started"
19716
19881
  );
19882
+ const devicePeer = await this.getRemotePeer();
19883
+ client.controlRemoteStream(defined(devicePeer).id, {
19884
+ streamName,
19885
+ setAudioFormat: newFormat
19886
+ });
19717
19887
  }
19718
- addErrorListener(listener) {
19719
- defined(this.channel, "channel not initalized").addErrorListener(listener);
19888
+ async disableRealtimeTelemetryPriorityIngestion(streamName) {
19889
+ const client = defined(
19890
+ this.rtcClient,
19891
+ "Realtime connection has not been started"
19892
+ );
19893
+ const devicePeer = await this.getRemotePeer();
19894
+ client.controlRemoteStream(defined(devicePeer).id, {
19895
+ streamName,
19896
+ enablePriorityUpload: false,
19897
+ pipeline: "telemetry"
19898
+ });
19720
19899
  }
19721
- removeErrorListener(listener) {
19722
- defined(this.channel, "channel not initalized").removeErrorListener(
19723
- listener
19900
+ async getRemotePeer() {
19901
+ const peers = await defined(
19902
+ this.rtcClient,
19903
+ "Realtime connection has not been started"
19904
+ ).getPeers();
19905
+ const devicePeer = peers.find((_) => _.deviceId === this.id);
19906
+ return defined(
19907
+ devicePeer,
19908
+ "Could not find remote peer for device " + this.id
19724
19909
  );
19725
19910
  }
19726
- }
19727
- class BinaryRequestDataChannel extends RequestDataChannel {
19728
- constructor() {
19729
- super(...arguments);
19730
- __publicField(this, "RESPONSE_SUCCESS_BYTE", 0);
19731
- __publicField(this, "decoder", new TextDecoder());
19911
+ async stopRealtimeConnection() {
19912
+ if (this.rtcClient) {
19913
+ await this.rtcClient.disconnect(this.id);
19914
+ } else {
19915
+ throw new Error(`Realtime connection hasn't been started for ${this.id}`);
19916
+ }
19732
19917
  }
19733
- generateBinaryId() {
19734
- const id = new Uint8Array(16);
19735
- for (let i = 0; i < id.length; i++) {
19736
- id[i] = Math.floor(Math.random() * 256);
19918
+ async isInRealtimeSession() {
19919
+ let peers = await Fleet.getPeers();
19920
+ let sessions = await Fleet.getRealtimeSessions();
19921
+ let peer = peers.find((_) => _.deviceId === this.id);
19922
+ if (peer) {
19923
+ return sessions[peer.id].length > 0;
19737
19924
  }
19738
- return id;
19925
+ return false;
19739
19926
  }
19740
- async initialize() {
19741
- this.channel = await this.device.createCustomDataChannel(this.channel_name);
19742
- this.channel.addBinaryListener((message) => {
19743
- const binaryId = message.slice(0, 16);
19744
- const id = binaryId.toString();
19745
- if (id.length === 0) {
19746
- throw new Error("Invalid response");
19747
- }
19748
- const response = message.slice(16);
19749
- if (response.length === 0) {
19750
- throw new Error("Invalid response");
19751
- }
19752
- if (this.requestIdToResponseMap.has(id)) {
19753
- this.requestIdToResponseMap.set(id, response);
19927
+ async getAvailableCommands() {
19928
+ const result = await fetch(
19929
+ `${FORMANT_API_URL}/v1/admin/command-templates/`,
19930
+ {
19931
+ method: "GET",
19932
+ headers: {
19933
+ "Content-Type": "application/json",
19934
+ Authorization: "Bearer " + Authentication.token
19935
+ }
19754
19936
  }
19755
- });
19937
+ );
19938
+ const commands = await result.json();
19939
+ return commands.items.map((i) => ({
19940
+ name: i.name,
19941
+ id: i.id,
19942
+ command: i.command,
19943
+ description: i.description,
19944
+ parameterEnabled: i.parameterEnabled,
19945
+ parameterValue: i.parameterValue,
19946
+ parameterMeta: i.parameterMeta,
19947
+ enabled: i.enabled
19948
+ }));
19756
19949
  }
19757
- async request(data) {
19758
- if (!this.channel) {
19759
- await this.initialize();
19760
- }
19761
- if (!this.channel) {
19762
- throw new Error("Failed to create channel");
19950
+ async sendCommand(name, data, time, metadata) {
19951
+ var _a;
19952
+ const commands = await this.getAvailableCommands();
19953
+ const command = commands.find((_) => _.name === name);
19954
+ if (!command) {
19955
+ throw new Error(`Could not find command with name "${name}"`);
19763
19956
  }
19764
- const { channel, requestIdToResponseMap, timeout } = this;
19765
- await channel.waitTilReady();
19766
- const binaryId = this.generateBinaryId();
19767
- const id = binaryId.toString();
19768
- requestIdToResponseMap.set(id, true);
19769
- channel.sendBinary(new Uint8Array([...binaryId, ...data]));
19770
- const start = new Date().getTime();
19771
- while (new Date().getTime() < start + timeout) {
19772
- await delay(50);
19773
- if (requestIdToResponseMap.has(id)) {
19774
- const response = requestIdToResponseMap.get(id);
19775
- if (response !== true) {
19776
- requestIdToResponseMap.delete(id);
19777
- const success = response[0] === this.RESPONSE_SUCCESS_BYTE;
19778
- const payload = response.slice(1);
19779
- if (success) {
19780
- return payload;
19781
- } else {
19782
- console.error({
19783
- name: "AdapterError",
19784
- message: this.decoder.decode(payload)
19785
- });
19786
- throw new Error("Binary request datachannel adapter error");
19787
- }
19788
- }
19957
+ let d;
19958
+ if (data === void 0) {
19959
+ if (command.parameterEnabled && command.parameterValue) {
19960
+ d = command.parameterValue;
19961
+ } else {
19962
+ throw new Error(
19963
+ "Command has no default parameter value, you must provide one"
19964
+ );
19789
19965
  }
19966
+ } else {
19967
+ d = data;
19790
19968
  }
19791
- requestIdToResponseMap.delete(id);
19792
- console.error({
19793
- name: "TimeoutError",
19794
- message: `Request timed out after ${timeout / 1e3} seconds`
19795
- });
19796
- throw new Error("Binary request data channel request timed out");
19797
- }
19798
- }
19799
- class TextRequestDataChannel extends RequestDataChannel {
19800
- generateTextId() {
19801
- return Math.random().toString(36).substring(2) + "-" + Math.random().toString(36).substring(2);
19802
- }
19803
- async initialize() {
19804
- this.channel = await this.device.createCustomDataChannel(this.channel_name);
19805
- this.channel.addListener((message) => {
19806
- const response = JSON.parse(message);
19807
- const { id, data, error } = response;
19808
- if (!id) {
19809
- throw new Error("Invalid response");
19810
- }
19811
- if (!data && !error) {
19812
- throw new Error("Invalid response");
19969
+ let parameter = {
19970
+ value: d,
19971
+ scrubberTime: (time || new Date()).toISOString(),
19972
+ meta: {
19973
+ ...command.parameterMeta,
19974
+ ...metadata
19813
19975
  }
19814
- if (this.requestIdToResponseMap.has(id)) {
19815
- this.requestIdToResponseMap.set(id, response);
19976
+ };
19977
+ await fetch(`${FORMANT_API_URL}/v1/admin/commands`, {
19978
+ method: "POST",
19979
+ body: JSON.stringify({
19980
+ commandTemplateId: command.id,
19981
+ organizationId: this.organizationId,
19982
+ deviceId: this.id,
19983
+ command: command.command,
19984
+ parameter,
19985
+ userId: (_a = Authentication.currentUser) == null ? void 0 : _a.id
19986
+ }),
19987
+ headers: {
19988
+ "Content-Type": "application/json",
19989
+ Authorization: "Bearer " + Authentication.token
19816
19990
  }
19817
19991
  });
19818
19992
  }
19819
- async request(data) {
19820
- if (!this.channel) {
19821
- await this.initialize();
19822
- }
19823
- if (!this.channel) {
19824
- throw new Error("Failed to create channel");
19993
+ async createCustomDataChannel(channelName, rtcConfig) {
19994
+ if (rtcClientVersion === "1") {
19995
+ throw new Error(
19996
+ "createCustomDataChannel is not supported in rtcClientVersion 1"
19997
+ );
19825
19998
  }
19826
- const { channel, requestIdToResponseMap, timeout } = this;
19827
- await channel.waitTilReady();
19828
- const id = this.generateTextId();
19829
- requestIdToResponseMap.set(id, true);
19830
- channel.send(
19831
- JSON.stringify({
19832
- id,
19833
- data
19834
- })
19999
+ const client = defined(
20000
+ this.rtcClient,
20001
+ "Realtime connection has not been started"
19835
20002
  );
19836
- const start = new Date().getTime();
19837
- while (new Date().getTime() < start + timeout) {
19838
- await delay(50);
19839
- if (requestIdToResponseMap.has(id)) {
19840
- const response = requestIdToResponseMap.get(id);
19841
- if (response !== true) {
19842
- requestIdToResponseMap.delete(id);
19843
- const { data: data2, error } = response;
19844
- if (data2) {
19845
- return data2;
19846
- }
19847
- if (error) {
19848
- console.error({
19849
- name: "AdapterError",
19850
- message: error
19851
- });
19852
- throw new Error("Text request datachannel adapter error");
19853
- }
20003
+ const devicePeer = await this.getRemotePeer();
20004
+ const p = await new Promise((resolve) => {
20005
+ client.createCustomDataChannel(
20006
+ defined(devicePeer).id,
20007
+ channelName,
20008
+ {
20009
+ ordered: true,
20010
+ ...rtcConfig
20011
+ },
20012
+ false,
20013
+ (_peerId, channel) => {
20014
+ const dataChannel = new DataChannel(channel);
20015
+ resolve(dataChannel);
19854
20016
  }
20017
+ );
20018
+ });
20019
+ await p.waitTilReady();
20020
+ return p;
20021
+ }
20022
+ createCustomRequestDataChannel(channelName, timeout = 3e3) {
20023
+ return new TextRequestDataChannel(this, channelName, timeout);
20024
+ }
20025
+ createCustomBinaryRequestDataChannel(channelName, timeout = 3e3) {
20026
+ return new BinaryRequestDataChannel(this, channelName, timeout);
20027
+ }
20028
+ async createCaptureStream(streamName) {
20029
+ const result = await fetch(`${FORMANT_API_URL}/v1/admin/capture-sessions`, {
20030
+ method: "POST",
20031
+ body: JSON.stringify({
20032
+ deviceId: this.id,
20033
+ streamName,
20034
+ tags: {}
20035
+ }),
20036
+ headers: {
20037
+ "Content-Type": "application/json",
20038
+ Authorization: "Bearer " + Authentication.token
19855
20039
  }
19856
- }
19857
- requestIdToResponseMap.delete(id);
19858
- console.error({
19859
- name: "TimeoutError",
19860
- message: `Request timed out after ${timeout / 1e3} seconds`
19861
20040
  });
19862
- throw new Error("Text request datachannel request timed out");
20041
+ const captureSession = await result.json();
20042
+ return new CaptureStream(captureSession);
19863
20043
  }
19864
- }
19865
- const urlParams$1 = new URLSearchParams(window.location.search);
19866
- const rtcClientVersion = urlParams$1.get("rtc_client");
19867
- const SessionType = {
19868
- Teleop: 1,
19869
- Observe: 3
19870
- };
19871
- class Device {
19872
- constructor(id, name, organizationId) {
19873
- __publicField(this, "rtcClient");
19874
- __publicField(this, "remoteDevicePeerId");
19875
- __publicField(this, "realtimeListeners", []);
19876
- __publicField(this, "handleMessage", (peerId, message) => {
19877
- this.realtimeListeners.forEach((_) => _(peerId, message));
19878
- });
19879
- this.id = id;
19880
- this.name = name;
19881
- this.organizationId = organizationId;
20044
+ async getTelemetry(streamNameOrStreamNames, start, end, tags) {
20045
+ return await Fleet.getTelemetry(
20046
+ this.id,
20047
+ streamNameOrStreamNames,
20048
+ start,
20049
+ end,
20050
+ tags
20051
+ );
19882
20052
  }
19883
- async getLatestTelemetry() {
19884
- const data = await fetch(
19885
- `${FORMANT_API_URL}/v1/queries/stream-current-value`,
20053
+ async getTelemetryStreams() {
20054
+ var _a, _b;
20055
+ const config = await this.getConfiguration();
20056
+ const result = await fetch(
20057
+ `${FORMANT_API_URL}/v1/queries/metadata/stream-names`,
19886
20058
  {
19887
20059
  method: "POST",
19888
20060
  body: JSON.stringify({
@@ -19894,109 +20066,123 @@ class Device {
19894
20066
  }
19895
20067
  }
19896
20068
  );
19897
- const telemetry = await data.json();
19898
- return telemetry.items;
19899
- }
19900
- async getConfiguration() {
19901
- let result = await fetch(`${FORMANT_API_URL}/v1/admin/devices/${this.id}`, {
19902
- method: "GET",
19903
- headers: {
19904
- "Content-Type": "application/json",
19905
- Authorization: "Bearer " + Authentication.token
20069
+ const disabledList = [];
20070
+ const onDemandList = [];
20071
+ (_b = (_a = config.telemetry) == null ? void 0 : _a.streams) == null ? void 0 : _b.forEach((_) => {
20072
+ if (_.disabled !== true) {
20073
+ disabledList.push(_.name);
20074
+ }
20075
+ if (_.onDemand === true) {
20076
+ onDemandList.push(_.name);
19906
20077
  }
19907
20078
  });
19908
- const device = await result.json();
19909
- if (!device.state.reportedConfiguration) {
19910
- throw new Error(
19911
- "Device has no configuration, has it ever been turned on?"
19912
- );
19913
- }
19914
- const version = device.state.reportedConfiguration.version;
19915
- result = await fetch(
19916
- `${FORMANT_API_URL}/v1/admin/devices/${this.id}/configurations/${version}`,
20079
+ console.log(onDemandList);
20080
+ const data = await result.json();
20081
+ let streamNames = data.items.filter((_) => !disabledList.includes(_)).map((_) => ({ name: _, onDemand: onDemandList.includes(_) }));
20082
+ return streamNames;
20083
+ }
20084
+ async createInterventionRequest(message, interventionType, interventionRequest, tags) {
20085
+ const intervention = await fetch(
20086
+ `${FORMANT_API_URL}/v1/admin/intervention-requests`,
19917
20087
  {
19918
- method: "GET",
20088
+ method: "POST",
20089
+ body: JSON.stringify({
20090
+ message,
20091
+ interventionType,
20092
+ time: new Date().toISOString(),
20093
+ deviceId: this.id,
20094
+ tags,
20095
+ data: interventionRequest
20096
+ }),
19919
20097
  headers: {
19920
20098
  "Content-Type": "application/json",
19921
20099
  Authorization: "Bearer " + Authentication.token
19922
20100
  }
19923
20101
  }
19924
20102
  );
19925
- const config = await result.json();
19926
- return config.document;
20103
+ const interventionJson = await intervention.json();
20104
+ return interventionJson;
19927
20105
  }
19928
- async getFileUrl(fileId) {
19929
- const result = await fetch(`${FORMANT_API_URL}/v1/admin/files/query`, {
19930
- method: "POST",
19931
- body: JSON.stringify({
19932
- fileIds: [fileId]
19933
- }),
19934
- headers: {
19935
- "Content-Type": "application/json",
19936
- Authorization: "Bearer " + Authentication.token
20106
+ async addInterventionResponse(interventionId, interventionType, data) {
20107
+ const response = await fetch(
20108
+ `${FORMANT_API_URL}/v1/admin/intervention-responses`,
20109
+ {
20110
+ method: "POST",
20111
+ body: JSON.stringify({
20112
+ interventionId,
20113
+ interventionType,
20114
+ data
20115
+ }),
20116
+ headers: {
20117
+ "Content-Type": "application/json",
20118
+ Authorization: "Bearer " + Authentication.token
20119
+ }
19937
20120
  }
20121
+ );
20122
+ const interventionResponse = await response.json();
20123
+ return interventionResponse;
20124
+ }
20125
+ }
20126
+ class PeerDevice {
20127
+ constructor(peerUrl) {
20128
+ __publicField(this, "rtcClient");
20129
+ __publicField(this, "remoteDevicePeerId");
20130
+ __publicField(this, "realtimeListeners", []);
20131
+ __publicField(this, "id");
20132
+ __publicField(this, "handleMessage", (peerId, message) => {
20133
+ this.realtimeListeners.forEach((_) => _(peerId, message));
19938
20134
  });
19939
- const files = await result.json();
19940
- return files.fileUrls;
20135
+ this.peerUrl = peerUrl;
20136
+ }
20137
+ async getLatestTelemetry() {
20138
+ const data = await fetch(`${this.peerUrl}/telemetry`);
20139
+ const telemetry = await data.json();
20140
+ const entries = Object.entries(telemetry);
20141
+ return entries.map(([stream, latestValue]) => {
20142
+ const v = {
20143
+ deviceId: this.id,
20144
+ streamName: stream,
20145
+ streamType: "json",
20146
+ currentValue: latestValue,
20147
+ currentValueTime: latestValue.timestamp,
20148
+ tags: {}
20149
+ };
20150
+ return v;
20151
+ });
20152
+ }
20153
+ async getDeviceId() {
20154
+ let result = await fetch(`${this.peerUrl}/configuration`);
20155
+ const cfg = await result.json();
20156
+ return cfg.agent_config.id;
20157
+ }
20158
+ async getConfiguration() {
20159
+ let result = await fetch(`${this.peerUrl}/configuration`);
20160
+ const cfg = await result.json();
20161
+ return cfg.agent_config.document;
19941
20162
  }
19942
20163
  getRealtimeStatus() {
19943
20164
  if (this.rtcClient && this.remoteDevicePeerId) {
19944
20165
  return this.rtcClient.getConnectionStatus(this.remoteDevicePeerId);
19945
20166
  } else {
19946
- throw new Error(`Realtime connection hasn't been started for ${this.id}`);
20167
+ throw new Error(`Realtime connection hasn't been started`);
19947
20168
  }
19948
20169
  }
19949
20170
  getRealtimePing() {
19950
20171
  if (this.rtcClient && this.remoteDevicePeerId) {
19951
20172
  return this.rtcClient.getPing(this.remoteDevicePeerId);
19952
20173
  } else {
19953
- throw new Error(`Realtime connection hasn't been started for ${this.id}`);
20174
+ throw new Error(`Realtime connection hasn't been started`);
19954
20175
  }
19955
20176
  }
19956
20177
  async startRealtimeConnection(sessionType) {
19957
20178
  if (!this.rtcClient) {
19958
- let rtcClient;
19959
- if (rtcClientVersion === "1") {
19960
- rtcClient = new dist.exports.RtcClientV1({
19961
- signalingClient: new dist.exports.RtcSignalingClient(
19962
- FORMANT_API_URL + "/v1/signaling"
19963
- ),
19964
- getToken: async () => defined(
19965
- Authentication.token,
19966
- "Realtime when user isn't authorized"
19967
- ),
19968
- receive: this.handleMessage
19969
- });
19970
- } else {
19971
- rtcClient = new dist.exports.RtcClient({
19972
- signalingClient: new dist.exports.SignalingPromiseClient(
19973
- FORMANT_API_URL,
19974
- null,
19975
- null
19976
- ),
19977
- getToken: async () => {
19978
- return defined(
19979
- Authentication.token,
19980
- "Realtime when user isn't authorized"
19981
- );
19982
- },
19983
- receive: this.handleMessage,
19984
- sessionType
19985
- });
19986
- }
19987
- if (rtcClient.isReady) {
19988
- while (!rtcClient.isReady()) {
19989
- await delay(100);
19990
- }
19991
- }
19992
- const peers = await rtcClient.getPeers();
19993
- const devicePeer = peers.find((_) => _.deviceId === this.id);
19994
- if (!devicePeer) {
19995
- throw new Error("Cannot find peer, is the robot offline?");
19996
- }
19997
- this.remoteDevicePeerId = devicePeer.id;
19998
- await rtcClient.connect(this.remoteDevicePeerId);
19999
- while (rtcClient.getConnectionStatus(this.remoteDevicePeerId) !== "connected") {
20179
+ const rtcClient = new dist.exports.RtcClient({
20180
+ lanOnlyMode: true,
20181
+ receive: this.handleMessage,
20182
+ sessionType
20183
+ });
20184
+ await rtcClient.connectLan(this.peerUrl);
20185
+ while (rtcClient.getConnectionStatus(this.peerUrl) !== "connected") {
20000
20186
  await delay(100);
20001
20187
  }
20002
20188
  this.rtcClient = rtcClient;
@@ -20006,16 +20192,6 @@ class Device {
20006
20192
  );
20007
20193
  }
20008
20194
  }
20009
- async sendRealtimeMessage(message, config = {
20010
- channelLabel: "stream.reliable"
20011
- }) {
20012
- const client = defined(
20013
- this.rtcClient,
20014
- "Realtime connection has not been started"
20015
- );
20016
- const devicePeer = await this.getRemotePeer();
20017
- client.send(defined(devicePeer).id, message, config);
20018
- }
20019
20195
  addRealtimeListener(listener) {
20020
20196
  this.realtimeListeners.push(listener);
20021
20197
  }
@@ -20024,54 +20200,27 @@ class Device {
20024
20200
  if (i === -1) {
20025
20201
  throw new Error("Could not find realtime listener to remove");
20026
20202
  }
20027
- this.realtimeListeners.splice(i, 1);
20028
- }
20029
- async getRealtimeAudioStreams() {
20030
- var _a, _b, _c, _d, _e, _f;
20031
- const document2 = await this.getConfiguration();
20032
- const streams = [];
20033
- for (const _ of (_b = (_a = document2.teleop) == null ? void 0 : _a.hardwareStreams) != null ? _b : []) {
20034
- if (_.rtcStreamType === "audio-chunk") {
20035
- streams.push({
20036
- name: _.name
20037
- });
20038
- }
20039
- }
20040
- for (const _ of (_d = (_c = document2.teleop) == null ? void 0 : _c.rosStreams) != null ? _d : []) {
20041
- if (_.topicType == "audio_common_msgs/AudioData") {
20042
- streams.push({
20043
- name: _.topicName
20044
- });
20045
- }
20046
- }
20047
- for (const _ of (_f = (_e = document2.teleop) == null ? void 0 : _e.customStreams) != null ? _f : []) {
20048
- if (_.rtcStreamType === "audio-chunk") {
20049
- streams.push({
20050
- name: _.name
20051
- });
20052
- }
20053
- }
20054
- return streams;
20203
+ this.realtimeListeners.splice(i, 1);
20055
20204
  }
20056
20205
  async getRealtimeVideoStreams() {
20057
- var _a, _b, _c, _d, _e, _f;
20206
+ var _a, _b, _c;
20058
20207
  const document2 = await this.getConfiguration();
20059
20208
  const streams = [];
20060
- for (const _ of (_b = (_a = document2.teleop) == null ? void 0 : _a.hardwareStreams) != null ? _b : []) {
20209
+ for (const _ of (_a = document2.teleop.hardwareStreams) != null ? _a : []) {
20061
20210
  if (_.rtcStreamType === "h264-video-frame") {
20062
20211
  streams.push({
20063
20212
  name: _.name
20064
20213
  });
20065
20214
  }
20066
20215
  }
20067
- for (const _ of (_d = (_c = document2.teleop) == null ? void 0 : _c.rosStreams) != null ? _d : []) {
20216
+ for (const _ of (_b = document2.teleop.rosStreams) != null ? _b : []) {
20068
20217
  if (_.topicType == "formant/H264VideoFrame") {
20069
20218
  streams.push({
20070
20219
  name: _.topicName
20071
20220
  });
20072
20221
  }
20073
20222
  }
20074
- for (const _ of (_f = (_e = document2.teleop) == null ? void 0 : _e.customStreams) != null ? _f : []) {
20223
+ for (const _ of (_c = document2.teleop.customStreams) != null ? _c : []) {
20075
20224
  if (_.rtcStreamType === "h264-video-frame") {
20076
20225
  streams.push({
20077
20226
  name: _.name
@@ -20161,17 +20310,6 @@ class Device {
20161
20310
  pipeline: "telemetry"
20162
20311
  });
20163
20312
  }
20164
- async changeStreamAudioType(streamName, newFormat) {
20165
- const client = defined(
20166
- this.rtcClient,
20167
- "Realtime connection has not been started"
20168
- );
20169
- const devicePeer = await this.getRemotePeer();
20170
- client.controlRemoteStream(defined(devicePeer).id, {
20171
- streamName,
20172
- setAudioFormat: newFormat
20173
- });
20174
- }
20175
20313
  async disableRealtimeTelemetryPriorityIngestion(streamName) {
20176
20314
  const client = defined(
20177
20315
  this.rtcClient,
@@ -20185,15 +20323,13 @@ class Device {
20185
20323
  });
20186
20324
  }
20187
20325
  async getRemotePeer() {
20188
- const peers = await defined(
20189
- this.rtcClient,
20190
- "Realtime connection has not been started"
20191
- ).getPeers();
20192
- const devicePeer = peers.find((_) => _.deviceId === this.id);
20193
- return defined(
20194
- devicePeer,
20195
- "Could not find remote peer for device " + this.id
20196
- );
20326
+ return {
20327
+ id: this.peerUrl,
20328
+ organizationId: "",
20329
+ deviceId: this.id,
20330
+ capabilities: [],
20331
+ capabilitySet: {}
20332
+ };
20197
20333
  }
20198
20334
  async stopRealtimeConnection() {
20199
20335
  if (this.rtcClient) {
@@ -20202,18 +20338,82 @@ class Device {
20202
20338
  throw new Error(`Realtime connection hasn't been started for ${this.id}`);
20203
20339
  }
20204
20340
  }
20205
- async isInRealtimeSession() {
20206
- let peers = await Fleet.getPeers();
20207
- let sessions = await Fleet.getRealtimeSessions();
20208
- let peer = peers.find((_) => _.deviceId === this.id);
20209
- if (peer) {
20210
- return sessions[peer.id].length > 0;
20341
+ async createCustomDataChannel(channelName, rtcConfig) {
20342
+ const client = defined(
20343
+ this.rtcClient,
20344
+ "Realtime connection has not been started"
20345
+ );
20346
+ const devicePeer = await this.getRemotePeer();
20347
+ const p = await new Promise((resolve) => {
20348
+ client.createCustomDataChannel(
20349
+ defined(devicePeer).id,
20350
+ channelName,
20351
+ {
20352
+ ordered: true,
20353
+ ...rtcConfig
20354
+ },
20355
+ false,
20356
+ (_peerId, channel) => {
20357
+ const dataChannel = new DataChannel(channel);
20358
+ resolve(dataChannel);
20359
+ }
20360
+ );
20361
+ });
20362
+ await p.waitTilReady();
20363
+ return p;
20364
+ }
20365
+ createCustomRequestDataChannel(channelName, timeout = 3e3) {
20366
+ return new TextRequestDataChannel(this, channelName, timeout);
20367
+ }
20368
+ createCustomBinaryRequestDataChannel(channelName, timeout = 3e3) {
20369
+ return new BinaryRequestDataChannel(this, channelName, timeout);
20370
+ }
20371
+ }
20372
+ const _Fleet$1 = class {
20373
+ static async setDefaultDevice(deviceId) {
20374
+ _Fleet$1.defaultDeviceId = deviceId;
20375
+ }
20376
+ static async getCurrentDevice() {
20377
+ if (!Authentication.token) {
20378
+ throw new Error("Not authenticated");
20211
20379
  }
20212
- return false;
20380
+ if (!_Fleet$1.defaultDeviceId) {
20381
+ throw new Error("No known default device");
20382
+ }
20383
+ const data = await fetch(
20384
+ `${FORMANT_API_URL}/v1/admin/device-details/query`,
20385
+ {
20386
+ method: "POST",
20387
+ headers: {
20388
+ "Content-Type": "application/json",
20389
+ Authorization: "Bearer " + Authentication.token
20390
+ }
20391
+ }
20392
+ );
20393
+ const devices = await data.json();
20394
+ const device = devices.items.find(
20395
+ (_) => _.id === _Fleet$1.defaultDeviceId
20396
+ );
20397
+ const name = device.name;
20398
+ const context = new Device(
20399
+ _Fleet$1.defaultDeviceId,
20400
+ name,
20401
+ defined(Authentication.currentOrganization)
20402
+ );
20403
+ _Fleet$1.knownContext.push(new WeakRef(context));
20404
+ return context;
20213
20405
  }
20214
- async getAvailableCommands() {
20215
- const result = await fetch(
20216
- `${FORMANT_API_URL}/v1/admin/command-templates/`,
20406
+ static async getPeerDevice(url) {
20407
+ const peer = new PeerDevice(url);
20408
+ peer.id = await peer.getDeviceId();
20409
+ return peer;
20410
+ }
20411
+ static async getDevice(deviceId) {
20412
+ if (!Authentication.token) {
20413
+ throw new Error("Not authenticated");
20414
+ }
20415
+ const data = await fetch(
20416
+ `${FORMANT_API_URL}/v1/admin/devices/${deviceId}`,
20217
20417
  {
20218
20418
  method: "GET",
20219
20419
  headers: {
@@ -20222,440 +20422,868 @@ class Device {
20222
20422
  }
20223
20423
  }
20224
20424
  );
20225
- const commands = await result.json();
20226
- return commands.items.map((i) => ({
20227
- name: i.name,
20228
- id: i.id,
20229
- command: i.command,
20230
- description: i.description,
20231
- parameterEnabled: i.parameterEnabled,
20232
- parameterValue: i.parameterValue,
20233
- parameterMeta: i.parameterMeta,
20234
- enabled: i.enabled
20235
- }));
20425
+ const device = await data.json();
20426
+ const name = device.name;
20427
+ const context = new Device(deviceId, name, device.organizationId);
20428
+ _Fleet$1.knownContext.push(new WeakRef(context));
20429
+ return context;
20236
20430
  }
20237
- async sendCommand(name, data, time, metadata) {
20238
- var _a;
20239
- const commands = await this.getAvailableCommands();
20240
- const command = commands.find((_) => _.name === name);
20241
- if (!command) {
20242
- throw new Error(`Could not find command with name "${name}"`);
20431
+ static async getDevices() {
20432
+ if (!Authentication.token) {
20433
+ throw new Error("Not authenticated");
20243
20434
  }
20244
- let d;
20245
- if (data === void 0) {
20246
- if (command.parameterEnabled && command.parameterValue) {
20247
- d = command.parameterValue;
20248
- } else {
20249
- throw new Error(
20250
- "Command has no default parameter value, you must provide one"
20435
+ const data = await fetch(
20436
+ `${FORMANT_API_URL}/v1/admin/device-details/query`,
20437
+ {
20438
+ method: "POST",
20439
+ body: JSON.stringify({ enabled: true, type: "default" }),
20440
+ headers: {
20441
+ "Content-Type": "application/json",
20442
+ Authorization: "Bearer " + Authentication.token
20443
+ }
20444
+ }
20445
+ );
20446
+ const devices = await data.json();
20447
+ devices.items;
20448
+ return devices.items.map(
20449
+ (_) => new Device(_.id, _.name, _.organizationId)
20450
+ );
20451
+ }
20452
+ static async queryDevices(query) {
20453
+ if (!Authentication.token) {
20454
+ throw new Error("Not authenticated");
20455
+ }
20456
+ const data = await fetch(`${FORMANT_API_URL}/v1/admin/devices/query`, {
20457
+ method: "POST",
20458
+ body: JSON.stringify(query),
20459
+ headers: {
20460
+ "Content-Type": "application/json",
20461
+ Authorization: "Bearer " + Authentication.token
20462
+ }
20463
+ });
20464
+ const devices = await data.json();
20465
+ return devices.items.map(
20466
+ (_) => new Device(_.id, _.name, _.organizationId)
20467
+ );
20468
+ }
20469
+ static async getOnlineDevices() {
20470
+ if (!Authentication.token) {
20471
+ throw new Error("Not authenticated");
20472
+ }
20473
+ const data = await fetch(`${FORMANT_API_URL}/v1/queries/online-devices`, {
20474
+ method: "GET",
20475
+ headers: {
20476
+ "Content-Type": "application/json",
20477
+ Authorization: "Bearer " + Authentication.token
20478
+ }
20479
+ });
20480
+ const devices = await data.json();
20481
+ const onlineIds = devices.items;
20482
+ const allDevices = await _Fleet$1.getDevices();
20483
+ return allDevices.filter((_) => onlineIds.includes(_.id));
20484
+ }
20485
+ static async getPeers() {
20486
+ if (!Authentication.token) {
20487
+ throw new Error("Not authenticated");
20488
+ }
20489
+ const rtcClient = new dist.exports.RtcClient({
20490
+ signalingClient: new dist.exports.SignalingPromiseClient(FORMANT_API_URL, null, null),
20491
+ getToken: async () => {
20492
+ return defined(
20493
+ Authentication.token,
20494
+ "Realtime when user isn't authorized"
20495
+ );
20496
+ },
20497
+ receive: () => {
20498
+ }
20499
+ });
20500
+ return await rtcClient.getPeers();
20501
+ }
20502
+ static async getRealtimeSessions() {
20503
+ if (!Authentication.token) {
20504
+ throw new Error("Not authenticated");
20505
+ }
20506
+ const rtcClient = new dist.exports.RtcClient({
20507
+ signalingClient: new dist.exports.SignalingPromiseClient(FORMANT_API_URL, null, null),
20508
+ getToken: async () => {
20509
+ return defined(
20510
+ Authentication.token,
20511
+ "Realtime when user isn't authorized"
20251
20512
  );
20513
+ },
20514
+ receive: () => {
20515
+ }
20516
+ });
20517
+ return await rtcClient.getSessions();
20518
+ }
20519
+ static async getRealtimeDevices() {
20520
+ if (!Authentication.token) {
20521
+ throw new Error("Not authenticated");
20522
+ }
20523
+ const data = await fetch(`${FORMANT_API_URL}/v1/signaling/peers`, {
20524
+ method: "GET",
20525
+ headers: {
20526
+ "Content-Type": "application/json",
20527
+ Authorization: "Bearer " + Authentication.token
20528
+ }
20529
+ });
20530
+ const devices = await data.json();
20531
+ const onlineIds = devices.items.map(
20532
+ (_) => _.deviceId
20533
+ );
20534
+ const allDevices = await _Fleet$1.getDevices();
20535
+ return allDevices.filter((_) => onlineIds.includes(_.id));
20536
+ }
20537
+ static async getLatestTelemetry(deviceIdOrDeviceIds) {
20538
+ let deviceIds = deviceIdOrDeviceIds;
20539
+ if (deviceIdOrDeviceIds && !Array.isArray(deviceIdOrDeviceIds)) {
20540
+ deviceIdOrDeviceIds = [deviceIdOrDeviceIds];
20541
+ }
20542
+ const data = await fetch(
20543
+ `${FORMANT_API_URL}/v1/queries/stream-current-value`,
20544
+ {
20545
+ method: "POST",
20546
+ body: JSON.stringify({
20547
+ deviceIds
20548
+ }),
20549
+ headers: {
20550
+ "Content-Type": "application/json",
20551
+ Authorization: "Bearer " + Authentication.token
20552
+ }
20252
20553
  }
20253
- } else {
20254
- d = data;
20554
+ );
20555
+ const telemetry = await data.json();
20556
+ return telemetry.items;
20557
+ }
20558
+ static async getTelemetry(deviceIdOrDeviceIds, streamNameOrStreamNames, start, end, tags) {
20559
+ let deviceIds = deviceIdOrDeviceIds;
20560
+ if (!Array.isArray(deviceIdOrDeviceIds)) {
20561
+ deviceIds = [deviceIdOrDeviceIds];
20255
20562
  }
20256
- let parameter = {
20257
- value: d,
20258
- scrubberTime: (time || new Date()).toISOString(),
20259
- meta: {
20260
- ...command.parameterMeta,
20261
- ...metadata
20563
+ let streamNames = streamNameOrStreamNames;
20564
+ if (!Array.isArray(streamNameOrStreamNames)) {
20565
+ streamNames = [streamNameOrStreamNames];
20566
+ }
20567
+ const data = await fetch(`${FORMANT_API_URL}/v1/queries/queries`, {
20568
+ method: "POST",
20569
+ body: JSON.stringify({
20570
+ deviceIds,
20571
+ end: end.toISOString(),
20572
+ names: streamNames,
20573
+ start: start.toISOString(),
20574
+ tags
20575
+ }),
20576
+ headers: {
20577
+ "Content-Type": "application/json",
20578
+ Authorization: "Bearer " + Authentication.token
20262
20579
  }
20263
- };
20264
- await fetch(`${FORMANT_API_URL}/v1/admin/commands`, {
20580
+ });
20581
+ const telemetry = await data.json();
20582
+ return telemetry.items;
20583
+ }
20584
+ static async getFileUrl(uuid) {
20585
+ const data = await fetch(`${FORMANT_API_URL}/v1/admin/files/query`, {
20265
20586
  method: "POST",
20266
20587
  body: JSON.stringify({
20267
- commandTemplateId: command.id,
20268
- organizationId: this.organizationId,
20269
- deviceId: this.id,
20270
- command: command.command,
20271
- parameter,
20272
- userId: (_a = Authentication.currentUser) == null ? void 0 : _a.id
20588
+ fileIds: [uuid]
20273
20589
  }),
20274
20590
  headers: {
20275
20591
  "Content-Type": "application/json",
20276
20592
  Authorization: "Bearer " + Authentication.token
20277
20593
  }
20278
20594
  });
20595
+ const result = await data.json();
20596
+ if (result.fileUrls.length === 0) {
20597
+ throw new Error("File not found");
20598
+ }
20599
+ return result.fileUrls[0];
20279
20600
  }
20280
- async createCustomDataChannel(channelName, rtcConfig) {
20281
- if (rtcClientVersion === "1") {
20282
- throw new Error(
20283
- "createCustomDataChannel is not supported in rtcClientVersion 1"
20284
- );
20601
+ static async queryTelemetry(query) {
20602
+ if (!Authentication.token) {
20603
+ throw new Error("Not authenticated");
20285
20604
  }
20286
- const client = defined(
20287
- this.rtcClient,
20288
- "Realtime connection has not been started"
20289
- );
20290
- const devicePeer = await this.getRemotePeer();
20291
- const p = await new Promise((resolve) => {
20292
- client.createCustomDataChannel(
20293
- defined(devicePeer).id,
20294
- channelName,
20295
- {
20296
- ordered: true,
20297
- ...rtcConfig
20298
- },
20299
- false,
20300
- (_peerId, channel) => {
20301
- const dataChannel = new DataChannel(channel);
20302
- resolve(dataChannel);
20303
- }
20304
- );
20605
+ const data = await fetch(`${FORMANT_API_URL}/v1/queries/queries`, {
20606
+ method: "POST",
20607
+ body: JSON.stringify(query),
20608
+ headers: {
20609
+ "Content-Type": "application/json",
20610
+ Authorization: "Bearer " + Authentication.token
20611
+ }
20305
20612
  });
20306
- await p.waitTilReady();
20307
- return p;
20308
- }
20309
- createCustomRequestDataChannel(channelName, timeout = 3e3) {
20310
- return new TextRequestDataChannel(this, channelName, timeout);
20613
+ return (await data.json()).items;
20311
20614
  }
20312
- createCustomBinaryRequestDataChannel(channelName, timeout = 3e3) {
20313
- return new BinaryRequestDataChannel(this, channelName, timeout);
20615
+ static async aggregateTelemetry(query) {
20616
+ if (!Authentication.token) {
20617
+ throw new Error("Not authenticated");
20618
+ }
20619
+ const data = await fetch(`${FORMANT_API_URL}/v1/queries/queries`, {
20620
+ method: "POST",
20621
+ body: JSON.stringify(query),
20622
+ headers: {
20623
+ "Content-Type": "application/json",
20624
+ Authorization: "Bearer " + Authentication.token
20625
+ }
20626
+ });
20627
+ return (await data.json()).aggregates;
20314
20628
  }
20315
- async createCaptureStream(streamName) {
20316
- const result = await fetch(`${FORMANT_API_URL}/v1/admin/capture-sessions`, {
20629
+ static async queryEvents(query) {
20630
+ if (!Authentication.token) {
20631
+ throw new Error("Not authenticated");
20632
+ }
20633
+ const data = await fetch(`${FORMANT_API_URL}/v1/admin/events/query`, {
20317
20634
  method: "POST",
20318
- body: JSON.stringify({
20319
- deviceId: this.id,
20320
- streamName,
20321
- tags: {}
20322
- }),
20635
+ body: JSON.stringify(query),
20323
20636
  headers: {
20324
20637
  "Content-Type": "application/json",
20325
20638
  Authorization: "Bearer " + Authentication.token
20326
20639
  }
20327
20640
  });
20328
- const captureSession = await result.json();
20329
- return new CaptureStream(captureSession);
20641
+ return (await data.json()).items;
20330
20642
  }
20331
- async getTelemetry(streamNameOrStreamNames, start, end, tags) {
20332
- return await Fleet.getTelemetry(
20333
- this.id,
20334
- streamNameOrStreamNames,
20335
- start,
20336
- end,
20337
- tags
20643
+ static async getEvent(uuid) {
20644
+ if (!Authentication.token) {
20645
+ throw new Error("Not authenticated");
20646
+ }
20647
+ const data = await fetch(
20648
+ `${FORMANT_API_URL}/v1/admin/events/query/id=${uuid}`,
20649
+ {
20650
+ method: "GET",
20651
+ headers: {
20652
+ "Content-Type": "application/json",
20653
+ Authorization: "Bearer " + Authentication.token
20654
+ }
20655
+ }
20338
20656
  );
20657
+ return (await data.json()).items;
20339
20658
  }
20340
- async getTelemetryStreams() {
20341
- var _a, _b;
20342
- const config = await this.getConfiguration();
20343
- const result = await fetch(
20344
- `${FORMANT_API_URL}/v1/queries/metadata/stream-names`,
20659
+ static async getInterventions() {
20660
+ if (!Authentication.token) {
20661
+ throw new Error("Not authenticated");
20662
+ }
20663
+ const interventions = await fetch(
20664
+ `${FORMANT_API_URL}/v1/admin/intervention-requests`,
20345
20665
  {
20346
- method: "POST",
20347
- body: JSON.stringify({
20348
- deviceIds: [this.id]
20349
- }),
20666
+ method: "GET",
20350
20667
  headers: {
20351
20668
  "Content-Type": "application/json",
20352
20669
  Authorization: "Bearer " + Authentication.token
20353
20670
  }
20354
20671
  }
20355
20672
  );
20356
- const disabledList = [];
20357
- const onDemandList = [];
20358
- (_b = (_a = config.telemetry) == null ? void 0 : _a.streams) == null ? void 0 : _b.forEach((_) => {
20359
- if (_.disabled !== true) {
20360
- disabledList.push(_.name);
20673
+ return (await interventions.json()).items;
20674
+ }
20675
+ static async getCurrentGroup() {
20676
+ if (!Authentication.token) {
20677
+ throw new Error("Not authenticated");
20678
+ }
20679
+ let urlParams2 = new URLSearchParams("");
20680
+ if (typeof window !== "undefined") {
20681
+ urlParams2 = new URLSearchParams(window.location.search);
20682
+ }
20683
+ const groupId = urlParams2.get("group");
20684
+ if (groupId === null || groupId.trim() === "") {
20685
+ return void 0;
20686
+ }
20687
+ const response = await fetch(
20688
+ `${FORMANT_API_URL}/v1/admin/groups/` + groupId,
20689
+ {
20690
+ headers: {
20691
+ "Content-Type": "application/json",
20692
+ Authorization: "Bearer " + Authentication.token
20693
+ }
20361
20694
  }
20362
- if (_.onDemand === true) {
20363
- onDemandList.push(_.name);
20695
+ );
20696
+ const { tagKey, tagValue } = await response.json();
20697
+ const devices = await this.queryDevices({
20698
+ tags: { [tagKey]: [tagValue] },
20699
+ enabled: true,
20700
+ type: "default"
20701
+ });
20702
+ return devices;
20703
+ }
20704
+ };
20705
+ let Fleet$1 = _Fleet$1;
20706
+ __publicField(Fleet$1, "defaultDeviceId");
20707
+ __publicField(Fleet$1, "knownContext", []);
20708
+ function toInteger(dirtyNumber) {
20709
+ if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
20710
+ return NaN;
20711
+ }
20712
+ var number = Number(dirtyNumber);
20713
+ if (isNaN(number)) {
20714
+ return number;
20715
+ }
20716
+ return number < 0 ? Math.ceil(number) : Math.floor(number);
20717
+ }
20718
+ function requiredArgs(required, args) {
20719
+ if (args.length < required) {
20720
+ throw new TypeError(required + " argument" + (required > 1 ? "s" : "") + " required, but only " + args.length + " present");
20721
+ }
20722
+ }
20723
+ function _typeof(obj) {
20724
+ "@babel/helpers - typeof";
20725
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
20726
+ _typeof = function _typeof2(obj2) {
20727
+ return typeof obj2;
20728
+ };
20729
+ } else {
20730
+ _typeof = function _typeof2(obj2) {
20731
+ return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
20732
+ };
20733
+ }
20734
+ return _typeof(obj);
20735
+ }
20736
+ function toDate(argument) {
20737
+ requiredArgs(1, arguments);
20738
+ var argStr = Object.prototype.toString.call(argument);
20739
+ if (argument instanceof Date || _typeof(argument) === "object" && argStr === "[object Date]") {
20740
+ return new Date(argument.getTime());
20741
+ } else if (typeof argument === "number" || argStr === "[object Number]") {
20742
+ return new Date(argument);
20743
+ } else {
20744
+ if ((typeof argument === "string" || argStr === "[object String]") && typeof console !== "undefined") {
20745
+ console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments");
20746
+ console.warn(new Error().stack);
20747
+ }
20748
+ return new Date(NaN);
20749
+ }
20750
+ }
20751
+ function addMilliseconds(dirtyDate, dirtyAmount) {
20752
+ requiredArgs(2, arguments);
20753
+ var timestamp = toDate(dirtyDate).getTime();
20754
+ var amount = toInteger(dirtyAmount);
20755
+ return new Date(timestamp + amount);
20756
+ }
20757
+ var MILLISECONDS_IN_MINUTE = 6e4;
20758
+ function addMinutes(dirtyDate, dirtyAmount) {
20759
+ requiredArgs(2, arguments);
20760
+ var amount = toInteger(dirtyAmount);
20761
+ return addMilliseconds(dirtyDate, amount * MILLISECONDS_IN_MINUTE);
20762
+ }
20763
+ function addSeconds(dirtyDate, dirtyAmount) {
20764
+ requiredArgs(2, arguments);
20765
+ var amount = toInteger(dirtyAmount);
20766
+ return addMilliseconds(dirtyDate, amount * 1e3);
20767
+ }
20768
+ var roundingMap = {
20769
+ ceil: Math.ceil,
20770
+ round: Math.round,
20771
+ floor: Math.floor,
20772
+ trunc: function trunc(value) {
20773
+ return value < 0 ? Math.ceil(value) : Math.floor(value);
20774
+ }
20775
+ };
20776
+ var defaultRoundingMethod = "trunc";
20777
+ function getRoundingMethod(method) {
20778
+ return method ? roundingMap[method] : roundingMap[defaultRoundingMethod];
20779
+ }
20780
+ function startOfMinute(dirtyDate) {
20781
+ requiredArgs(1, arguments);
20782
+ var date = toDate(dirtyDate);
20783
+ date.setSeconds(0, 0);
20784
+ return date;
20785
+ }
20786
+ function roundToNearestMinutes(dirtyDate, options) {
20787
+ var _options$nearestTo;
20788
+ if (arguments.length < 1) {
20789
+ throw new TypeError("1 argument required, but only none provided present");
20790
+ }
20791
+ var nearestTo = toInteger((_options$nearestTo = options === null || options === void 0 ? void 0 : options.nearestTo) !== null && _options$nearestTo !== void 0 ? _options$nearestTo : 1);
20792
+ if (nearestTo < 1 || nearestTo > 30) {
20793
+ throw new RangeError("`options.nearestTo` must be between 1 and 30");
20794
+ }
20795
+ var date = toDate(dirtyDate);
20796
+ var seconds = date.getSeconds();
20797
+ var minutes = date.getMinutes() + seconds / 60;
20798
+ var roundingMethod = getRoundingMethod(options === null || options === void 0 ? void 0 : options.roundingMethod);
20799
+ var roundedMinutes = roundingMethod(minutes / nearestTo) * nearestTo;
20800
+ var remainderMinutes = minutes % nearestTo;
20801
+ var addedMinutes = Math.round(remainderMinutes / nearestTo) * nearestTo;
20802
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), roundedMinutes + addedMinutes);
20803
+ }
20804
+ const millisecond = 1;
20805
+ const second = 1e3;
20806
+ const minute = 60 * second;
20807
+ const hour = 60 * minute;
20808
+ const day = 24 * hour;
20809
+ const week = 7 * day;
20810
+ const month = 30 * day;
20811
+ const year = 365 * day;
20812
+ const duration = {
20813
+ millisecond,
20814
+ second,
20815
+ minute,
20816
+ hour,
20817
+ day,
20818
+ week,
20819
+ month,
20820
+ year
20821
+ };
20822
+ function filterDataByType(datas, type) {
20823
+ return datas.filter((_) => _.type === type);
20824
+ }
20825
+ function filterDataByTime(datas, start, end) {
20826
+ const startTime = start.getTime();
20827
+ const endTime = end.getTime();
20828
+ return datas.map((data) => ({
20829
+ ...data,
20830
+ points: data.points.filter(
20831
+ ([timestamp]) => timestamp >= startTime && timestamp < endTime
20832
+ )
20833
+ })).filter(({ points }) => points.length > 0);
20834
+ }
20835
+ function fork(_) {
20836
+ return void 0;
20837
+ }
20838
+ class StoreCache {
20839
+ constructor({
20840
+ capacity,
20841
+ timeout
20842
+ } = {}) {
20843
+ __publicField(this, "entries", /* @__PURE__ */ new Map());
20844
+ __publicField(this, "metadata", /* @__PURE__ */ new Map());
20845
+ __publicField(this, "capacity");
20846
+ __publicField(this, "timeout");
20847
+ this.capacity = capacity || 1e4;
20848
+ this.timeout = timeout || duration.minute;
20849
+ }
20850
+ get(key, generator) {
20851
+ const cacheKey = this.keyToCacheKey(key);
20852
+ const entry = this.entries.get(cacheKey);
20853
+ const metadata = this.metadata.get(cacheKey);
20854
+ if ((entry === void 0 || metadata && (metadata == null ? void 0 : metadata.expiration.getTime()) < Date.now()) && !(metadata == null ? void 0 : metadata.generating) && generator) {
20855
+ this.generate(key, generator());
20856
+ }
20857
+ if (entry === void 0 && metadata && metadata.lastValue !== void 0) {
20858
+ return metadata.lastValue;
20859
+ }
20860
+ return entry;
20861
+ }
20862
+ set(key, value) {
20863
+ const cacheKey = this.keyToCacheKey(key);
20864
+ this.metadata.set(cacheKey, {
20865
+ generating: false,
20866
+ expiration: new Date(Date.now() + this.timeout),
20867
+ lastValue: value
20868
+ });
20869
+ this.entries.set(cacheKey, value);
20870
+ if (this.metadata.size > this.capacity) {
20871
+ this.deleteOldestEntry();
20872
+ }
20873
+ }
20874
+ clear() {
20875
+ this.entries.clear();
20876
+ [...this.metadata.values()].forEach((value) => value.generating = false);
20877
+ }
20878
+ clearKey(key) {
20879
+ this.metadata.delete(key);
20880
+ this.entries.delete(key);
20881
+ }
20882
+ keyToCacheKey(key) {
20883
+ return JSON.stringify(key);
20884
+ }
20885
+ deleteOldestEntry() {
20886
+ if (this.metadata.size < 1) {
20887
+ return;
20888
+ }
20889
+ const [key] = [...this.metadata.entries()].reduce(
20890
+ ([oldestKey, oldestEntry], [thisKey, entry]) => entry.expiration.getTime() < oldestEntry.expiration.getTime() ? [thisKey, entry] : [oldestKey, oldestEntry]
20891
+ );
20892
+ this.clearKey(key);
20893
+ }
20894
+ generate(key, promise) {
20895
+ const cacheKey = this.keyToCacheKey(key);
20896
+ const existingMetadata = this.metadata.get(cacheKey) || {};
20897
+ this.metadata.set(cacheKey, {
20898
+ ...existingMetadata,
20899
+ generating: true,
20900
+ expiration: new Date(Date.now() + this.timeout)
20901
+ });
20902
+ setTimeout(() => {
20903
+ fork(
20904
+ promise.then((value) => {
20905
+ const metadata = this.metadata.get(cacheKey);
20906
+ const canceled = !(metadata == null ? void 0 : metadata.generating);
20907
+ if (!canceled) {
20908
+ this.set(key, value);
20909
+ }
20910
+ })
20911
+ );
20912
+ }, 0);
20913
+ }
20914
+ }
20915
+ class QueryStore {
20916
+ constructor() {
20917
+ __publicField(this, "queryStoreCache", new StoreCache({
20918
+ capacity: 1e4,
20919
+ timeout: 20 * duration.second
20920
+ }));
20921
+ __publicField(this, "liveQueryStoreCache", new StoreCache({
20922
+ capacity: 1e4,
20923
+ timeout: 200 * duration.millisecond
20924
+ }));
20925
+ }
20926
+ moduleQuery(filter, name, type, start, end, latestOnly = false) {
20927
+ const q = {
20928
+ ...filter,
20929
+ names: [name],
20930
+ types: [type]
20931
+ };
20932
+ const data = this.query(q, start, end, latestOnly);
20933
+ if (data === void 0 || data === "too much data") {
20934
+ return data;
20935
+ }
20936
+ return filterDataByType(data, type);
20937
+ }
20938
+ query(filter, start, end, latestOnly = false) {
20939
+ const q = {
20940
+ ...filter,
20941
+ start: startOfMinute(start).toISOString(),
20942
+ end: latestOnly ? end.toISOString() : addMinutes(roundToNearestMinutes(end), 1).toISOString(),
20943
+ latestOnly
20944
+ };
20945
+ const isLive = end > addSeconds(new Date(), -20);
20946
+ let data;
20947
+ if (isLive) {
20948
+ data = this.liveQueryCache(q);
20949
+ } else {
20950
+ data = this.queryCache(q);
20951
+ }
20952
+ if (!data || data === "too much data") {
20953
+ return data;
20954
+ }
20955
+ if (latestOnly) {
20956
+ return data;
20957
+ }
20958
+ return filterDataByTime(data, start, end);
20959
+ }
20960
+ queryCache(query) {
20961
+ return this.queryStoreCache.get(query, async () => {
20962
+ try {
20963
+ return await Fleet$1.queryTelemetry(query);
20964
+ } catch (error) {
20965
+ throw error;
20364
20966
  }
20365
20967
  });
20366
- console.log(onDemandList);
20367
- const data = await result.json();
20368
- let streamNames = data.items.filter((_) => !disabledList.includes(_)).map((_) => ({ name: _, onDemand: onDemandList.includes(_) }));
20369
- return streamNames;
20370
20968
  }
20371
- async createInterventionRequest(message, interventionType, interventionRequest, tags) {
20372
- const intervention = await fetch(
20373
- `${FORMANT_API_URL}/v1/admin/intervention-requests`,
20374
- {
20375
- method: "POST",
20376
- body: JSON.stringify({
20377
- message,
20378
- interventionType,
20379
- time: new Date().toISOString(),
20380
- deviceId: this.id,
20381
- tags,
20382
- data: interventionRequest
20383
- }),
20384
- headers: {
20385
- "Content-Type": "application/json",
20386
- Authorization: "Bearer " + Authentication.token
20387
- }
20969
+ liveQueryCache(query) {
20970
+ return this.liveQueryStoreCache.get(query, async () => {
20971
+ try {
20972
+ return await Fleet$1.queryTelemetry(query);
20973
+ } catch (error) {
20974
+ throw error;
20388
20975
  }
20389
- );
20390
- const interventionJson = await intervention.json();
20391
- return interventionJson;
20976
+ });
20392
20977
  }
20393
- async addInterventionResponse(interventionId, interventionType, data) {
20978
+ }
20979
+ const queryStore = new QueryStore();
20980
+ class App {
20981
+ static sendAppMessage(message) {
20982
+ window.parent.postMessage(message, "*");
20983
+ }
20984
+ static getCurrentModuleContext() {
20985
+ let urlParams2 = new URLSearchParams("");
20986
+ if (typeof window !== "undefined") {
20987
+ urlParams2 = new URLSearchParams(window.location.search);
20988
+ }
20989
+ const moduleName2 = urlParams2.get("module");
20990
+ return moduleName2;
20991
+ }
20992
+ static async getCurrentModuleConfiguration() {
20993
+ let urlParams2 = new URLSearchParams("");
20994
+ if (typeof window !== "undefined") {
20995
+ urlParams2 = new URLSearchParams(window.location.search);
20996
+ }
20997
+ const configurationId = urlParams2.get("configuration");
20998
+ if (configurationId === null || configurationId.trim() === "") {
20999
+ return void 0;
21000
+ }
20394
21001
  const response = await fetch(
20395
- `${FORMANT_API_URL}/v1/admin/intervention-responses`,
21002
+ `${FORMANT_API_URL}/v1/admin/module-configurations/` + configurationId,
20396
21003
  {
20397
- method: "POST",
20398
- body: JSON.stringify({
20399
- interventionId,
20400
- interventionType,
20401
- data
20402
- }),
20403
21004
  headers: {
20404
21005
  "Content-Type": "application/json",
20405
21006
  Authorization: "Bearer " + Authentication.token
20406
21007
  }
20407
21008
  }
20408
21009
  );
20409
- const interventionResponse = await response.json();
20410
- return interventionResponse;
21010
+ const moduleConfiguration = await response.json();
21011
+ return moduleConfiguration.configuration;
20411
21012
  }
20412
- }
20413
- class PeerDevice {
20414
- constructor(peerUrl) {
20415
- __publicField(this, "rtcClient");
20416
- __publicField(this, "remoteDevicePeerId");
20417
- __publicField(this, "realtimeListeners", []);
20418
- __publicField(this, "id");
20419
- __publicField(this, "handleMessage", (peerId, message) => {
20420
- this.realtimeListeners.forEach((_) => _(peerId, message));
20421
- });
20422
- this.peerUrl = peerUrl;
21013
+ static isModule() {
21014
+ return this.getCurrentModuleContext() !== null;
20423
21015
  }
20424
- async getLatestTelemetry() {
20425
- const data = await fetch(`${this.peerUrl}/telemetry`);
20426
- const telemetry = await data.json();
20427
- const entries = Object.entries(telemetry);
20428
- return entries.map(([stream, latestValue]) => {
20429
- const v = {
20430
- deviceId: this.id,
20431
- streamName: stream,
20432
- streamType: "json",
20433
- currentValue: latestValue,
20434
- currentValueTime: latestValue.timestamp,
20435
- tags: {}
20436
- };
20437
- return v;
21016
+ static goToTime(date) {
21017
+ this.sendAppMessage({
21018
+ type: "go_to_time",
21019
+ time: date.getTime()
20438
21020
  });
20439
21021
  }
20440
- async getDeviceId() {
20441
- let result = await fetch(`${this.peerUrl}/configuration`);
20442
- const cfg = await result.json();
20443
- return cfg.agent_config.id;
21022
+ static goToDevice(deviceId) {
21023
+ this.sendAppMessage({
21024
+ type: "go_to_device",
21025
+ deviceId
21026
+ });
20444
21027
  }
20445
- async getConfiguration() {
20446
- let result = await fetch(`${this.peerUrl}/configuration`);
20447
- const cfg = await result.json();
20448
- return cfg.agent_config.document;
21028
+ static showMessage(message) {
21029
+ this.sendAppMessage({ type: "show_message", message });
20449
21030
  }
20450
- getRealtimeStatus() {
20451
- if (this.rtcClient && this.remoteDevicePeerId) {
20452
- return this.rtcClient.getConnectionStatus(this.remoteDevicePeerId);
20453
- } else {
20454
- throw new Error(`Realtime connection hasn't been started`);
21031
+ static requestModuleData() {
21032
+ const moduleName2 = this.getCurrentModuleContext();
21033
+ if (!moduleName2) {
21034
+ throw new Error("No module context");
20455
21035
  }
21036
+ this.sendAppMessage({
21037
+ type: "request_module_data",
21038
+ module: moduleName2
21039
+ });
20456
21040
  }
20457
- getRealtimePing() {
20458
- if (this.rtcClient && this.remoteDevicePeerId) {
20459
- return this.rtcClient.getPing(this.remoteDevicePeerId);
20460
- } else {
20461
- throw new Error(`Realtime connection hasn't been started`);
21041
+ static setModuleDateTimeRange(beforeInMilliseconds, afterInMilliseconds) {
21042
+ const moduleName2 = this.getCurrentModuleContext();
21043
+ if (!moduleName2) {
21044
+ throw new Error("No module context");
20462
21045
  }
21046
+ this.sendAppMessage({
21047
+ type: "set_module_data_time_range",
21048
+ module: moduleName2,
21049
+ before: beforeInMilliseconds,
21050
+ after: afterInMilliseconds || 0
21051
+ });
20463
21052
  }
20464
- async startRealtimeConnection(sessionType) {
20465
- if (!this.rtcClient) {
20466
- const rtcClient = new dist.exports.RtcClient({
20467
- lanOnlyMode: true,
20468
- receive: this.handleMessage,
20469
- sessionType
20470
- });
20471
- await rtcClient.connectLan(this.peerUrl);
20472
- while (rtcClient.getConnectionStatus(this.peerUrl) !== "connected") {
20473
- await delay(100);
20474
- }
20475
- this.rtcClient = rtcClient;
20476
- } else {
20477
- throw new Error(
20478
- `Already created realtime connection to device ${this.id}`
20479
- );
21053
+ static refreshAuthToken() {
21054
+ const moduleName2 = this.getCurrentModuleContext();
21055
+ if (!moduleName2) {
21056
+ throw new Error("No module context");
20480
21057
  }
21058
+ this.sendAppMessage({
21059
+ type: "refresh_auth_token",
21060
+ module: moduleName2
21061
+ });
20481
21062
  }
20482
- addRealtimeListener(listener) {
20483
- this.realtimeListeners.push(listener);
20484
- }
20485
- removeRealtimeListener(listener) {
20486
- const i = this.realtimeListeners.indexOf(listener);
20487
- if (i === -1) {
20488
- throw new Error("Could not find realtime listener to remove");
21063
+ static sendChannelData(channel, data) {
21064
+ const moduleName2 = this.getCurrentModuleContext();
21065
+ if (!moduleName2) {
21066
+ throw new Error("No module context");
20489
21067
  }
20490
- this.realtimeListeners.splice(i, 1);
21068
+ this.sendAppMessage({
21069
+ type: "send_channel_data",
21070
+ source: moduleName2,
21071
+ channel,
21072
+ data
21073
+ });
20491
21074
  }
20492
- async getRealtimeVideoStreams() {
20493
- var _a, _b, _c;
20494
- const document2 = await this.getConfiguration();
20495
- const streams = [];
20496
- for (const _ of (_a = document2.teleop.hardwareStreams) != null ? _a : []) {
20497
- if (_.rtcStreamType === "h264-video-frame") {
20498
- streams.push({
20499
- name: _.name
20500
- });
20501
- }
21075
+ static setupModuleMenus(menus) {
21076
+ const moduleName2 = this.getCurrentModuleContext();
21077
+ if (!moduleName2) {
21078
+ throw new Error("No module context");
20502
21079
  }
20503
- for (const _ of (_b = document2.teleop.rosStreams) != null ? _b : []) {
20504
- if (_.topicType == "formant/H264VideoFrame") {
20505
- streams.push({
20506
- name: _.topicName
20507
- });
21080
+ this.sendAppMessage({
21081
+ type: "setup_module_menus",
21082
+ module: moduleName2,
21083
+ menus
21084
+ });
21085
+ }
21086
+ static addMenuListener(handler) {
21087
+ window.addEventListener("message", (event) => {
21088
+ const msg = event.data;
21089
+ if (msg.type === "module_menu_item_clicked") {
21090
+ handler(msg.menu);
20508
21091
  }
20509
- }
20510
- for (const _ of (_c = document2.teleop.customStreams) != null ? _c : []) {
20511
- if (_.rtcStreamType === "h264-video-frame") {
20512
- streams.push({
20513
- name: _.name
20514
- });
21092
+ });
21093
+ }
21094
+ static addAccessTokenRefreshListener(handler) {
21095
+ window.addEventListener("message", (event) => {
21096
+ const msg = event.data;
21097
+ if (msg.type === "auth_token") {
21098
+ handler(msg.token);
20515
21099
  }
20516
- }
20517
- return streams;
21100
+ });
20518
21101
  }
20519
- async getRealtimeManipulators() {
20520
- var _a;
20521
- const document2 = await this.getConfiguration();
20522
- const manipulators = [];
20523
- for (const _ of (_a = document2.teleop.rosStreams) != null ? _a : []) {
20524
- if (_.topicType == "sensor_msgs/JointState") {
20525
- manipulators.push(
20526
- new Manipulator(this, {
20527
- currentJointStateStream: { name: _.topicName },
20528
- plannedJointStateStream: _.plannedTopic ? { name: _.plannedTopic } : void 0,
20529
- planValidStream: _.planValidTopic ? { name: _.planValidTopic } : void 0,
20530
- endEffectorStream: _.endEffectorTopic ? { name: _.endEffectorTopic } : void 0,
20531
- endEffectorLinkName: _.endEffectorLinkName,
20532
- baseReferenceFrame: _.baseReferenceFrame,
20533
- localFrame: _.localFrame
20534
- })
21102
+ static addModuleDataListener(handler) {
21103
+ const moduleName2 = this.getCurrentModuleContext();
21104
+ if (moduleName2) {
21105
+ this.sendAppMessage({ type: "request_module_data", module: moduleName2 });
21106
+ }
21107
+ window.addEventListener("message", (event) => {
21108
+ const msg = event.data;
21109
+ if (msg.type === "module_data") {
21110
+ handler({
21111
+ streams: msg.streams,
21112
+ time: msg.time,
21113
+ queryRange: msg.queryRange
21114
+ });
21115
+ }
21116
+ });
21117
+ }
21118
+ static addStreamListener(streamName, streamType, handler) {
21119
+ const listener = (event) => {
21120
+ const msg = event.data;
21121
+ if (msg.type === "module_data") {
21122
+ const { start, end } = msg.queryRange;
21123
+ handler(
21124
+ queryStore.moduleQuery(
21125
+ {},
21126
+ streamName,
21127
+ streamType,
21128
+ new Date(start),
21129
+ new Date(end),
21130
+ false
21131
+ )
20535
21132
  );
20536
21133
  }
20537
- }
20538
- return manipulators;
21134
+ };
21135
+ window.addEventListener("message", listener);
21136
+ return () => window.removeEventListener("message", listener);
20539
21137
  }
20540
- async startListeningToRealtimeVideo(stream) {
20541
- const client = defined(
20542
- this.rtcClient,
20543
- "Realtime connection has not been started"
20544
- );
20545
- const devicePeer = await this.getRemotePeer();
20546
- client.controlRemoteStream(defined(devicePeer).id, {
20547
- streamName: stream.name,
20548
- enable: true,
20549
- pipeline: "rtc"
21138
+ static addModuleConfigurationListener(handler) {
21139
+ window.addEventListener("message", (event) => {
21140
+ const msg = event.data;
21141
+ if (msg.type === "module_configuration") {
21142
+ handler(msg);
21143
+ }
20550
21144
  });
20551
21145
  }
20552
- async stopListeningToRealtimeVideo(stream) {
20553
- const client = defined(
20554
- this.rtcClient,
20555
- "Realtime connection has not been started"
20556
- );
20557
- const devicePeer = await this.getRemotePeer();
20558
- client.controlRemoteStream(defined(devicePeer).id, {
20559
- streamName: stream.name,
20560
- enable: false,
20561
- pipeline: "rtc"
21146
+ static addChannelDataListener(channel, handler) {
21147
+ window.addEventListener("message", (event) => {
21148
+ const msg = event.data;
21149
+ if (msg.type === "channel_data" && msg.channel === channel) {
21150
+ handler({
21151
+ source: msg.source,
21152
+ data: msg.data
21153
+ });
21154
+ }
20562
21155
  });
20563
21156
  }
20564
- async startListeningToRealtimeDataStream(stream) {
20565
- const client = defined(
20566
- this.rtcClient,
20567
- "Realtime connection has not been started"
20568
- );
20569
- const devicePeer = await this.getRemotePeer();
20570
- client.controlRemoteStream(defined(devicePeer).id, {
20571
- streamName: stream.name,
20572
- enable: true,
20573
- pipeline: "rtc"
21157
+ static requestOverviewDevices(handler) {
21158
+ this.sendAppMessage({ type: "request_devices" });
21159
+ window.addEventListener("message", (event) => {
21160
+ const msg = event.data;
21161
+ handler(msg);
20574
21162
  });
20575
21163
  }
20576
- async stopListeningToRealtimeDataStream(stream) {
20577
- const client = defined(
20578
- this.rtcClient,
20579
- "Realtime connection has not been started"
20580
- );
20581
- const devicePeer = await this.getRemotePeer();
20582
- client.controlRemoteStream(defined(devicePeer).id, {
20583
- streamName: stream.name,
20584
- enable: false,
20585
- pipeline: "rtc"
20586
- });
21164
+ }
21165
+ const _Authentication = class {
21166
+ static async login(email, password) {
21167
+ try {
21168
+ const result = await fetch(`${FORMANT_API_URL}/v1/admin/auth/login`, {
21169
+ method: "POST",
21170
+ body: JSON.stringify({ email, password }),
21171
+ headers: {
21172
+ "Content-Type": "application/json"
21173
+ }
21174
+ });
21175
+ const auth = await result.json();
21176
+ if (result.status !== 200) {
21177
+ throw new Error(auth.message);
21178
+ }
21179
+ await _Authentication.loginWithToken(
21180
+ auth.authentication.accessToken,
21181
+ auth.authentication.refreshToken
21182
+ );
21183
+ return auth.authentication;
21184
+ } catch (e) {
21185
+ _Authentication.waitingForAuth.forEach((_) => _(false));
21186
+ _Authentication.waitingForAuth = [];
21187
+ return Promise.reject(e);
21188
+ }
20587
21189
  }
20588
- async enableRealtimeTelemetryPriorityIngestion(streamName) {
20589
- const client = defined(
20590
- this.rtcClient,
20591
- "Realtime connection has not been started"
20592
- );
20593
- const devicePeer = await this.getRemotePeer();
20594
- client.controlRemoteStream(defined(devicePeer).id, {
20595
- streamName,
20596
- enablePriorityUpload: true,
20597
- pipeline: "telemetry"
20598
- });
21190
+ static async loginWithToken(token, refreshToken) {
21191
+ const tokenData = JSON.parse(atob(token.split(".")[1]));
21192
+ try {
21193
+ let userId;
21194
+ _Authentication.isShareToken = tokenData["formant:claims"] && tokenData["formant:claims"].type == "share";
21195
+ if (tokenData["formant:claims"]) {
21196
+ _Authentication.currentOrganization = tokenData["formant:claims"].organizationId;
21197
+ }
21198
+ if (tokenData["custom:organization_id"]) {
21199
+ _Authentication.currentOrganization = tokenData["custom:organization_id"];
21200
+ }
21201
+ if (!_Authentication.isShareToken) {
21202
+ userId = tokenData.sub;
21203
+ }
21204
+ if (tokenData["formant:claims"] && tokenData["formant:claims"].userId) {
21205
+ userId = tokenData["formant:claims"].userId;
21206
+ }
21207
+ if (userId) {
21208
+ const result = await fetch(
21209
+ `${FORMANT_API_URL}/v1/admin/users/${userId}`,
21210
+ {
21211
+ method: "GET",
21212
+ headers: {
21213
+ "Content-Type": "application/json",
21214
+ Authorization: "Bearer " + token
21215
+ }
21216
+ }
21217
+ );
21218
+ const data = await result.json();
21219
+ if (result.status !== 200) {
21220
+ throw new Error(data.message);
21221
+ }
21222
+ _Authentication.currentUser = data;
21223
+ }
21224
+ _Authentication.token = token;
21225
+ _Authentication.waitingForAuth.forEach((_) => _(true));
21226
+ } catch (e) {
21227
+ console.error(e);
21228
+ _Authentication.waitingForAuth.forEach((_) => _(false));
21229
+ }
21230
+ _Authentication.waitingForAuth = [];
21231
+ if (refreshToken) {
21232
+ _Authentication.refreshToken = refreshToken;
21233
+ setInterval(async () => {
21234
+ if (_Authentication.refreshToken) {
21235
+ const result = await fetch(
21236
+ `${FORMANT_API_URL}/v1/admin/auth/refresh`,
21237
+ {
21238
+ method: "POST",
21239
+ headers: {
21240
+ "Content-Type": "application/json"
21241
+ },
21242
+ body: JSON.stringify({
21243
+ refreshToken: _Authentication.refreshToken
21244
+ })
21245
+ }
21246
+ );
21247
+ const refreshData = await result.json();
21248
+ _Authentication.token = refreshData.authentication.accessToken;
21249
+ }
21250
+ }, 1e3 * 60 * 60);
21251
+ }
20599
21252
  }
20600
- async disableRealtimeTelemetryPriorityIngestion(streamName) {
20601
- const client = defined(
20602
- this.rtcClient,
20603
- "Realtime connection has not been started"
20604
- );
20605
- const devicePeer = await this.getRemotePeer();
20606
- client.controlRemoteStream(defined(devicePeer).id, {
20607
- streamName,
20608
- enablePriorityUpload: false,
20609
- pipeline: "telemetry"
20610
- });
21253
+ static isAuthenticated() {
21254
+ return _Authentication.token !== void 0;
20611
21255
  }
20612
- async getRemotePeer() {
20613
- return {
20614
- id: this.peerUrl,
20615
- organizationId: "",
20616
- deviceId: this.id,
20617
- capabilities: [],
20618
- capabilitySet: {}
20619
- };
21256
+ static getCurrentUser() {
21257
+ return _Authentication.currentUser;
20620
21258
  }
20621
- async stopRealtimeConnection() {
20622
- if (this.rtcClient) {
20623
- await this.rtcClient.disconnect(this.id);
21259
+ static async waitTilAuthenticated() {
21260
+ if (_Authentication.token !== void 0) {
21261
+ return true;
20624
21262
  } else {
20625
- throw new Error(`Realtime connection hasn't been started for ${this.id}`);
21263
+ return new Promise((resolve) => {
21264
+ _Authentication.waitingForAuth.push(function(result) {
21265
+ resolve(result);
21266
+ });
21267
+ });
20626
21268
  }
20627
21269
  }
20628
- async createCustomDataChannel(channelName, rtcConfig) {
20629
- const client = defined(
20630
- this.rtcClient,
20631
- "Realtime connection has not been started"
20632
- );
20633
- const devicePeer = await this.getRemotePeer();
20634
- const p = await new Promise((resolve) => {
20635
- client.createCustomDataChannel(
20636
- defined(devicePeer).id,
20637
- channelName,
20638
- {
20639
- ordered: true,
20640
- ...rtcConfig
20641
- },
20642
- false,
20643
- (_peerId, channel) => {
20644
- const dataChannel = new DataChannel(channel);
20645
- resolve(dataChannel);
20646
- }
20647
- );
21270
+ static async listenForRefresh() {
21271
+ App.addAccessTokenRefreshListener((token) => {
21272
+ this.loginWithToken(token);
20648
21273
  });
20649
- await p.waitTilReady();
20650
- return p;
20651
- }
20652
- createCustomRequestDataChannel(channelName, timeout = 3e3) {
20653
- return new TextRequestDataChannel(this, channelName, timeout);
20654
- }
20655
- createCustomBinaryRequestDataChannel(channelName, timeout = 3e3) {
20656
- return new BinaryRequestDataChannel(this, channelName, timeout);
21274
+ setInterval(async () => {
21275
+ App.refreshAuthToken();
21276
+ }, 1e3 * 60 * 60);
20657
21277
  }
20658
- }
21278
+ };
21279
+ let Authentication = _Authentication;
21280
+ __publicField(Authentication, "token");
21281
+ __publicField(Authentication, "refreshToken");
21282
+ __publicField(Authentication, "currentUser");
21283
+ __publicField(Authentication, "currentOrganization");
21284
+ __publicField(Authentication, "isShareToken", false);
21285
+ __publicField(Authentication, "defaultDeviceId");
21286
+ __publicField(Authentication, "waitingForAuth", []);
20659
21287
  const _Fleet = class {
20660
21288
  static async setDefaultDevice(deviceId) {
20661
21289
  _Fleet.defaultDeviceId = deviceId;
@@ -21159,9 +21787,6 @@ function combineNumericSetAggregates(e1, e2) {
21159
21787
  function stringToArrayBuffer(input) {
21160
21788
  return Uint8Array.from(atob(input), (_) => _.charCodeAt(0));
21161
21789
  }
21162
- function fork(_) {
21163
- return void 0;
21164
- }
21165
21790
  function browser() {
21166
21791
  const { userAgent } = navigator;
21167
21792
  if (userAgent.includes("Firefox/")) {