UNPKG

@wandelbots/nova-js

Version:

Official JS client for the Wandelbots API

1,452 lines (1,437 loc) 76 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/lib/v2/index.ts var v2_exports = {}; __export(v2_exports, { ConnectedMotionGroup: () => ConnectedMotionGroup, JoggerConnection: () => JoggerConnection, MotionStreamConnection: () => MotionStreamConnection, NovaCellAPIClient: () => NovaCellAPIClient, NovaClient: () => NovaClient, ProgramState: () => ProgramState, ProgramStateConnection: () => ProgramStateConnection }); module.exports = __toCommonJS(v2_exports); __reExport(v2_exports, require("@wandelbots/nova-api/v2"), module.exports); // src/lib/v2/ConnectedMotionGroup.ts var import_axios = require("axios"); var import_mobx = require("mobx"); // src/lib/converters.ts function tryParseJson(json) { try { return JSON.parse(json); } catch (e) { return void 0; } } // src/lib/v2/motionStateUpdate.ts function jointValuesEqual(oldJointValues, newJointValues, changeDeltaThreshold) { if (newJointValues.length !== oldJointValues.length) { return true; } for (let jointIndex = 0; jointIndex < newJointValues.length; jointIndex++) { if (Math.abs(newJointValues[jointIndex] - oldJointValues[jointIndex]) > changeDeltaThreshold) { return false; } } return true; } function tcpPoseEqual(oldTcp, newTcp, changeDeltaThreshold) { if (oldTcp === void 0 && newTcp || oldTcp && newTcp === void 0) { return false; } if (oldTcp === void 0 || newTcp === void 0) { return true; } let changedDelta = 0; changedDelta += Math.abs(oldTcp.orientation[0] - newTcp.orientation[0]); changedDelta += Math.abs(oldTcp.orientation[1] - newTcp.orientation[1]); changedDelta += Math.abs(oldTcp.orientation[2] - newTcp.orientation[2]); changedDelta += Math.abs(oldTcp.position[0] - newTcp.position[0]); changedDelta += Math.abs(oldTcp.position[1] - newTcp.position[1]); changedDelta += Math.abs(oldTcp.position[2] - newTcp.position[2]); if (changedDelta > changeDeltaThreshold) { return false; } return oldTcp.coordinate_system === newTcp.coordinate_system && oldTcp.tcp === newTcp.tcp; } // src/lib/v2/ConnectedMotionGroup.ts var MOTION_DELTA_THRESHOLD = 1e-4; var ConnectedMotionGroup = class _ConnectedMotionGroup { constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup) { this.nova = nova; this.controller = controller; this.motionGroup = motionGroup; this.initialMotionState = initialMotionState; this.motionStateSocket = motionStateSocket; this.isVirtual = isVirtual; this.tcps = tcps; this.motionGroupSpecification = motionGroupSpecification; this.safetySetup = safetySetup; this.connectedJoggingCartesianSocket = null; this.connectedJoggingJointsSocket = null; // tmp this.joggingVelocity = 10; this.rapidlyChangingMotionState = initialMotionState; motionStateSocket.addEventListener("message", (event) => { var _a; const motionStateResponse = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result; if (!motionStateResponse) { throw new Error( `Failed to get motion state for ${this.motionGroupId}: ${event.data}` ); } if (!jointValuesEqual( this.rapidlyChangingMotionState.joint_position.joints, motionStateResponse.joint_position.joints, MOTION_DELTA_THRESHOLD )) { (0, import_mobx.runInAction)(() => { this.rapidlyChangingMotionState = motionStateResponse; }); } if (!tcpPoseEqual( this.rapidlyChangingMotionState.tcp_pose, motionStateResponse.tcp_pose, MOTION_DELTA_THRESHOLD )) { (0, import_mobx.runInAction)(() => { this.rapidlyChangingMotionState.tcp_pose = motionStateResponse.tcp_pose; }); } }); (0, import_mobx.makeAutoObservable)(this); } static connect(nova, motionGroupId, controllers) { return __async(this, null, function* () { var _a; const [_motionGroupIndex, controllerId] = motionGroupId.split("@"); const controller = controllers.find((c) => c.controller === controllerId); const motionGroup = controller == null ? void 0 : controller.motion_groups.find( (mg) => mg.motion_group === motionGroupId ); if (!controller || !motionGroup) { throw new Error( `Controller ${controllerId} or motion group ${motionGroupId} not found` ); } const motionStateSocket = nova.openReconnectingWebsocket( `/motion-groups/${motionGroupId}/state-stream` ); const firstMessage = yield motionStateSocket.firstMessage(); const initialMotionState = (_a = tryParseJson(firstMessage.data)) == null ? void 0 : _a.result; if (!initialMotionState) { throw new Error( `Unable to parse initial motion state message ${firstMessage.data}` ); } console.log( `Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state: `, initialMotionState ); let isVirtual = false; try { const opMode = yield nova.api.virtualRobotMode.getOperationMode(controllerId); if (opMode) isVirtual = true; } catch (err) { if (err instanceof import_axios.AxiosError) { console.log( `Received ${err.status} from getOperationMode, concluding that ${controllerId} is physical` ); } else { throw err; } } const { tcps } = yield nova.api.motionGroupInfos.listTcps(motionGroupId); const motionGroupSpecification = yield nova.api.motionGroupInfos.getMotionGroupSpecification(motionGroupId); const safetySetup = yield nova.api.motionGroupInfos.getSafetySetup(motionGroupId); return new _ConnectedMotionGroup( nova, controller, motionGroup, initialMotionState, motionStateSocket, isVirtual, tcps, motionGroupSpecification, safetySetup ); }); } get motionGroupId() { return this.motionGroup.motion_group; } get controllerId() { return this.controller.controller; } get modelFromController() { return this.motionGroup.model_from_controller; } get wandelscriptIdentifier() { const num = this.motionGroupId.split("@")[0]; return `${this.controllerId.replaceAll("-", "_")}_${num}`; } /** Jogging velocity in radians for rotation and joint movement */ get joggingVelocityRads() { return this.joggingVelocity * Math.PI / 180; } get joints() { return this.initialMotionState.joint_position.joints.map((_, i) => { return { index: i }; }); } get dhParameters() { return this.motionGroupSpecification.dh_parameters; } get safetyZones() { return this.safetySetup.safety_zones; } dispose() { this.motionStateSocket.close(); if (this.connectedJoggingCartesianSocket) this.connectedJoggingCartesianSocket.close(); if (this.connectedJoggingJointsSocket) this.connectedJoggingJointsSocket.close(); } setJoggingVelocity(velocity) { this.joggingVelocity = velocity; } }; // src/lib/v2/vectorUtils.ts var THREE = __toESM(require("three"), 1); function axisToIndex(axis) { switch (axis) { case "x": return 0; case "y": return 1; case "z": return 2; } } function vector3ToArray(vector) { return [vector.x, vector.y, vector.z]; } // src/lib/v2/JoggerConnection.ts var JoggerConnection = class _JoggerConnection { constructor(nova, cell, motionGroupId, motionGroupState, opts) { this.nova = nova; this.cell = cell; this.motionGroupId = motionGroupId; this.motionGroupState = motionGroupState; this.opts = opts; // Currently a separate websocket is needed for each mode, pester API people // to merge these for simplicity this.joggingWebsocket = null; this.lastVelocityRequest = null; this.lastResponse = null; this.joggingWebsocket = nova.openReconnectingWebsocket( `/cells/${cell}/execution/jogging` ); this.joggingWebsocket.addEventListener("message", (ev) => { const data = tryParseJson(ev.data); if (data && "error" in data) { if (this.opts.onError) { this.opts.onError(ev.data); } else { throw new Error(ev.data); } } }); this.joggingWebsocket.addEventListener("message", (ev) => { const data = tryParseJson(ev.data); if (data && "error" in data) { if (this.opts.onError) { this.opts.onError(ev.data); } else { throw new Error(ev.data); } } }); } static open(nova, cell, motionGroupId, opts) { return __async(this, null, function* () { const motionGroupState = yield nova.api.motionGroupInfos.getCurrentMotionGroupState(motionGroupId); return new _JoggerConnection( nova, cell, motionGroupId, motionGroupState, opts ); }); } get jointCount() { var _a; return (_a = this.motionGroupState.joint_current) == null ? void 0 : _a.joints.length; } get activeWebsocket() { return this.joggingWebsocket; } stop() { return __async(this, null, function* () { var _a, _b; if (!this.joggingWebsocket) { return; } if (((_a = this.lastVelocityRequest) == null ? void 0 : _a.message_type) === "JointVelocityRequest") { this.joggingWebsocket.sendJson({ message_type: "JointVelocityRequest", velocity: { joints: Array.from(new Array(this.jointCount).keys()).map(() => 0) } }); } if (((_b = this.lastVelocityRequest) == null ? void 0 : _b.message_type) === "TcpVelocityRequest") { this.joggingWebsocket.sendJson({ message_type: "TcpVelocityRequest", rotation: [0, 0, 0], translation: [0, 0, 0] }); } }); } dispose() { if (this.joggingWebsocket) { this.joggingWebsocket.dispose(); } } /** * Start rotation of a single robot joint at the specified velocity */ startJointRotation(_0) { return __async(this, arguments, function* ({ joint, velocityRadsPerSec }) { if (!this.joggingWebsocket) { throw new Error( "Joint jogging websocket not connected. Wait for reconnect or open new jogging connection" ); } const jointVelocities = new Array(this.jointCount).fill(0); jointVelocities[joint] = velocityRadsPerSec; this.joggingWebsocket.sendJson({ message_type: "JointVelocityRequest", velocity: { joints: jointVelocities } }); }); } /** * Start the TCP moving along a specified axis at a given velocity */ startTCPTranslation(_0) { return __async(this, arguments, function* ({ axis, velocityMmPerSec, useToolCoordinateSystem }) { if (!this.joggingWebsocket) { throw new Error( "Cartesian jogging websocket not connected. Wait for reconnect or open new jogging connection" ); } const joggingVector = [0, 0, 0]; joggingVector[axisToIndex(axis)] = velocityMmPerSec; this.joggingWebsocket.sendJson({ message_type: "TcpVelocityRequest", translation: joggingVector, rotation: [0, 0, 0], use_tool_coordinate_system: useToolCoordinateSystem }); }); } /** * Start the TCP rotating around a specified axis at a given velocity */ startTCPRotation(_0) { return __async(this, arguments, function* ({ axis, velocityRadsPerSec, useToolCoordinateSystem }) { if (!this.joggingWebsocket) { throw new Error( "Cartesian jogging websocket not connected. Wait for reconnect or open new jogging connection" ); } const joggingVector = [0, 0, 0]; joggingVector[axisToIndex(axis)] = velocityRadsPerSec; this.joggingWebsocket.sendJson({ message_type: "TcpVelocityRequest", rotation: joggingVector, translation: [0, 0, 0], use_tool_coordinate_system: useToolCoordinateSystem }); }); } }; // src/lib/v2/MotionStreamConnection.ts var import_mobx2 = require("mobx"); var THREE2 = __toESM(require("three"), 1); var MOTION_DELTA_THRESHOLD2 = 1e-4; function unwrapRotationVector(newRotationVectorApi, currentRotationVectorApi) { const currentRotationVector = new THREE2.Vector3( currentRotationVectorApi[0], currentRotationVectorApi[1], currentRotationVectorApi[2] ); const newRotationVector = new THREE2.Vector3( newRotationVectorApi[0], newRotationVectorApi[1], newRotationVectorApi[2] ); const currentAngle = currentRotationVector.length(); const currentAxis = currentRotationVector.normalize(); let newAngle = newRotationVector.length(); let newAxis = newRotationVector.normalize(); if (newAxis.dot(currentAxis) < 0) { newAngle = -newAngle; newAxis = newAxis.multiplyScalar(-1); } let angleDifference = newAngle - currentAngle; angleDifference -= 2 * Math.PI * Math.floor((angleDifference + Math.PI) / (2 * Math.PI)); newAngle = currentAngle + angleDifference; return vector3ToArray(newAxis.multiplyScalar(newAngle)); } var MotionStreamConnection = class _MotionStreamConnection { constructor(nova, controller, motionGroup, initialMotionState, motionStateSocket) { this.nova = nova; this.controller = controller; this.motionGroup = motionGroup; this.initialMotionState = initialMotionState; this.motionStateSocket = motionStateSocket; this.rapidlyChangingMotionState = initialMotionState; motionStateSocket.addEventListener("message", (event) => { var _a; const motionState = (_a = tryParseJson(event.data)) == null ? void 0 : _a.result; if (!motionState) { throw new Error( `Failed to get motion state for ${this.motionGroupId}: ${event.data}` ); } if (!jointValuesEqual( this.rapidlyChangingMotionState.joint_position.joints, motionState.joint_position.joints, MOTION_DELTA_THRESHOLD2 )) { (0, import_mobx2.runInAction)(() => { this.rapidlyChangingMotionState = motionState; }); } if (!tcpPoseEqual( this.rapidlyChangingMotionState.tcp_pose, motionState.tcp_pose, MOTION_DELTA_THRESHOLD2 )) { (0, import_mobx2.runInAction)(() => { if (this.rapidlyChangingMotionState.tcp_pose == void 0) { this.rapidlyChangingMotionState.tcp_pose = motionState.tcp_pose; } else { this.rapidlyChangingMotionState.tcp_pose = { position: motionState.tcp_pose.position, orientation: unwrapRotationVector( motionState.tcp_pose.orientation, this.rapidlyChangingMotionState.tcp_pose.orientation ), tcp: motionState.tcp_pose.tcp, coordinate_system: motionState.tcp_pose.coordinate_system }; } }); } }); (0, import_mobx2.makeAutoObservable)(this); } static open(nova, motionGroupId) { return __async(this, null, function* () { var _a; const { controllers } = yield nova.api.controller.listControllers(); const [_motionGroupIndex, controllerId] = motionGroupId.split("@"); const controller = controllers.find((c) => c.controller === controllerId); const motionGroup = controller == null ? void 0 : controller.motion_groups.find( (mg) => mg.motion_group === motionGroupId ); if (!controller || !motionGroup) { throw new Error( `Controller ${controllerId} or motion group ${motionGroupId} not found` ); } const motionStateSocket = nova.openReconnectingWebsocket( `/motion-groups/${motionGroupId}/state-stream` ); const firstMessage = yield motionStateSocket.firstMessage(); console.log("got first message", firstMessage); const initialMotionState = (_a = tryParseJson(firstMessage.data)) == null ? void 0 : _a.result; if (!initialMotionState) { throw new Error( `Unable to parse initial motion state message ${firstMessage.data}` ); } console.log( `Connected motion state websocket to motion group ${motionGroup.motion_group}. Initial state: `, initialMotionState ); return new _MotionStreamConnection( nova, controller, motionGroup, initialMotionState, motionStateSocket ); }); } get motionGroupId() { return this.motionGroup.motion_group; } get controllerId() { return this.controller.controller; } get modelFromController() { return this.motionGroup.model_from_controller; } get wandelscriptIdentifier() { const num = this.motionGroupId.split("@")[0]; return `${this.controllerId.replaceAll("-", "_")}_${num}`; } get joints() { return this.initialMotionState.joint_position.joints.map((_, i) => { return { index: i }; }); } dispose() { this.motionStateSocket.close(); } }; // src/lib/v2/NovaCellAPIClient.ts var import_v2 = require("@wandelbots/nova-api/v2"); var import_axios2 = __toESM(require("axios"), 1); var NovaCellAPIClient = class { constructor(cellId, opts) { this.cellId = cellId; this.opts = opts; this.system = this.withUnwrappedResponsesOnly(import_v2.SystemApi); this.cell = this.withUnwrappedResponsesOnly(import_v2.CellApi); this.motionGroup = this.withCellId(import_v2.MotionGroupApi); this.motionGroupInfos = this.withCellId(import_v2.MotionGroupInfoApi); this.controller = this.withCellId(import_v2.ControllerApi); this.program = this.withCellId(import_v2.ProgramApi); this.programOperator = this.withCellId(import_v2.ProgramOperatorApi); this.controllerIOs = this.withCellId(import_v2.ControllerInputsOutputsApi); this.motionGroupKinematic = this.withCellId(import_v2.MotionGroupKinematicsApi); this.trajectoryPlanning = this.withCellId(import_v2.TrajectoryPlanningApi); this.trajectoryExecution = this.withCellId(import_v2.TrajectoryExecutionApi); this.coordinateSystems = this.withCellId(import_v2.CoordinateSystemsApi); this.application = this.withCellId(import_v2.ApplicationApi); this.applicationGlobal = this.withUnwrappedResponsesOnly(import_v2.ApplicationApi); this.jogging = this.withCellId(import_v2.JoggingApi); this.virtualRobot = this.withCellId(import_v2.VirtualRobotApi); this.virtualRobotSetup = this.withCellId(import_v2.VirtualRobotSetupApi); this.virtualRobotMode = this.withCellId(import_v2.VirtualRobotModeApi); this.virtualRobotBehavior = this.withCellId(import_v2.VirtualRobotBehaviorApi); this.storeObject = this.withCellId(import_v2.StoreObjectApi); this.storeCollisionComponents = this.withCellId( import_v2.StoreCollisionComponentsApi ); this.storeCollisionScenes = this.withCellId(import_v2.StoreCollisionScenesApi); } /** * Some TypeScript sorcery which alters the API class methods so you don't * have to pass the cell id to every single one, and de-encapsulates the * response data */ withCellId(ApiConstructor) { var _a, _b; const apiClient = new ApiConstructor( __spreadProps(__spreadValues({}, this.opts), { isJsonMime: (mime) => { return mime === "application/json"; } }), (_a = this.opts.basePath) != null ? _a : "", (_b = this.opts.axiosInstance) != null ? _b : import_axios2.default.create() ); for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) { if (key !== "constructor" && typeof apiClient[key] === "function") { const originalFunction = apiClient[key]; apiClient[key] = (...args) => { return originalFunction.apply(apiClient, [this.cellId, ...args]).then((res) => res.data); }; } } return apiClient; } /** * As withCellId, but only does the response unwrapping */ withUnwrappedResponsesOnly(ApiConstructor) { var _a, _b; const apiClient = new ApiConstructor( __spreadProps(__spreadValues({}, this.opts), { isJsonMime: (mime) => { return mime === "application/json"; } }), (_a = this.opts.basePath) != null ? _a : "", (_b = this.opts.axiosInstance) != null ? _b : import_axios2.default.create() ); for (const key of Reflect.ownKeys(Reflect.getPrototypeOf(apiClient))) { if (key !== "constructor" && typeof apiClient[key] === "function") { const originalFunction = apiClient[key]; apiClient[key] = (...args) => { return originalFunction.apply(apiClient, args).then((res) => res.data); }; } } return apiClient; } }; // src/lib/v2/NovaClient.ts var import_axios4 = __toESM(require("axios"), 1); var import_url_join = __toESM(require("url-join"), 1); // src/LoginWithAuth0.ts var DOMAIN_SUFFIX = "wandelbots.io"; var auth0ConfigMap = { dev: { domain: `https://auth.portal.dev.${DOMAIN_SUFFIX}`, clientId: "fLbJD0RLp5r2Dpucm5j8BjwMR6Hunfha" }, stg: { domain: `https://auth.portal.stg.${DOMAIN_SUFFIX}`, clientId: "joVDeD9e786WzFNSGCqoVq7HNkWt5j6s" }, prod: { domain: `https://auth.portal.${DOMAIN_SUFFIX}`, clientId: "J7WJUi38xVQdJAEBNRT9Xw1b0fXDb4J2" } }; var getAuth0Config = (instanceUrl) => { if (instanceUrl.includes(`dev.${DOMAIN_SUFFIX}`)) return auth0ConfigMap.dev; if (instanceUrl.includes(`stg.${DOMAIN_SUFFIX}`)) return auth0ConfigMap.stg; if (instanceUrl.includes(DOMAIN_SUFFIX)) return auth0ConfigMap.prod; throw new Error( "Unsupported instance URL. Cannot determine Auth0 configuration." ); }; var loginWithAuth0 = (instanceUrl) => __async(void 0, null, function* () { var _a; if (typeof window === "undefined") { throw new Error( `Access token must be set to use NovaClient when not in a browser environment.` ); } const auth0Config = getAuth0Config(instanceUrl); if (new URL(instanceUrl).origin === window.location.origin) { window.location.reload(); throw new Error( "Failed to reload page to get auth details, please refresh manually" ); } const { Auth0Client } = yield import("@auth0/auth0-spa-js"); const auth0Client = new Auth0Client({ domain: auth0Config.domain, clientId: (_a = auth0Config.clientId) != null ? _a : "", useRefreshTokens: false, authorizationParams: { audience: "nova-api", redirect_uri: window.location.origin } }); if (window.location.search.includes("code=") && window.location.search.includes("state=")) { const { appState } = yield auth0Client.handleRedirectCallback(); window.history.replaceState( {}, document.title, (appState == null ? void 0 : appState.returnTo) || window.location.pathname ); } else { yield auth0Client.loginWithRedirect(); } const accessToken = yield auth0Client.getTokenSilently(); return accessToken; }); // src/lib/AutoReconnectingWebsocket.ts var import_reconnecting_websocket = __toESM(require("reconnecting-websocket"), 1); var AutoReconnectingWebsocket = class extends import_reconnecting_websocket.default { constructor(targetUrl, opts = {}) { console.log("Opening websocket to", targetUrl); super(() => this.targetUrl || targetUrl, void 0, { startClosed: true }); this.opts = opts; this.disposed = false; Object.defineProperty(this, "url", { get() { return this.targetUrl; } }); this.targetUrl = targetUrl; this.addEventListener("open", () => { console.log(`Websocket to ${this.url} opened`); }); this.addEventListener("message", (ev) => { if (!this.receivedFirstMessage) { this.receivedFirstMessage = ev; } }); this.addEventListener("close", () => { console.log(`Websocket to ${this.url} closed`); }); const origReconnect = this.reconnect; this.reconnect = () => { if (this.opts.mock) { this.opts.mock.handleWebsocketConnection(this); } else { origReconnect.apply(this); } }; this.reconnect(); } changeUrl(targetUrl) { this.receivedFirstMessage = void 0; this.targetUrl = targetUrl; this.reconnect(); } sendJson(data) { if (this.opts.mock) { this.opts.mock.handleWebsocketMessage(this, JSON.stringify(data)); } else { this.send(JSON.stringify(data)); } } /** * Permanently close this websocket and indicate that * this object should not be used again. **/ dispose() { this.close(); this.disposed = true; if (this.opts.onDispose) { this.opts.onDispose(); } } /** * Returns a promise that resolves once the websocket * is in the OPEN state. */ opened() { return __async(this, null, function* () { return new Promise((resolve, reject) => { if (this.readyState === WebSocket.OPEN) { resolve(); } else { this.addEventListener("open", () => resolve()); this.addEventListener("error", reject); } }); }); } /** * Returns a promise that resolves once the websocket * is in the CLOSED state. */ closed() { return __async(this, null, function* () { return new Promise((resolve, reject) => { if (this.readyState === WebSocket.CLOSED) { resolve(); } else { this.addEventListener("close", () => resolve()); this.addEventListener("error", reject); } }); }); } /** * Returns a promise that resolves when the first message * is received from the websocket. Resolves immediately if * the first message has already been received. */ firstMessage() { return __async(this, null, function* () { if (this.receivedFirstMessage) { return this.receivedFirstMessage; } return new Promise((resolve, reject) => { const onMessage = (ev) => { this.receivedFirstMessage = ev; this.removeEventListener("message", onMessage); this.removeEventListener("error", onError); resolve(ev); }; const onError = (ev) => { this.removeEventListener("message", onMessage); this.removeEventListener("error", onError); reject(ev); }; this.addEventListener("message", onMessage); this.addEventListener("error", onError); }); }); } /** * Returns a promise that resolves when the next message * is received from the websocket. */ nextMessage() { return __async(this, null, function* () { return new Promise((resolve, reject) => { const onMessage = (ev) => { this.removeEventListener("message", onMessage); this.removeEventListener("error", onError); resolve(ev); }; const onError = (ev) => { this.removeEventListener("message", onMessage); this.removeEventListener("error", onError); reject(ev); }; this.addEventListener("message", onMessage); this.addEventListener("error", onError); }); }); } }; // src/lib/availableStorage.ts var AvailableStorage = class { constructor() { this.available = typeof window !== "undefined" && !!window.localStorage; } getJSON(key) { if (!this.available) return null; const result = window.localStorage.getItem(key); if (result === null) return null; try { return JSON.parse(result); } catch (err) { return null; } } setJSON(key, obj) { if (!this.available) return null; window.localStorage.setItem(key, JSON.stringify(obj)); } delete(key) { if (!this.available) return null; window.localStorage.removeItem(key); } setString(key, value) { if (!this.available) return null; window.localStorage.setItem(key, value); } getString(key) { if (!this.available) return null; return window.localStorage.getItem(key); } }; var availableStorage = new AvailableStorage(); // src/lib/v2/mock/MockNovaInstance.ts var import_axios3 = require("axios"); var pathToRegexp = __toESM(require("path-to-regexp"), 1); var MockNovaInstance = class { constructor() { this.connections = []; } handleAPIRequest(config) { return __async(this, null, function* () { var _a, _b, _c; const apiHandlers = [ { method: "GET", path: "/cells/:cellId/controllers", handle() { return { controllers: [ { controller: "mock-ur5e", model_name: "UniversalRobots::Controller", host: "mock-ur5e", allow_software_install_on_controller: true, motion_groups: [ { motion_group: "0@mock-ur5e", name_from_controller: "UR5e", active: false, model_from_controller: "UniversalRobots_UR5e" } ], has_error: false, error_details: "" } ] }; } }, { method: "GET", path: "/cells/:cellId/controllers/:controllerId", handle() { return { configuration: { kind: "VirtualController", manufacturer: "universalrobots", position: "[0,-1.571,-1.571,-1.571,1.571,-1.571,0]", type: "universalrobots-ur5e" }, name: "mock-ur5" }; } }, { method: "GET", path: "/cells/:cellId/motion-groups/:motionGroupId/specification", handle() { return { dh_parameters: [ { alpha: 1.5707963267948966, theta: 0, a: 0, d: 162.25, reverse_rotation_direction: false }, { alpha: 0, theta: 0, a: -425, d: 0, reverse_rotation_direction: false }, { alpha: 0, theta: 0, a: -392.2, d: 0, reverse_rotation_direction: false }, { alpha: 1.5707963267948966, theta: 0, a: 0, d: 133.3, reverse_rotation_direction: false }, { alpha: -1.5707963267948966, theta: 0, a: 0, d: 99.7, reverse_rotation_direction: false }, { alpha: 0, theta: 0, a: 0, d: 99.6, reverse_rotation_direction: false } ], mechanical_joint_limits: [ { joint: "JOINTNAME_AXIS_1", lower_limit: -6.335545063018799, upper_limit: 6.335545063018799, unlimited: false }, { joint: "JOINTNAME_AXIS_2", lower_limit: -6.335545063018799, upper_limit: 6.335545063018799, unlimited: false }, { joint: "JOINTNAME_AXIS_3", lower_limit: -6.335545063018799, upper_limit: 6.335545063018799, unlimited: false }, { joint: "JOINTNAME_AXIS_4", lower_limit: -6.335545063018799, upper_limit: 6.335545063018799, unlimited: false }, { joint: "JOINTNAME_AXIS_5", lower_limit: -6.335545063018799, upper_limit: 6.335545063018799, unlimited: false }, { joint: "JOINTNAME_AXIS_6", lower_limit: -6.335545063018799, upper_limit: 6.335545063018799, unlimited: false } ] }; } }, { method: "GET", path: "/cells/:cellId/motion-groups/:motionGroupId/safety-setup", handle() { return { safety_settings: [ { safety_state: "SAFETY_NORMAL", settings: { joint_position_limits: [ { joint: "JOINTNAME_AXIS_1", lower_limit: -2.96705961227417, upper_limit: 2.96705961227417, unlimited: false }, { joint: "JOINTNAME_AXIS_2", lower_limit: -1.7453292608261108, upper_limit: 2.7925267219543457, unlimited: false }, { joint: "JOINTNAME_AXIS_3", lower_limit: -3.3161256313323975, upper_limit: 0.40142571926116943, unlimited: false }, { joint: "JOINTNAME_AXIS_4", lower_limit: -3.4906585216522217, upper_limit: 3.4906585216522217, unlimited: false }, { joint: "JOINTNAME_AXIS_5", lower_limit: -2.4434609413146973, upper_limit: 2.4434609413146973, unlimited: false }, { joint: "JOINTNAME_AXIS_6", lower_limit: -4.71238899230957, upper_limit: 4.71238899230957, unlimited: false } ], joint_velocity_limits: [ { joint: "JOINTNAME_AXIS_1", limit: 3.1415927410125732 }, { joint: "JOINTNAME_AXIS_2", limit: 3.1415927410125732 }, { joint: "JOINTNAME_AXIS_3", limit: 3.4906585216522217 }, { joint: "JOINTNAME_AXIS_4", limit: 6.108652591705322 }, { joint: "JOINTNAME_AXIS_5", limit: 6.108652591705322 }, { joint: "JOINTNAME_AXIS_6", limit: 6.981317043304443 } ], joint_acceleration_limits: [], joint_torque_limits: [], tcp_velocity_limit: 1800 } } ], safety_zones: [ { id: 1, priority: 0, geometry: { compound: { child_geometries: [ { convex_hull: { vertices: [ { vertex: [-800, -1330, -1820] }, { vertex: [1650, -1330, -1820] }, { vertex: [1650, 1330, -1820] }, { vertex: [-800, 1330, -1820] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "box" }, { convex_hull: { vertices: [ { vertex: [-800, -1330, -1820] }, { vertex: [1650, -1330, -1820] }, { vertex: [1650, -1330, 1500] }, { vertex: [-800, -1330, 1500] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "box" }, { convex_hull: { vertices: [ { vertex: [-800, -1330, -1820] }, { vertex: [-800, 1330, -1820] }, { vertex: [-800, 1330, 1500] }, { vertex: [-800, -1330, 1500] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "box" }, { convex_hull: { vertices: [ { vertex: [1650, 1330, 1500] }, { vertex: [-800, 1330, 1500] }, { vertex: [-800, -1330, 1500] }, { vertex: [1650, -1330, 1500] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "box" }, { convex_hull: { vertices: [ { vertex: [1650, 1330, 1500] }, { vertex: [-800, 1330, 1500] }, { vertex: [-800, 1330, -1820] }, { vertex: [1650, 1330, -1820] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "box" }, { convex_hull: { vertices: [ { vertex: [1650, 1330, 1500] }, { vertex: [1650, -1330, 1500] }, { vertex: [1650, -1330, -1820] }, { vertex: [1650, 1330, -1820] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "box" } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "Cell workzone" }, motion_group_uid: 1 }, { id: 2, priority: 0, geometry: { convex_hull: { vertices: [ { vertex: [1650, 1330, -1850] }, { vertex: [865, 1330, -1850] }, { vertex: [865, -720, -1850] }, { vertex: [1650, -720, -1850] }, { vertex: [1650, 1330, -920] }, { vertex: [865, 1330, -920] }, { vertex: [865, -720, -920] }, { vertex: [1650, -720, -920] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "Transport" }, motion_group_uid: 1 }, { id: 3, priority: 0, geometry: { convex_hull: { vertices: [ { vertex: [1650, 1330, -600] }, { vertex: [865, 1330, -600] }, { vertex: [865, 430, -600] }, { vertex: [1650, 430, -600] }, { vertex: [1650, 1330, -1250] }, { vertex: [865, 1330, -1250] }, { vertex: [865, 430, -1250] }, { vertex: [1650, 430, -1250] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "Tunel" }, motion_group_uid: 1 }, { id: 4, priority: 0, geometry: { convex_hull: { vertices: [ { vertex: [1650, -760, -440] }, { vertex: [900, -760, -440] }, { vertex: [900, -1330, -440] }, { vertex: [1650, -1330, -440] }, { vertex: [1650, -760, -1800] }, { vertex: [900, -760, -1800] }, { vertex: [900, -1330, -1800] }, { vertex: [1650, -1330, -1800] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "Fanuc controller" }, motion_group_uid: 1 }, { id: 6, priority: 0, geometry: { convex_hull: { vertices: [ { vertex: [-200, -200, -1900] }, { vertex: [200, -200, -1900] }, { vertex: [200, 200, -1900] }, { vertex: [-200, 200, -1900] }, { vertex: [-200, -200, -350] }, { vertex: [200, -200, -350] }, { vertex: [200, 200, -350] }, { vertex: [-200, 200, -350] } ] }, init_pose: { position: [0, 0, 0], orientation: [0, 0, 0, 1] }, id: "Robot base" }, motion_group_uid: 1 } ], robot_model_geometries: [ { link_index: 1, geometry: { sphere: { radius: 270 }, init_pose: { position: [-70, -70, -50], orientation: [0, 0, 0, 1] },