import API from './ecosystem-base.js';
import {Logger} from './../function/log-helper.js';
import {ErrorCode, ExceptionIdMap} from './../exception/exceptionDesc.js';
import {InfoType, WarningType} from '../information/informationCode.js';
const factoryApiRws = function (rws) {
/**
* The API.RWS namespace is an extension to the Omnicore SDK.
* @alias API.RWS
* @namespace
*/
rws.RWS = new (function () {
const logModule = 'ecosystem-rws';
this.MASTERSHIP = {
Nomaster: 'nomaster',
Remote: 'remote',
Local: 'local',
Internal: 'internal',
};
this.LEADTHROUGHSTATUS = {
Inactive: 'Inactive',
Active: 'Active',
};
function parseJSON(json) {
try {
return JSON.parse(json);
} catch (error) {
return undefined;
}
}
function rwsPost(url, body, error_msg) {
return RWS.Network.post(url, body)
.then((ret) => {
if (!ret || !ret.response) {
return Promise.resolve();
}
const responseText = ret.response;
try {
const content = JSON.parse(responseText);
return Promise.resolve(content);
} catch (e) {
return Promise.resolve(responseText);
}
})
.catch((err) => {
return API.rejectWithStatus(error_msg, err, ErrorCode.FailedToSendRWSPost, logModule);
});
}
/**
* @typedef {'edit' | 'motion' } MastershipType
* @memberof API.RWS
*/
/**
* @alias requestMastership
* @memberof API.RWS
* @param {MastershipType} type The mastership type, which can be 'edit' or 'motion'.
* @returns {Promise<any>}
* @example
* API.RWS.requestMastership('edit')
*/
const requestMastership = function (type = 'edit') {
if (type === 'edit')
return RWS.Mastership.request()
.then(() => Promise.resolve())
.catch((err) => {
return API.rejectWithStatus(
'Could not get edit Mastership.',
err,
ErrorCode.FailedToRequestEditMastership,
logModule,
);
});
else if (type != '') type = type + '/';
return rwsPost(`/rw/mastership/${type}request`, '', `Request ${type} mastership failed.`);
};
this.requestMastership = requestMastership;
/**
* @alias releaseMastership
* @memberof API.RWS
* @param {MastershipType} type The mastership type, which can be 'edit' or 'motion'.
* @returns {Promise<any>}
* @example
* API.RWS.releaseMastership('edit')
*/
const releaseMastership = function (type = 'edit') {
if (type === 'edit')
return RWS.Mastership.release()
.then(() => Promise.resolve())
.catch((err) => {
Logger.d(logModule, `Could not release Mastership. >>> ${err.message}`);
RWS.writeDebug(`Could not release Mastership. >>> ${err.message}`);
return Promise.resolve();
});
else if (type != '') type = type + '/';
return rwsPost(`/rw/mastership/${type}release`, '', `Release ${type} mastership failed.`);
};
this.releaseMastership = releaseMastership;
/**
* Executes the function with holding the specified mastership.
* @alias executeWithMastership
* @memberof API.RWS
* @param {any} args The arguments for function calling.
* @param {Function} func The function to be called.
* @param {MastershipType} type The mastership type, which can be 'edit' or 'motion'.
* @returns {Promise<any>}
*/
const executeWithMastership = async function (func, args, type = 'edit') {
let hasMastership = false;
try {
await requestMastership(type);
hasMastership = true;
await func.apply(this, args);
return;
} catch (err) {
return API.rejectWithStatus('Failed to get mastership.', err, ErrorCode.FailedToGetMastershipStatus);
} finally {
if (hasMastership) {
await releaseMastership(type);
}
}
};
/**
* @alias getMastershipState
* @memberof API.RWS
* @param {string} type The mastership type, which can be 'edit' or 'motion'.
* @returns {Promise<object>}
*/
this.getMastershipState = async function (type = 'edit') {
try {
let res = await RWS.Network.get(`/rw/mastership/${type}`);
let obj = parseJSON(res.responseText);
return obj['state'][0]['mastership'];
} catch (err) {
return API.rejectWithStatus(
`Failed to get ${type} mastership status`,
err,
ErrorCode.FailedToGetMastershipStatus,
logModule,
);
}
};
/**
* Checks if held the mastership.
* @alias checkIfHeldMastership
* @memberof API.RWS
* @param {string} type The mastership type, which can be 'edit' or 'motion'.
* @returns {Promise<boolean>}
* @example
* // check if holding edit mastership
* await API.RWS.checkIfHeldMastership()
*/
this.checkIfHeldMastership = async function (type = 'edit') {
try {
let res = await RWS.Network.get(`/rw/mastership/${type}`);
let obj = parseJSON(res.responseText);
let state = obj['state'][0];
return state && state.mastershipheldbyme && state.mastershipheldbyme == 'TRUE';
} catch (err) {
return API.rejectWithStatus(
`Failed to check if held ${type} mastership`,
err,
ErrorCode.FailedToCheckIfHeldMastership,
logModule,
);
}
};
function parseResponse(res) {
let items = [];
let obj = parseJSON(res.responseText);
if (typeof obj === 'undefined') return Promise.reject('Could not parse JSON.');
let resources = obj._embedded.resources;
resources.forEach((item) => {
let it = {};
it.name = item._title;
for (let prop in item) {
if (prop.indexOf('_') === -1) {
it[prop] = item[prop];
}
}
items.push(it);
});
return items;
}
/**
* This class provides motion-related interfaces that are not supported by the OmniCore SDK.
* @namespace MOTIONSYSTEM
* @memberof API.RWS
*/
this.MOTIONSYSTEM = new (function () {
/**
*
* @typedef Mechunits
* @prop {string} activationAllowed
* @prop {string} driveModule
* @prop {string} mode // 'Activated', ...
* @prop {string} name
* @memberof API.RWS.MOTIONSYSTEM
*/
/**
*
* @typedef Mechunit
* @prop {string} axes
* @prop {string} axesTotal
* @prop {string} coords
* @prop {string} hasIntegratedUnit
* @prop {string} isIntegratedUnit
* @prop {string} jogMode
* @prop {string} mode
* @prop {string} payload
* @prop {string} status
* @prop {string} task
* @prop {string} tool
* @prop {string} totalPayload
* @prop {string} type
* @prop {string} wobj
* @prop {string} name
* @memberof API.RWS.MOTIONSYSTEM
*/
/**
* Gets details of all the mechanical units.
* @alias getMechunits
* @memberof API.RWS.MOTIONSYSTEM
* @returns {Promise<Mechunits[]>}
* @example
* const mechunits = await API.RWS.MOTIONSYSTEM.getMechunits();
* console.log(mechunits); // Outputs an array of mechanical units
*/
this.getMechunits = async function () {
try {
let res = await RWS.Network.get('/rw/motionsystem/mechunits');
let items = [];
let obj = parseJSON(res.responseText);
if (typeof obj === 'undefined') return Promise.reject('Could not parse the response of getting mechunits');
let resources = obj._embedded.resources;
resources.forEach((item) => {
let it = {};
it.name = item._title;
for (let prop in item) {
if (prop.indexOf('_') === -1) {
it[prop] = item[prop];
}
}
items.push(it);
});
return items;
} catch (err) {
return API.rejectWithStatus('Failed to get mechunits.', err, ErrorCode.FailedToGetMechunits, logModule);
}
};
/**
* Gets the details of a mechanical unit.
* @alias getMechunit
* @memberof API.RWS.MOTIONSYSTEM
* @param {string} name Name of the mechanical unit., e.g., 'ROB_1'
* @returns {Promise<Mechunit>}
* @example
* const mechunit = await API.RWS.MOTIONSYSTEM.getMechunit('ROB_1');
* console.log(mechunit); // Outputs details of the specified mechanical unit
*/
this.getMechunit = async function (name = 'ROB_1') {
try {
let res = await RWS.Network.get(`/rw/motionsystem/mechunits/${name}?continue-on-err=1`);
let obj = parseJSON(res.responseText);
let mechunit = {};
mechunit.axes = obj.state[0].axes;
mechunit.axesTotal = obj.state[0]['axes-total'];
mechunit.coords = obj.state[0]['coord-system'];
mechunit.hasIntegratedUnit = obj.state[0]['has-integrated-unit'];
mechunit.isIntegratedUnit = obj.state[0]['is-integrated-unit'];
mechunit.jogMode = obj.state[0]['jog-mode'];
mechunit.mode = obj.state[0]['mode'];
mechunit.payload = obj.state[0]['payload-name'];
mechunit.status = obj.state[0]['status'];
mechunit.task = obj.state[0]['task-name'];
mechunit.tool = obj.state[0]['tool-name'];
mechunit.totalPayload = obj.state[0]['total-payload-name'];
mechunit.type = obj.state[0]['type'];
mechunit.wobj = obj.state[0]['wobj-name'];
mechunit.name = obj.state[0]._title;
return mechunit;
} catch (err) {
return API.rejectWithStatus(
`Failed to get mechunit ${name} info`,
err,
ErrorCode.FailedToGetMechunitInfo,
logModule,
);
}
};
/**
* @typedef SetMechunitProps
* @prop {string} [name]
* @prop {string} [tool]
* @prop {string} [wobj]
* @prop {string} [coords]
* @prop {string} [jogMode]
* @prop {string} [mode]
* @prop {string} [payload]
* @prop {string} [totalPayload]
* @memberof API.RWS.MOTIONSYSTEM
*/
/**
* Sets the properties of a mechanical unit.
* @alias setMechunit
* @memberof API.RWS.MOTIONSYSTEM
* @param {SetMechunitProps} props See {@link SetMechunitProps}
* @returns {Promise<any>}
* @example
* await API.RWS.MOTIONSYSTEM.setMechunit({
* name: 'ROB_1',
* tool: 'Tool1',
* wobj: 'WObj1',
* });
*/
this.setMechunit = async function ({
name = 'ROB_1',
tool = '',
wobj = '',
coords = '',
payload = '',
totalPayload = '',
mode = '',
jogMode = '',
} = {}) {
let url = `/rw/motionsystem/mechunits/${name}?continue-on-err=1`;
let body = '';
body += tool ? 'tool=' + tool : '';
body += wobj ? (body ? '&' : '') + 'wobj=' + wobj : '';
body += payload ? (body ? '&' : '') + 'payload=' + payload : '';
body += totalPayload ? (body ? '&' : '') + 'total-payload=' + totalPayload : '';
body += mode ? (body ? '&' : '') + 'mode=' + mode : '';
body += jogMode ? (body ? '&' : '') + 'jog-mode=' + jogMode : '';
body += coords ? (body ? '&' : '') + 'coord-system=' + coords : '';
let res = await rwsPost(url, body, 'Failed to set mechunit.');
return res;
};
/**
* Sets the robot position target for GoTo task.
* @alias setRobotPositionTarget
* @memberof API.RWS.MOTIONSYSTEM
* @param {API.MOTION.RobTarget} r See {@link API.MOTION.RobTarget}
* @returns {Promise<any>}
* @example
* const robTarget = {
* trans: { x: 100, y: 200, z: 300 },
* rot: { q1: 1, q2: 0, q3: 0, q4: 0 },
* robconf: { cf1: 0, cf4: 0, cf6: 0, cfx: 0 },
* extax: { eax_a: 0, eax_b: 0, eax_c: 0, eax_d: 0, eax_e: 0, eax_f: 0 },
* };
* await API.RWS.MOTIONSYSTEM.setRobotPositionTarget(robTarget);
*/
this.setRobotPositionTarget = function (r) {
if (r.trans === undefined || r.rot === undefined || r.robconf === undefined) {
return API.rejectWithStatus("Parameter 'r' is not a robtarget.", {}, ErrorCode.InvalidPrameter, logModule);
}
let url = `/rw/motionsystem/position-target`;
let body = `pos-x=${r.trans.x}&pos-y=${r.trans.y}&pos-z=${r.trans.z}&orient-q1=${r.rot.q1}&orient-q2=${
r.rot.q2
}&orient-q3=${r.rot.q3}&orient-q4=${r.rot.q4}&config-j1=${r.robconf.cf1}&config-j4=${r.robconf.cf4}&config-j6=${
r.robconf.cf6
}&config-jx=${r.robconf.cfx}&extjoint-1=${r.extax ? r.extax.eax_a : 9e9}&extjoint-2=${
r.extax ? r.extax.eax_b : 9e9
}&extjoint-3=${r.extax ? r.extax.eax_c : 9e9}&extjoint-4=${r.extax ? r.extax.eax_d : 9e9}&extjoint-5=${
r.extax ? r.extax.eax_e : 9e9
}&extjoint-6=${r.extax ? r.extax.eax_f : 9e9}`;
return rwsPost(url, body, 'Failed to set target robot position for GoTo');
};
/**
* Sets the joint position target for GoTo task.
* @alias setRobotPositionJoint
* @memberof API.RWS.MOTIONSYSTEM
* @param {API.MOTION.JointTarget} j
* @returns {Promise<any>}
* @example
* const jointTarget = {
* robax: { rax_1: 0, rax_2: 0, rax_3: 0, rax_4: 0, rax_5: 0, rax_6: 0 },
* extax: { eax_a: 0, eax_b: 0, eax_c: 0, eax_d: 0, eax_e: 0, eax_f: 0 },
* };
* await API.RWS.MOTIONSYSTEM.setRobotPositionJoint(jointTarget);
*/
this.setRobotPositionJoint = function (j) {
if (j.robax === undefined) return Promise.reject("Parameter 'j' is not a jointtarget.");
let url = `/rw/motionsystem/position-joint`;
let body = `robjoint=${j.robax.rax_1},${j.robax.rax_2},${j.robax.rax_3},${j.robax.rax_4},${j.robax.rax_5},${
j.robax.rax_6
}&extjoint=${j.extax ? j.extax.eax_a : 9e9},${j.extax ? j.extax.eax_b : 9e9},${j.extax ? j.extax.eax_c : 9e9},${
j.extax ? j.extax.eax_d : 9e9
},${j.extax ? j.extax.eax_e : 9e9},${j.extax ? j.extax.eax_f : 9e9}`;
return rwsPost(url, body, 'Failed to set target joint position for GoTo');
};
/**
* Starts jogging. This request shall be sent cyclically during the jogging.
* @alias jog
* @memberof API.RWS.MOTIONSYSTEM
* @param {API.MOTION.JogData} jogdata Jogging speed for the axis.
* @param {number} ccount Counter value, which needs to be obtained using {@link getChangeCount} before start jogging.
* @returns {Promise<any>}
* @example
* const jogData = [10, 0, 0, 0, 0, 0]; // Jogging along axis 1
* const changeCount = await API.RWS.MOTIONSYSTEM.getChangeCount();
* await API.RWS.MOTIONSYSTEM.jog(jogData, changeCount);
*/
this.jog = async function (jogdata, ccount) {
let url = `/rw/motionsystem/jog`;
let body = `axis1=${jogdata[0]}&axis2=${jogdata[1]}&axis3=${jogdata[2]}&axis4=${jogdata[3]}&axis5=${jogdata[4]}&axis6=${jogdata[5]}&ccount=${ccount}`;
return rwsPost(url, body, `Failed to send jog commands.jogdata: ${jogdata.toString()}. ccount:${ccount}.`);
};
/**
* Gets the change count of the motion system.
* @alias getChangeCount
* @memberof API.RWS.MOTIONSYSTEM
* @returns {Promise<number>}
* @example
* const changeCount = await API.RWS.MOTIONSYSTEM.getChangeCount();
* console.log(`Change count: ${changeCount}`);
*/
this.getChangeCount = async function () {
try {
let res = await RWS.Network.get(`/rw/motionsystem?resource=change-count`);
let obj = parseJSON(res.responseText);
return obj['state'][0]['change-count'];
} catch (err) {
return API.rejectWithStatus(
'Failed to get change count of motion system',
err,
ErrorCode.FailedToGetMotionSystemChangeCount,
logModule,
);
}
};
this.parseRobTarget = function (robTarget) {
let rt = {trans: {}, rot: {}, robconf: {}, extax: {}};
rt.trans.x = parseFloat(robTarget['x']);
rt.trans.y = parseFloat(robTarget['y']);
rt.trans.z = parseFloat(robTarget['z']);
rt.rot.q1 = parseFloat(robTarget['q1']);
rt.rot.q2 = parseFloat(robTarget['q2']);
rt.rot.q3 = parseFloat(robTarget['q3']);
rt.rot.q4 = parseFloat(robTarget['q4']);
rt.robconf.cf1 = parseFloat(robTarget['cf1']);
rt.robconf.cf4 = parseFloat(robTarget['cf4']);
rt.robconf.cf6 = parseFloat(robTarget['cf6']);
rt.robconf.cfx = parseFloat(robTarget['cfx']);
rt.extax.eax_a = parseFloat(robTarget['eax_a']);
rt.extax.eax_b = parseFloat(robTarget['eax_b']);
rt.extax.eax_c = parseFloat(robTarget['eax_c']);
rt.extax.eax_d = parseFloat(robTarget['eax_d']);
rt.extax.eax_e = parseFloat(robTarget['eax_e']);
rt.extax.eax_f = parseFloat(robTarget['eax_f']);
return rt;
};
/**
* @typedef RobTargetProps
* @param {string} [tool]
* @param {string} [wobj]
* @param {string} [coords]
* @param {string} [mechunit]
* @memberof API.RWS.MOTIONSYSTEM
*/
/**
* Gets the current robot position.
* @alias getRobTarget
* @memberof API.RWS.MOTIONSYSTEM
* @param {RobTargetProps} props See {@link RobTargetProps}
* @returns {Promise<API.MOTION.RobTarget>}
* @example
* const robTarget = await API.RWS.MOTIONSYSTEM.getRobTarget('Tool1', 'WObj1');
*/
this.getRobTarget = async function (tool = '', wobj = '', coords = '', mechunit = 'ROB_1') {
try {
let params = '';
params += tool ? '?tool=' + tool : '';
params += wobj ? (params ? '&' : '?') + 'wobj=' + wobj : '';
params += coords ? (params ? '&' : '?') + 'coordinate=' + coords : '';
let res = await RWS.Network.get(`/rw/motionsystem/mechunits/${mechunit}/robtarget${params}`);
let obj = parseJSON(res.responseText);
let rt = this.parseRobTarget(obj['state'][0]);
return rt;
} catch (e) {
return API.rejectWithStatus(
'Failed to get current robot position',
e,
ErrorCode.FailedToGetRobotTarget,
logModule,
);
}
};
this.parseJointTarget = function (jointTarget, toDegrees = false) {
let jt = {robax: {}, extax: {}};
let factor = 180 / Math.PI;
jt.robax.rax_1 = toDegrees ? parseFloat(jointTarget['rax_1']) * factor : parseFloat(jointTarget['rax_1']);
jt.robax.rax_2 = toDegrees ? parseFloat(jointTarget['rax_2']) * factor : parseFloat(jointTarget['rax_2']);
jt.robax.rax_3 = toDegrees ? parseFloat(jointTarget['rax_3']) * factor : parseFloat(jointTarget['rax_3']);
jt.robax.rax_4 = toDegrees ? parseFloat(jointTarget['rax_4']) * factor : parseFloat(jointTarget['rax_4']);
jt.robax.rax_5 = toDegrees ? parseFloat(jointTarget['rax_5']) * factor : parseFloat(jointTarget['rax_5']);
jt.robax.rax_6 = toDegrees ? parseFloat(jointTarget['rax_6']) * factor : parseFloat(jointTarget['rax_6']);
jt.extax.eax_a = parseFloat(jointTarget['eax_a']);
jt.extax.eax_b = parseFloat(jointTarget['eax_b']);
jt.extax.eax_c = parseFloat(jointTarget['eax_c']);
jt.extax.eax_d = parseFloat(jointTarget['eax_d']);
jt.extax.eax_e = parseFloat(jointTarget['eax_e']);
jt.extax.eax_f = parseFloat(jointTarget['eax_f']);
return jt;
};
/**
* Gets the current joint position.
* @alias getJointTarget
* @memberof API.RWS.MOTIONSYSTEM
* @param {string} mechunit
* @returns {Promise<API.MOTION.JointTarget>}
* @example
* const jointTarget = await API.RWS.MOTIONSYSTEM.getJointTarget('ROB_1');
* console.log(jointTarget); // Outputs the current joint positions
*/
this.getJointTarget = async function (mechunit = 'ROB_1') {
try {
let res = await RWS.Network.get(`/rw/motionsystem/mechunits/${mechunit}/jointtarget`);
let obj = parseJSON(res.responseText);
let jt = this.parseJointTarget(obj['state'][0], false);
return jt;
} catch (e) {
return API.rejectWithStatus(
'Failed to get current robot joint position',
e,
ErrorCode.FailedToGetJointTarget,
logModule,
);
}
};
/**
*
* @typedef JointsSolutionProps
* @prop {string} [mechUnit]
* @prop {API.MOTION.RobTarget} robTarget
* @prop {API.MOTION.ToolData} [toolData]
*/
/**
* Get all joint solutions
* @alias getAllJointsSolution
* @memberof API.RWS.MOTIONSYSTEM
* @param {JointsSolutionProps} props
* @returns {Promise<any>}
*/
this.getAllJointsSolution = async function ({mechUnit = 'ROB_1', robTarget, toolData}) {
/*
* {
* curr_position* string
* [x,y,z]
*
* curr_ext_joints* string
* [j1,j2,j3,j4,j5,j6]
*
* tool_frame_position* string
* [x, y, z]
*
* curr_orientation* string
* [u0, u1, u2, u3]
*
* tool_frame_orientation* string
* [u0, u1, u2, u3]
*
* robot_fixed_object* string
* TRUE|FALSE
*
* robot_configuration* string
* [quarter_rev_j1, quarter_rev_j4, quarter_rev_j6, quarter_rev_jx]
*
* }
*/
Logger.i(InfoType.RobotOperation, 'Trying to get joint solution for a target position');
const r = robTarget;
const t = toolData
? toolData
: {robhold: true, tframe: {trans: {x: 0, y: 0, z: 0}, rot: {q1: 1, q2: 0, q3: 0, q4: 0}}};
const toMeters = 0.001;
if (r.trans === undefined || r.rot === undefined || r.robconf === undefined)
return API.rejectWithStatus(
"Parameter 'robTarget' is not a valid robtarget value.",
{},
ErrorCode.InvalidPrameter,
logModule,
);
let url = `/rw/motionsystem/mechunits/${mechUnit}/all-joints-solution`;
let body = `curr_position=[${r.trans.x * toMeters},${r.trans.y * toMeters},${
r.trans.z * toMeters
}]&curr_ext_joints=[${r.extax ? r.extax.eax_a : 9e9},${r.extax ? r.extax.eax_b : 9e9},${
r.extax ? r.extax.eax_c : 9e9
},${r.extax ? r.extax.eax_d : 9e9},${r.extax ? r.extax.eax_e : 9e9},${
r.extax ? r.extax.eax_f : 9e9
}]&tool_frame_position=[${t.tframe.trans.x * toMeters},${t.tframe.trans.y * toMeters},${
t.tframe.trans.z * toMeters
}]&curr_orientation=[${r.rot.q1},${r.rot.q2},${r.rot.q3},${r.rot.q4}]&tool_frame_orientation=[${
t.tframe.rot.q1
},${t.tframe.rot.q2},${t.tframe.rot.q3},${t.tframe.rot.q4}]&robot_fixed_object=${
t.robhold ? 'TRUE' : 'FALSE'
}&robot_configuration=[${r.robconf.cf1},${r.robconf.cf4},${r.robconf.cf6},${r.robconf.cfx}]`;
let res = await rwsPost(url, body, 'Failed to get all joint solutions from Cartesian');
let toDegree = 180 / Math.PI;
let jtArray = res.state.map((jointData) => {
let jt = {robax: {}, extax: {}, robconf: {}};
jt.robax.rax_1 = parseFloat(jointData['robotjoint1']) * toDegree;
jt.robax.rax_2 = parseFloat(jointData['robotjoint2']) * toDegree;
jt.robax.rax_3 = parseFloat(jointData['robotjoint3']) * toDegree;
jt.robax.rax_4 = parseFloat(jointData['robotjoint4']) * toDegree;
jt.robax.rax_5 = parseFloat(jointData['robotjoint5']) * toDegree;
jt.robax.rax_6 = parseFloat(jointData['robotjoint6']) * toDegree;
jt.extax.eax_a = parseFloat(jointData['extjoint1']);
jt.extax.eax_b = parseFloat(jointData['extjoint2']);
jt.extax.eax_c = parseFloat(jointData['extjoint3']);
jt.extax.eax_d = parseFloat(jointData['extjoint4']);
jt.extax.eax_e = parseFloat(jointData['extjoint5']);
jt.extax.eax_f = parseFloat(jointData['extjoint6']);
jt.robconf.cf1 = parseInt(jointData['quarter_rev_j11']);
jt.robconf.cf4 = parseInt(jointData['quarter_rev_j4']);
jt.robconf.cf6 = parseInt(jointData['quarter_rev_j6']);
jt.robconf.cfx = parseInt(jointData['quarter_rev_jx']);
return jt;
});
return jtArray;
};
/**
*
* @typedef JontsFromCartesianProps
* @prop {string} [mechUnit]
* @prop {API.MOTION.RobTarget} robTarget
* @prop {API.MOTION.ToolData} [toolData]
* @prop {API.MOTION.JointTarget} jointTarget
*/
/**
* Get all the joint solutions.
* @alias getJointsFromCartesian
* @memberof API.RWS.MOTIONSYSTEM
* @param {JontsFromCartesianProps} props
* @returns {Promise<any>}
*/
this.getJointsFromCartesian = async function ({mechUnit = 'ROB_1', robTarget, toolData, jointTarget}) {
/*
* {
* curr_position* string
* [x,y,z]
*
* curr_ext_joints* string
* [j1,j2,j3,j4,j5,j6]
*
* tool_frame_position* string
* [x, y, z]
*
* curr_orientation* string
* [u0, u1, u2, u3]
*
* tool_frame_orientation* string
* [u0, u1, u2, u3]
*
* old_rob_joints* string
* [j1,j2,j3,j4,j5,j6]
*
* old_ext_joints* string
* [j1,j2,j3,j4,j5,j6]
*
* robot_fixed_object* string
* TRUE|FALSE
*
* robot_configuration* string
* [quarter_rev_j1, quarter_rev_j4, quarter_rev_j6, quarter_rev_jx]
*
* elog_at_error* string
* TRUE|FALSE
*
* }
*/
Logger.i(InfoType.RobotOperation, 'Trying to get joint solution for a target position');
const r = robTarget;
const j = jointTarget;
const t = toolData
? toolData
: {robhold: true, tframe: {trans: {x: 0, y: 0, z: 0}, rot: {q1: 1, q2: 0, q3: 0, q4: 0}}};
const toRadians = Math.PI / 180;
const toMeters = 0.001;
if (r.trans === undefined || r.rot === undefined || r.robconf === undefined || j.robax === undefined)
return API.rejectWithStatus(
"Parameter 'robTarget' is not a valid robtarget value.",
{},
ErrorCode.InvalidPrameter,
logModule,
);
let url = `/rw/motionsystem/mechunits/${mechUnit}/joints-from-cartesian`;
let body = `curr_position=[${r.trans.x * toMeters},${r.trans.y * toMeters},${
r.trans.z * toMeters
}]&curr_ext_joints=[${r.extax ? r.extax.eax_a : 9e9},${r.extax ? r.extax.eax_b : 9e9},${
r.extax ? r.extax.eax_c : 9e9
},${r.extax ? r.extax.eax_d : 9e9},${r.extax ? r.extax.eax_e : 9e9},${
r.extax ? r.extax.eax_f : 9e9
}]&tool_frame_position=[${t.tframe.trans.x},${t.tframe.trans.y},${t.tframe.trans.z}]&curr_orientation=[${
r.rot.q1
},${r.rot.q2},${r.rot.q3},${r.rot.q4}]&tool_frame_orientation=[${t.tframe.rot.q1},${t.tframe.rot.q2},${
t.tframe.rot.q3
},${t.tframe.rot.q4}]&old_rob_joints=[${j.robax.rax_1 * toRadians},${j.robax.rax_2 * toRadians},${
j.robax.rax_3 * toRadians
},${j.robax.rax_4 * toRadians},${j.robax.rax_5 * toRadians},${j.robax.rax_6 * toRadians}]&old_ext_joints=[${
j.extax ? j.extax.eax_a : 9e9
},${j.extax ? j.extax.eax_b : 9e9},${j.extax ? j.extax.eax_c : 9e9},${j.extax ? j.extax.eax_d : 9e9},${
j.extax ? j.extax.eax_e : 9e9
},${j.extax ? j.extax.eax_f : 9e9}]&robot_fixed_object=${t.robhold ? 'TRUE' : 'FALSE'}&robot_configuration=[${
r.robconf.cf1
},${r.robconf.cf4},${r.robconf.cf6},${r.robconf.cfx}]&elog_at_error=TRUE`;
let res = await rwsPost(url, body, 'Failed to get joint solution from Cartesian');
let jt = {robax: {}, extax: {}};
let toDegree = 180 / Math.PI;
jt.robax.rax_1 = parseFloat(res.state[0]['robotjoint1']) * toDegree;
jt.robax.rax_2 = parseFloat(res.state[0]['robotjoint2']) * toDegree;
jt.robax.rax_3 = parseFloat(res.state[0]['robotjoint3']) * toDegree;
jt.robax.rax_4 = parseFloat(res.state[0]['robotjoint4']) * toDegree;
jt.robax.rax_5 = parseFloat(res.state[0]['robotjoint5']) * toDegree;
jt.robax.rax_6 = parseFloat(res.state[0]['robotjoint6']) * toDegree;
jt.extax.eax_a = parseFloat(res.state[0]['extjoint1']);
jt.extax.eax_b = parseFloat(res.state[0]['extjoint2']);
jt.extax.eax_c = parseFloat(res.state[0]['extjoint3']);
jt.extax.eax_d = parseFloat(res.state[0]['extjoint4']);
jt.extax.eax_e = parseFloat(res.state[0]['extjoint5']);
jt.extax.eax_f = parseFloat(res.state[0]['extjoint6']);
return jt;
};
/**
* Gets the lead-through status.
* @alias getLeadThroughStatus
* @memberof API.RWS.MOTIONSYSTEM
* @param {string} mechunit
* @returns {Promise<any>}
* @example
* const status = await API.RWS.MOTIONSYSTEM.getLeadThroughStatus('ROB_1');
* console.log(`Lead-through status: ${status}`);
*/
this.getLeadThroughStatus = async function (mechunit = 'ROB_1') {
try {
let ltRes = await RWS.Network.get(`/rw/motionsystem/mechunits/${mechunit}/lead-through`);
let obj = parseJSON(ltRes.responseText);
return obj['state'][0]['status'];
} catch (e) {
return API.rejectWithStatus(
'Get leadthrough status failed.',
e,
ErrorCode.FailedToGetLeadthroughStatus,
logModule,
);
}
};
/**
* Sets the lead-through status.
* @alias setLeadThroughStatus
* @memberof API.RWS.MOTIONSYSTEM
* @param {string} type API.RWS.LEADTHROUGHSTATUS.Inactive | API.RWS.LEADTHROUGHSTATUS.Active
* @param {string} disableAutoLoadCompensation Being Active if the precision mode is used. This is supported from RW7.6.
* @param {string} mechunit The name of the mechanical unit.
* @returns {Promise<any>}
* @example
* await API.RWS.MOTIONSYSTEM.setLeadThroughStatus(
* API.RWS.LEADTHROUGHSTATUS.Active,
* 'inactive',
* 'ROB_1'
* );
* console.log('Lead-through status set successfully.');
*/
this.setLeadThroughStatus = async function (type, disableAutoLoadCompensation = 'inactive', mechunit = 'ROB_1') {
let data = 'status=' + type;
let systemInfo = await API.RWS.CONTROLLER.getSystemInfo();
if (parseInt(systemInfo['major']) == 7 && parseInt(systemInfo['minor']) >= 6) {
data += '&disableautoloadcompensation=' + disableAutoLoadCompensation;
}
try {
await RWS.Network.post('/rw/motionsystem/mechunits/' + mechunit + '/lead-through', data);
} catch (e) {
return API.rejectWithStatus(
`Failed to set leadthrough status to ${type}`,
e,
ErrorCode.FailedToSetLeadthrough,
logModule,
);
}
};
})();
/**
* The API.RWS.RAPID namespace provides RAPID-related interfaces that are not supported by the OmniCore SDK.
* @namespace RAPID
* @memberof API.RWS
*/
this.RAPID = new (function () {
/**
* Loads a module from the HOME directory of the controller into the specified task.
* @alias loadModule
* @memberof API.RWS.RAPID
* @param {string} path Path to the module file in the HOME directory (including the file extension).
* @param {boolean} [replace] If the value is 'true', existing module in RAPID with the same name will be replaced.
* @param {string} [taskName] The task name.
* @param {boolean} [requestMsh] Edit mastership needs to be requested before loading the module.
* @returns {Promise<any>}
* @example
* let url = `${this.path}/${this.name}${this.extension}`;
* await API.RWS.RAPID.loadModule(url, true, 'T_ROB1');
*/
this.loadModule = async function (path, replace = false, taskName = 'T_ROB1', requestMsh = true) {
const f = async function () {
return await RWS.Network.post(
`/rw/rapid/tasks/${taskName}/loadmod`,
'modulepath=' + path + '&replace=' + replace,
);
};
try {
if (requestMsh) {
return await executeWithMastership(f);
} else {
return await f();
}
} catch (e) {
return API.rejectWithStatus(
`Failed to load RAPID module at path ${path}`,
e,
ErrorCode.FailedToLoadRapidModule,
logModule,
);
}
};
/**
* Unloads a RAPID module.
* @alias unloadModule
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} [taskName] The task name.
* @param {boolean} [requestMsh] Edit mastership needs to be requested before unloading the module.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.unloadModule('MyModule', 'T_ROB1');
*/
this.unloadModule = async function (moduleName, taskName = 'T_ROB1', requestMsh = true) {
const f = function () {
return RWS.Network.post(`/rw/rapid/tasks/${taskName}/unloadmod`, 'module=' + moduleName);
};
try {
if (requestMsh) {
return await executeWithMastership(f);
} else {
return await f();
}
} catch (e) {
return API.rejectWithStatus(
`Failed to unload RAPID module. Task: ${taskName}. Module: ${moduleName}`,
e,
ErrorCode.FailedToUnloadRapidModule,
logModule,
);
}
};
/**
* Gets the RAPID module text.
* @alias getModuleText
* @memberof API.RWS.RAPID
* @param {*} moduleName The module name.
* @param {*} taskName The task name.
* @returns {Promise<any>} An object containing the structure
* {
* change-count,
* module-length,
* module-text?,
* file-path?,
* _title,
* _type,
* }
* @example
* const moduleText = await API.RWS.RAPID.getModuleText('MyModule', 'T_ROB1');
*/
this.getModuleText = async function (moduleName, taskName = 'T_ROB1') {
try {
let res = await RWS.Network.get(`/rw/rapid/tasks/${taskName}/modules/${moduleName}/text`);
var fixedResponse = res.responseText.replace(/""(.*?)""/g, '"$1"');
let obj = parseJSON(fixedResponse);
if (typeof obj === 'undefined') return Promise.reject('Could not parse JSON.');
if (!obj.state[0]) return Promise.reject('Failed to get module text.');
return obj.state[0];
} catch (e) {
return API.rejectWithStatus(
`Failed to get module text content. Task: ${taskName}. Module: ${moduleName}`,
e,
ErrorCode.FailedToGetRapidModuleContent,
logModule,
);
}
};
/**
* Sets the content of a RAPID module.
* @alias setModuleText
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} text The new content of the module.
* @param {string} [taskName] The task name.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.setModuleText("Module1",`MODULE Module1\r\nPROC proc1()\r\nTPWrite "123";\r\nENDPROC\r\nENDMODULE`), 'T_ROB1');
*/
this.setModuleText = async function (moduleName, text, taskName = 'T_ROB1') {
const url = `/rw/rapid/tasks/${taskName}/modules/${moduleName}/text`;
const body = `text=${encodeURIComponent(text)}`;
return await rwsPost(url, body, `Failed to set content of ${taskName}:${moduleName}.`);
};
/**
* Sets the content of a RAPID module within a specified range.
* @alias setModuleTextInRange
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} text The new content to insert.
* @param {number} startRow Start row of the range.
* @param {number} startCol Start column of the range.
* @param {number} endRow End row of the range.
* @param {number} endCol End column of the range.
* @param {string} [taskName] The task name.
* @param {string} [replaceMode] Replace mode, e.g., 'Replace'.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.setModuleTextInRange(
* 'MyModule',
* 'TPErase;',
* 5,
* 1,
* 10,
* 1,
* 'T_ROB1',
* 'Replace'
* );
*/
this.setModuleTextInRange = async function (
moduleName,
text,
startRow,
startCol,
endRow,
endCol,
taskName = 'T_ROB1',
replaceMode = 'Replace',
) {
const url = `/rw/rapid/tasks/${taskName}/modules/${moduleName}/text/range`;
const body = `replace-mode=${replaceMode}&query-mode=Force&startrow=${startRow}&startcol=${startCol}&endrow=${endRow}&endcol=${endCol}&text=${encodeURIComponent(
text,
)}`;
return rwsPost(url, body, `Failed to set content range of ${taskName}:${moduleName}.`);
};
/**
* Moves the program pointer to a specified cursor position.
* @alias movePPToCursor
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} taskName The task name.
* @param {string} line Number of the line to which the pointer is desired.
* @param {string} column Number of the column to which the pointer is desired.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.movePPToCursor('MyModule', 'T_ROB1', '10', '5');
*/
this.movePPToCursor = function (moduleName, taskName, line, column) {
if (typeof moduleName !== 'string') return Promise.reject("Parameter 'module' is not a string.");
if (typeof line !== 'string') return Promise.reject("Parameter 'line' is not a string.");
if (typeof column !== 'string') return Promise.reject("Parameter 'column' is not a string.");
let url = `/rw/rapid/tasks/${encodeURIComponent(taskName)}/pcp/cursor?mastership=implicit`;
let body = `module=${encodeURIComponent(moduleName)}&line=${encodeURIComponent(
line,
)}&column=${encodeURIComponent(column)}`;
return rwsPost(
url,
body,
`Failed to set PP to cursor. Task: ${taskName}. Module: ${moduleName}. line:${line}. column: ${column}.`,
);
};
/**
* Sets the program pointer to a specified routine.
* @alias setPPToRoutine
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} routineName Routine's name.
* @param {string} [taskName] The task name.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.setPPToRoutine('MyModule', 'MainRoutine', 'T_ROB1');
*/
this.setPPToRoutine = function (moduleName, routineName, taskName = 'T_ROB1') {
let url = `/rw/rapid/tasks/${taskName}/pcp/routine-from-url`;
let body = `routineurl=/RAPID/${taskName}/${moduleName}/${routineName}&userlevel=false`;
return rwsPost(
url,
body,
`Failed to set PP to routine. Task: ${taskName}. Module: ${moduleName}. routine: ${routineName}.`,
);
};
/**
* Gets the information of program pointers
* @alias getPointersInfo
* @memberof API.RWS.RAPID
* @param {string} [taskName] The task name.
* @returns {Promise<any>}
* @example
* const pointersInfo = await API.RWS.RAPID.getPointersInfo('T_ROB1');
*/
this.getPointersInfo = async function (taskName = 'T_ROB1') {
try {
let res = await RWS.Network.get('/rw/rapid/tasks/' + taskName + '/pcp');
let pcpInfo = JSON.parse(res.responseText)['state'];
return pcpInfo;
} catch (e) {
return API.rejectWithStatus(
`Failed to get program/motion pointers information. Task: ${taskName}.`,
e,
ErrorCode.FailedToGetPointersInfo,
logModule,
);
}
};
/**
* Synchronizes the value of persistent variables in a specified module.
* @alias syncPers
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} [taskName] The task name.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.syncPers('MyModule', 'T_ROB1');
*/
this.syncPers = function (moduleName, taskName = 'T_ROB1') {
let url = `/rw/rapid/tasks/${taskName}/modules/${moduleName}/sync-pers`;
return rwsPost(url, '', `Failed to sync pers. Task: ${taskName}. Module: ${moduleName}`);
};
/**
* Gets the properties of the specified RAPID data type
* @alias getDataTypeProperty
* @memberof API.RWS.RAPID
* @param {string} typeUrl The URL of the data type.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.getDataTypeProperty('robtarget');
*/
this.getDataTypeProperty = async function (typeUrl) {
try {
let res = await RWS.Network.get(`/rw/rapid/symbol/${typeUrl}/properties`);
let typeProp = JSON.parse(res.responseText)['state'][0];
return typeProp;
} catch (e) {
return API.rejectWithStatus(
`Failed to get data type property of ${typeUrl}`,
e,
ErrorCode.FailedToGetDataTypeProperty,
logModule,
);
}
};
/**
* Gets the RECORD data list.
* @alias getRecordTypes
* @memberof API.RWS.RAPID
* @param {string} task The task name.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.getRecordTypes()
*/
this.getRecordTypes = function (task = 'T_ROB1') {
let data = '';
data += '&blockurl=' + `RAPID/${task}`;
data += '&recursive=TRUE'; // True all the way
data += '&symtyp=rec';
data += "®exp = '[^<].*?[^>]'";
return rwsPost('/rw/rapid/symbols/search', data, `Failed to get RECORD name list of task ${task}`);
};
/**
* Get the data structure of the specified RAPID data type
* @alias getDataTypeStructure
* @memberof API.RWS.RAPID
* @param {string} typeUrl The URL of the data type.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.getDataTypeStructure();
*/
this.getDataTypeStructure = function (blockurl = 'RAPID/robtarget', exturl = 'symbols/search') {
let data = '';
data += '&blockurl=' + blockurl;
data += '&recursive=TRUE'; // True all the way
return rwsPost('/rw/rapid/' + exturl, data, `Failed to get data structure of ${blockurl}`);
};
/**
* Gets the raw value of a RAPID variable.
* @alias getVariableRawValue
* @memberof API.RWS.RAPID
* @param {string} moduleName The module name.
* @param {string} variableName The variable name.
* @param {string} taskName The task name.
* @returns {Promise<string>}
* @example
* await API.RWS.RAPID.getVariableRawValue('TestModule', 'TestVariable', 'T_ROB1');
*/
this.getVariableRawValue = async function (moduleName, variableName, taskName = 'T_ROB1') {
try {
let res = await RWS.Network.get(`/rw/rapid/symbol/RAPID/${taskName}/${moduleName}/${variableName}/data`);
let value = JSON.parse(res.responseText)['state'][0]['value'];
return value;
} catch (e) {
return API.rejectWithStatus(
`Failed to get variable value. Task: ${taskName}. Module: ${moduleName}. Variable: ${variableName}`,
e,
ErrorCode.FailedToGetVariableValue,
logModule,
);
}
};
/**
* Gets the service routines.
* @alias getServiceRoutines
* @memberof API.RWS.RAPID
* @param {string} exturl External URL for the service routines.
* @param {boolean} allread Indicates whether to include all the readable routines.
* @returns {Promise<any>}
*/
this.getServiceRoutines = async function (exturl, allread) {
try {
let searchedResult = await RWS.Network.get('/rw/rapid/' + exturl + 'allread=' + (allread ? 'TRUE' : 'FALSE'));
return JSON.parse(searchedResult.responseText);
} catch (e) {
return API.rejectWithStatus(
'Failed to get service routine list',
e,
ErrorCode.FailedToGetServiceRoutines,
logModule,
);
}
};
/**
* Sets the cycle mode for the program execution.
* @alias setCycleMode
* @memberof API.RWS.RAPID
* @param {string} mode Cycle mode, e.g., 'once' or 'forever'.
* @returns {Promise<any>}
* @example
* await API.RWS.RAPID.setCycleMode('forever');
*/
this.setCycleMode = async function (mode = 'once') {
let url = `/rw/rapid/execution/cycle`;
let body = `cycle=${mode}`;
return rwsPost(url, body, `Failed to set cycle mode to ${mode}`, ErrorCode.FailedToSetCycleMode, logModule);
};
/**
* Gets the current cycle mode of the program execution.
* @alias getCycleMode
* @memberof API.RWS.RAPID
* @returns {Promise<string>} The current cycle mode.
* @example
* const cycleMode = await API.RWS.RAPID.getCycleMode();
*/
this.getCycleMode = async function () {
try {
let res = await RWS.Network.get('/rw/rapid/execution');
let executionInfo = JSON.parse(res.responseText)['state'][0];
return executionInfo['cycle'];
} catch (e) {
return API.rejectWithStatus('Failed to get cycle mode', e, ErrorCode.FailedToGetCycleMode, logModule);
}
};
/**
* This class represents a monitor on the RAPID task changes.
* @class TaskChangeMonitor
* @memberof API.RWS
* @param {string} taskName The task name to be monitored.
*/
class TaskChangeMonitor {
constructor(task = 'T_ROB1') {
this.url = `/rw/rapid/tasks/${encodeURIComponent(task)}`;
this.resourceString = `/rw/rapid/tasks/${encodeURIComponent(task)};taskchange`;
this.callbacks = [];
}
getTitle() {
return this.url;
}
getResourceString() {
return this.resourceString;
}
addCallbackOnChanged(callback) {
if (typeof callback !== 'function') {
throw new Error('callback is not a valid function');
}
this.callbacks.push(callback);
}
async onchanged(newValue) {
let parsedValue = {};
let taskChangeInfo = {};
taskChangeInfo['changeCount'] = Object.prototype.hasOwnProperty.call(newValue, 'change-count')
? newValue['change-count']
: '';
taskChangeInfo['changeType'] = Object.prototype.hasOwnProperty.call(newValue, 'changetype')
? newValue['changetype']
: '';
taskChangeInfo['moduleName'] = Object.prototype.hasOwnProperty.call(newValue, 'module-name')
? newValue['module-name']
: '';
taskChangeInfo['programName'] = Object.prototype.hasOwnProperty.call(newValue, 'program-name')
? newValue['program-name']
: '';
taskChangeInfo['taskName'] = Object.prototype.hasOwnProperty.call(newValue, 'task-name')
? newValue['task-name']
: '';
parsedValue = taskChangeInfo;
for (let i = 0; i < this.callbacks.length; i++) {
try {
this.callbacks[i](parsedValue);
} catch (error) {
return API.rejectWithStatus(
'Failed to execute specific callback when RAPID task change is triggered',
error,
ErrorCode.FailedToExecuteCallback,
logModule,
);
}
}
}
subscribe() {
return RWS.Subscriptions.subscribe([this]);
}
unsubscribe() {
return RWS.Subscriptions.unsubscribe([this]);
}
}
/**
* Gets an instance of a API.RAPID.TaskChangeMonitor class
* @alias getTaskChangeMonitor
* @memberof API.RWS.RAPID
* @param {string} taskName - Task name
* @returns {Promise<object>} - API.RAPID.TaskChangeMonitor
* @example
* let taskChangeMonitor = await API.RWS.getTaskChangeMonitor();
* const taskchangeCb = function (data) {
* console.log('RAPID is changed');
* };
* taskChangeMonitor.addCallbackOnChanged(taskchangeCb);
* taskChangeMonitor.subscribe()
*/
this.getTaskChangeMonitor = function (taskName = 'T_ROB1') {
return new TaskChangeMonitor(taskName);
};
})();
/**
* The API.RWS.CFG namespace provides configuration-related interfaces that are not supported by OmniCore SDK.
* @namespace CFG
* @memberof API.RWS
*/
this.CFG = new (function () {
/**
* Deletes an existing entry from the configuraiton database
* @alias deleteConfigInstance
* @memberof API.RWS.CFG
* @param {string} name The instance name
* @param {string} type The instance type
* @param {string} domain The instance domain
* @param {boolean} [requestMsh] Edit mastership needs to be requested before deleting the instance.
* @returns {Promise<any>}
* @example
* // delete the signal configuration instance
* await API.RWS.CFG.deleteConfigInstance("TestDO1", "EIO_SIGNAL", "eio")
*/
this.deleteConfigInstance = async function (name, type, domain, requestMsh = true) {
const f = function () {
return RWS.Network.delete(`/rw/cfg/${domain}/${type}/instances/${name}`);
};
try {
if (requestMsh) {
return await executeWithMastership(f);
} else {
return await f();
}
} catch (e) {
return API.rejectWithStatus(
`Failed to delete configuration instance.${domain}-${type}-${name}`,
e,
ErrorCode.FailedToDeleteConfigInstance,
logModule,
);
}
};
})();
/**
* The RWS.CONTROLLER class provides a set of controller-related interfaces that are not supported by the OmniCore SDK.
* It includes methods for retrieving robot types, system information, and managing program execution settings such as speed ratio.
* @namespace CONTROLLER
* @memberof API.RWS
*/
this.CONTROLLER = new (function () {
/**
* Gets the robot type.
* @alias getRobotType
* @memberof API.RWS.CONTROLLER
* @returns {Promise<string>} A promise with a string containing the robot type.
* @example
* const robotType = await API.RWS.CONTROLLER.getRobotType();
* console.log(robotType); // Outputs the robot type
*/
this.getRobotType = async function () {
try {
let robotType = await RWS.Network.get('/rw/system/robottype');
return JSON.parse(robotType.responseText)['state'][0]['robot-type'];
} catch (e) {
return API.rejectWithStatus('Get robot type failed', e, ErrorCode.FailedToGetRobotType, logModule);
}
};
/**
* Gets the system information.
* @alias getSystemInfo
* @memberof API.RWS.CONTROLLER
* @returns {Promise<any>}
* @example
* const systemInfo = await API.RWS.CONTROLLER.getSystemInfo();
* console.log(systemInfo);
*/
this.getSystemInfo = async function () {
try {
let systemRes = await RWS.Network.get('/rw/system');
let res = JSON.parse(systemRes.responseText);
let result = {
options: [],
rwversionname: res['state'][0]['rwversionname'],
major: res['state'][0]['major'],
minor: res['state'][0]['minor'],
build: res['state'][0]['build'],
revision: res['state'][0]['revision'],
date: res['state'][0]['date'],
name: res['state'][0]['name'],
sysid: res['state'][0]['sysid'],
};
let opts = res['_embedded']['resources'][0]['options'];
for (const iterator of opts) {
if (iterator['option'] != undefined) {
result.options.push(iterator['option']);
}
}
return result;
} catch (e) {
return API.rejectWithStatus(
'Failed to get controller system information',
e,
ErrorCode.FailedToGetSystemInfo,
logModule,
);
}
};
/**
* Sets the speed ratio for program execution. The setting requires the editing mastership and only supports the Auto mode.
* @alias setSpeedRatio
* @memberof API.RWS.CONTROLLER
* @param {number} speedRatio The speed ratio number in percentage.
* @returns {Promise<string>}
* @example
* await API.RWS.CONTROLLER.setSpeedRatio(50); // Sets the speed ratio to 50%
*/
this.setSpeedRatio = async function (speedRatio) {
try {
return RWS.Network.post('/rw/panel/speedratio', 'speed-ratio=' + speedRatio.toString());
} catch (e) {
return API.rejectWithStatus(
`Failed to set speed ratio to ${speedRatio}`,
e,
ErrorCode.FailedToSetSpeedRatio.logModule,
);
}
};
/**
* Gets the speed ratio for program execution.
* @alias getSpeedRatio
* @memberof API.RWS.CONTROLLER
* @returns {Promise<number>}
* @example
* const speedRatio = await API.RWS.CONTROLLER.getSpeedRatio();
* console.log(`Current speed ratio: ${speedRatio}%`);
*/
this.getSpeedRatio = async function () {
try {
let speedRes = await RWS.Network.get('/rw/panel/speedratio');
return parseInt(JSON.parse(speedRes.responseText)['state'][0]['speedratio']);
} catch (e) {
return API.rejectWithStatus('Failed to get speed ratio', e, ErrorCode.FailedToGetSpeedRatio, logModule);
}
};
})();
/**
* This class class provides a set of signal-related interfaces that are not supported by the OmniCore SDK.
* @namespace SIGNAL
* @memberof API.RWS
*/
this.SIGNAL = new (function () {
/**
* Modifies the signal value.
* @alias setSignalValue
* @memberof API.RWS.SIGNAL
* @param {string} signalName
* @param {number} value
* @param {string} mode value | pulse | invert | toggle | delay
* @param {number} pulses Number of pulses. This parameter is required to be set if the mode is set to "toggle" or "pulse".
* @param {number} activePulse Active pulse length for pulse/toggle mode, in ms
* @param {number} passivePulse Passive pulse length for pulse/toggle mode, in ms
* @param {number} delay Delay time for delay mode, in ms
* @param {string} deviceType
* @param {string} networkType
* @param {*} attr
* @example
* await API.RWS.SIGNAL.setSignalValue("TestDO1","1");
*/
this.setSignalValue = async function (
signalName,
value,
{
mode = '',
pulses = 1,
activePulse = 1000,
passivePulse = 1000,
delay = 1000,
deviceType = '',
networkType = '',
} = {},
) {
try {
const isPulseParameterRequired = ['pulse', 'toggle'].includes(mode);
const isDelayParameterRequired = ['delay'].includes(mode);
await RWS.Network.post(
'/rw/iosystem/signals/' +
(networkType ? networkType + '/' : '') +
(deviceType ? deviceType + '/' : '') +
signalName +
'/set-value',
'lvalue=' +
value +
(mode ? `&mode=${mode}` : '') +
(isPulseParameterRequired
? `&Pulses=${pulses}&ActivePulse=${activePulse}&PassivePulse=${passivePulse}`
: '') +
(isDelayParameterRequired ? `&Delay=${delay}` : ''),
);
} catch (error) {
Logger.e(logModule, ErrorCode.FailedToSetSignalValue, error);
TComponents.Popup_A.warning(
`${ExceptionIdMap.FailedToSetSignalValue}-${TComponents.Component_A.t(
`framework:${ExceptionIdMap.FailedToSetSignalValue}.title`,
)}`,
TComponents.Component_A.t(`framework:${ExceptionIdMap.FailedToSetSignalValue}.causes`),
);
}
};
/**
* Gets the signal value.
* @alias getSignalValue
* @memberof API.RWS.SIGNAL
* @param {string} signalName The signal name.
* @param {string} deviceType The device type.
* @param {string} networkType The network type.
* @returns {Promise<string>}
* @example
* await API.RWS.SIGNAL.getSignalValue("TestDO1");
*/
this.getSignalValue = async function (signalName, {deviceType = '', networkType = ''} = {}) {
try {
let signalRes = await RWS.Network.get(
'/rw/iosystem/signals/' +
(networkType ? networkType + '/' : '') +
(deviceType ? deviceType + '/' : '') +
signalName +
';state',
);
return JSON.parse(signalRes.responseText).state[0].lvalue;
} catch (error) {
return API.rejectWithStatus(
`Failed to get signal ${signalName} value`,
error,
ErrorCode.FailedToGetSignalValue,
);
}
};
})();
/**
* This class provides a set of UAS-related interfaces that are not supported by the OmniCore SDK.
* @namespace UAS
* @memberof API.RWS
*/
this.UAS = new (function () {
/**
* Get the grants of a specified user.
* @alias getGrantsOfUser
* @memberof API.RWS.UAS
* @param {string} userName The user name.
* @example
* await API.RWS.UAS.getGrantsOfUser("admin")
*/
this.getGrantsOfUser = async function (userName) {
try {
let userGrantsInfoRes = await RWS.Network.get(`/uas/users/${userName}/grants`);
let userGrantsInfo = JSON.parse(userGrantsInfoRes.responseText).state;
let userGrants = [];
userGrantsInfo.forEach((info) => {
userGrants.push(info.grantname);
});
return userGrants;
} catch (e) {
return API.rejectWithStatus(
`Failed to get grant list of user ${userName}`,
e,
ErrorCode.FailedToGetUserGrants,
logModule,
);
}
};
})();
/**
* This class provides a set of user-releated interfaces.
* @namespace USER
* @memberof API.RWS
*/
this.USER = new (function () {
const RMMPStatus = {
GRANTED: 'GRANTED',
PENDING: 'PENDING',
REJECTED: 'REJECTED',
};
// TODO: check the name of all user functions
this.poller = 0;
/**
* Gets thw RMMP state.
* @alias getRMMPState
* @memberof API.RWS.USER
* @example
* await API.RWS.USER.getRMMPState()
*/
this.getRMMPState = async function () {
try {
let rmmpStates = await RWS.Network.get('/users/rmmp');
return JSON.parse(rmmpStates.responseText)['state'][0];
} catch (e) {
return API.rejectWithStatus('Failed to get RMMP state', e, ErrorCode.FailedToGetRMMPState, logModule);
}
};
/**
* Cancels the RMMP request.
* @alias cancelRMMP
* @memberof API.RWS.USER
* @example
* await API.RWS.USER.cancelRMMP()
*/
this.cancelRMMP = async function () {
clearInterval(this.poller);
return await RWS.Network.post('/users/rmmp/cancel', '');
};
/**
* Requests the RMMP. Release RMMP first if RMMP is held.
* @alias reqRMMP
* @memberof API.RWS.USER
* @example
* await API.RWS.USER.reqRMMP()
*/
this.reqRMMP = async () => {
try {
var resRMMP = await API.RWS.USER.getRMMPState();
if (resRMMP['rmmpheldbyme'] === 'false') {
await API.RWS.USER.requestRMMP();
} else if (resRMMP['rmmpheldbyme'] === 'true' && resRMMP['privilege'] != 'none') {
// TODO: confirm if it is offical way to handle the case where TPU revoke the msh
// The reason why add "privilege" is that it cannot request msh when rmmpheldbyme is true and privilege is 'modify'
await API.RWS.USER.relRMMP();
await API.RWS.USER.requestRMMP();
}
} catch (e) {
return API.rejectWithStatus('Failed to request RMMP', e, ErrorCode.FailedToRequestRMMP, logModule);
}
};
/**
* Releases the RMMP.
* @alias relRMMP
* @memberof API.RWS.USER
* @example
* await API.RWS.USER.relRMMP()
*/
this.relRMMP = async () => {
try {
let resRMMP = await API.RWS.USER.getRMMPState();
if (resRMMP['rmmpheldbyme'] === 'false') {
return;
} else if (resRMMP['rmmpheldbyme'] === 'true') {
try {
await API.RWS.USER.cancelRMMP();
} catch (error) {
throw new Error('release RMMP failed');
}
}
} catch (error) {
return API.rejectWithStatus('Failed to release RMMP', error, ErrorCode.FailedToReleaseRMMP, logModule);
}
};
/**
* Request RMMP
* @alias requestRMMP
* @memberof API.RWS.USER
* @example
* await API.RWS.USER.requestRMMP()
*/
this.requestRMMP = async (type = 'modify') => {
await RWS.Network.post('/users/rmmp', `privilege=${type}`);
};
/**
* Polls the RMMP state.
* @alias pollRMMPStatus
* @memberof API.RWS.USER
* @example
* await API.RWS.USER.pollRMMPStatus()
*/
this.pollRMMPStatus = async () => {
let rmmpStates = await RWS.Network.get('/users/rmmp/poll');
return JSON.parse(rmmpStates.responseText)['state'][0];
};
this.pollRMMPState = () => {
return new Promise((resolve, reject) => {
let timeout = 500;
clearInterval(this.poller);
let that = this;
this.poller = setInterval(async function () {
try {
var rmmp = await API.RWS.USER.pollRMMPStatus();
} catch (error) {
Logger.e(
logModule,
ErrorCode.FailedToPollRMMP,
`Could not request edit Mastership in manual mode. >>> Failed to poll RMMP status!`,
);
reject('Failed to poll RMMP status!');
return;
}
let rmmpStatus = rmmp.status;
switch (rmmpStatus) {
case RMMPStatus.GRANTED:
clearInterval(that.poller);
resolve(true);
break;
case RMMPStatus.REJECTED:
clearInterval(that.poller);
Logger.e(
logModule,
ErrorCode.FailedToPollRMMP,
`Could not request edit Mastership in manual mode. >>> RMMP rejected by local client!`,
);
reject('RMMP rejected');
break;
case RMMPStatus.PENDING:
timeout -= 1; // 1000ms/1. 200ms/0.2.
if (timeout < 0) {
await API.RWS.USER.relRMMP();
clearInterval(that.poller);
Logger.e(
logModule,
ErrorCode.FailedToPollRMMP,
`Could not request edit Mastership in manual mode. >>> RMMP request pending timeout!`,
);
reject('Pending timeout');
}
break;
default:
}
}, 200);
});
};
})();
})();
rws.constructedRWS = true;
};
if (typeof API.constructedRWS === 'undefined') {
factoryApiRws(API);
}
export default API;
export {factoryApiRws};