@wandelbots/nova-js
Version:
Official JS client for the Wandelbots API
1,452 lines (1,437 loc) • 76 kB
JavaScript
"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]
},