abb-rws-client 0.2.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -0
- package/README.md +364 -143
- package/dist/HttpSession.d.ts.map +1 -1
- package/dist/HttpSession.js +18 -1
- package/dist/HttpSession.js.map +1 -1
- package/dist/IRWSAdapter.d.ts +421 -0
- package/dist/IRWSAdapter.d.ts.map +1 -0
- package/dist/IRWSAdapter.js +2 -0
- package/dist/IRWSAdapter.js.map +1 -0
- package/dist/Logger.d.ts +35 -0
- package/dist/Logger.d.ts.map +1 -0
- package/dist/Logger.js +24 -0
- package/dist/Logger.js.map +1 -0
- package/dist/MultiRobotManager.d.ts +56 -0
- package/dist/MultiRobotManager.d.ts.map +1 -0
- package/dist/MultiRobotManager.js +129 -0
- package/dist/MultiRobotManager.js.map +1 -0
- package/dist/RWS1Adapter.d.ts +297 -0
- package/dist/RWS1Adapter.d.ts.map +1 -0
- package/dist/RWS1Adapter.js +870 -0
- package/dist/RWS1Adapter.js.map +1 -0
- package/dist/RWS2Adapter.d.ts +20 -0
- package/dist/RWS2Adapter.d.ts.map +1 -0
- package/dist/RWS2Adapter.js +19 -0
- package/dist/RWS2Adapter.js.map +1 -0
- package/dist/ResourceMapper.d.ts +226 -2
- package/dist/ResourceMapper.d.ts.map +1 -1
- package/dist/ResourceMapper.js +286 -3
- package/dist/ResourceMapper.js.map +1 -1
- package/dist/ResponseParser.d.ts +81 -2
- package/dist/ResponseParser.d.ts.map +1 -1
- package/dist/ResponseParser.js +309 -3
- package/dist/ResponseParser.js.map +1 -1
- package/dist/RobotManager.d.ts +536 -0
- package/dist/RobotManager.d.ts.map +1 -0
- package/dist/RobotManager.js +1523 -0
- package/dist/RobotManager.js.map +1 -0
- package/dist/RwsClient.d.ts +280 -4
- package/dist/RwsClient.d.ts.map +1 -1
- package/dist/RwsClient.js +698 -10
- package/dist/RwsClient.js.map +1 -1
- package/dist/RwsClient2.d.ts +438 -0
- package/dist/RwsClient2.d.ts.map +1 -0
- package/dist/RwsClient2.js +1672 -0
- package/dist/RwsClient2.js.map +1 -0
- package/dist/WsSubscriber.d.ts.map +1 -1
- package/dist/WsSubscriber.js +18 -11
- package/dist/WsSubscriber.js.map +1 -1
- package/dist/XhtmlParser.d.ts +24 -0
- package/dist/XhtmlParser.d.ts.map +1 -0
- package/dist/XhtmlParser.js +56 -0
- package/dist/XhtmlParser.js.map +1 -0
- package/dist/detect.d.ts +54 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +187 -0
- package/dist/detect.js.map +1 -0
- package/dist/index.d.ts +30 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +190 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/examples/01-quickstart-auto.mjs +20 -0
- package/examples/02-rws1-explicit.mjs +30 -0
- package/examples/03-rws2-explicit.mjs +26 -0
- package/examples/04-multi-robot.mjs +35 -0
- package/examples/05-remote-control-rmmp.mjs +52 -0
- package/examples/06-pull-module-source.mjs +38 -0
- package/package.json +31 -5
package/dist/RwsClient.js
CHANGED
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
import { HttpSession } from './HttpSession.js';
|
|
18
18
|
import { WsSubscriber } from './WsSubscriber.js';
|
|
19
19
|
import { RwsError } from './types.js';
|
|
20
|
-
import { controllerState as pathControllerState, operationMode as pathOperationMode, rapidTasks as pathRapidTasks, rapidExecutionState as pathRapidExecutionState, startRapid as mapStartRapid, stopRapid as mapStopRapid, resetRapid as mapResetRapid, jointTarget as pathJointTarget, robTarget as pathRobTarget, loadModule as mapLoadModule, listModules as pathListModules, uploadFile as pathUploadFile, signal as pathSignal, setSignal as mapSetSignal, } from './ResourceMapper.js';
|
|
21
|
-
import { parseControllerState, parseOperationMode, parseExecutionState, parseJointTarget, parseRobTarget, parseSignal, parseRapidTasks, } from './ResponseParser.js';
|
|
20
|
+
import { controllerState as pathControllerState, setControllerState as mapSetControllerState, operationMode as pathOperationMode, speedRatio as pathSpeedRatio, setSpeedRatio as mapSetSpeedRatio, collisionDetectionState as pathCollisionDetectionState, restartController as mapRestartController, lockOperationMode as mapLockOperationMode, unlockOperationMode as mapUnlockOperationMode, rapidTasks as pathRapidTasks, rapidExecutionState as pathRapidExecutionState, startRapid as mapStartRapid, stopRapid as mapStopRapid, resetRapid as mapResetRapid, setExecutionCycle as mapSetExecutionCycle, rapidSymbol as pathRapidSymbol, rapidSymbolProperties as pathRapidSymbolProperties, setRapidSymbol as mapSetRapidSymbol, activeUiInstruction as pathActiveUiInstruction, setUiInstructionParam as mapSetUiInstructionParam, activateRapidTask as mapActivateRapidTask, deactivateRapidTask as mapDeactivateRapidTask, activateAllRapidTasks as mapActivateAllRapidTasks, deactivateAllRapidTasks as mapDeactivateAllRapidTasks, searchRapidSymbols as mapSearchRapidSymbols, validateRapidValue as mapValidateRapidValue, jointTarget as pathJointTarget, robTarget as pathRobTarget, cartesianFull as pathCartesianFull, loadModule as mapLoadModule, listModules as pathListModules, uploadFile as pathUploadFile, allSignals as pathAllSignals, networks as pathNetworks, devices as pathDevices, signal as pathSignal, setSignal as mapSetSignal, systemInfo as pathSystemInfo, controllerIdentity as pathControllerIdentity, clockInfo as pathClockInfo, setControllerClock as mapSetControllerClock, elogMessages as pathElogMessages, clearElogDomain as mapClearElogDomain, clearAllElogs as mapClearAllElogs, fileServicePath, deleteFile as pathDeleteFile, copyFile as mapCopyFile, requestMastership as mapRequestMastership, releaseMastership as mapReleaseMastership, } from './ResourceMapper.js';
|
|
21
|
+
import { parseControllerState, parseOperationMode, parseSpeedRatio, parseExecutionState, parseExecutionInfo, parseJointTarget, parseRobTarget, parseCartesianFull, parseRapidSymbolValue, parseRapidSymbolProperties, parseSignal, parseSignalList, parseNetworks, parseDevices, parseRapidTasks, parseSystemInfo, parseControllerIdentity, parseControllerClock, parseActiveUiInstruction, parseRapidSymbolSearch, parseElogMessages, parseDirectory, parseCollisionDetectionState, } from './ResponseParser.js';
|
|
22
22
|
export class RwsClient {
|
|
23
23
|
session;
|
|
24
24
|
subscriber;
|
|
25
25
|
constructor(options) {
|
|
26
26
|
const sessionOptions = {
|
|
27
27
|
baseUrl: `http://${options.host}:${options.port ?? 80}`,
|
|
28
|
-
username: options.username ?? '
|
|
28
|
+
username: options.username ?? 'Admin',
|
|
29
29
|
password: options.password ?? 'robotics',
|
|
30
30
|
requestIntervalMs: options.requestIntervalMs ?? 55,
|
|
31
31
|
timeoutMs: options.timeout ?? 5000,
|
|
@@ -38,6 +38,36 @@ export class RwsClient {
|
|
|
38
38
|
getSessionCookie() {
|
|
39
39
|
return this.session.getSessionCookie();
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Generic HTTP request helper exposing the underlying authenticated session.
|
|
43
|
+
*
|
|
44
|
+
* Lets adapters call any RWS endpoint without requiring this library to wrap
|
|
45
|
+
* each one in a typed method. Useful for endpoints that aren't (yet) exposed
|
|
46
|
+
* as named methods — the caller handles parsing the response body.
|
|
47
|
+
*
|
|
48
|
+
* Reuses the session's digest auth, cookie, queue, retry, and timeout logic.
|
|
49
|
+
*
|
|
50
|
+
* @param method 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
51
|
+
* @param path URL path, e.g. `/rw/cfg/MOC/ROBOT/instances?json=1`
|
|
52
|
+
* @param body Optional request body (form-encoded string for POST/PUT)
|
|
53
|
+
* @returns `{ status: number, body: string }` — raw response
|
|
54
|
+
*/
|
|
55
|
+
async request(method, path, body) {
|
|
56
|
+
let res;
|
|
57
|
+
if (method === 'GET') {
|
|
58
|
+
res = await this.session.get(path);
|
|
59
|
+
}
|
|
60
|
+
else if (method === 'POST') {
|
|
61
|
+
res = await this.session.post(path, body ?? '');
|
|
62
|
+
}
|
|
63
|
+
else if (method === 'PUT') {
|
|
64
|
+
res = await this.session.put(path, body ?? '');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
res = await this.session.delete(path);
|
|
68
|
+
}
|
|
69
|
+
return { status: res.status, body: res.body };
|
|
70
|
+
}
|
|
41
71
|
// ─── Connection ─────────────────────────────────────────────────────────────
|
|
42
72
|
/**
|
|
43
73
|
* Establish a session with the controller.
|
|
@@ -66,9 +96,16 @@ export class RwsClient {
|
|
|
66
96
|
try {
|
|
67
97
|
await this.subscriber.closeAll();
|
|
68
98
|
}
|
|
69
|
-
|
|
70
|
-
|
|
99
|
+
catch { /* ignore */ }
|
|
100
|
+
// Server-side cleanup: GET /logout releases mastership, subscriptions, and frees
|
|
101
|
+
// the session slot in the controller's pool. Without this, orphan mastership can
|
|
102
|
+
// block subsequent clients for several minutes (until the controller times out
|
|
103
|
+
// the session by inactivity). Best-effort — ignore errors.
|
|
104
|
+
try {
|
|
105
|
+
await this.session.get('/logout');
|
|
71
106
|
}
|
|
107
|
+
catch { /* ignore */ }
|
|
108
|
+
this.session.clearSession();
|
|
72
109
|
}
|
|
73
110
|
// ─── Controller state ───────────────────────────────────────────────────────
|
|
74
111
|
/**
|
|
@@ -89,6 +126,24 @@ export class RwsClient {
|
|
|
89
126
|
throw new RwsError(`getControllerState failed: ${String(e)}`, 'UNKNOWN');
|
|
90
127
|
}
|
|
91
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Set the controller motor state.
|
|
131
|
+
* Requires AUTO mode and mastership (request with requestMastership('motion') first).
|
|
132
|
+
*
|
|
133
|
+
* @param state - 'motoron' | 'motoroff'
|
|
134
|
+
* @throws {RwsError} code='AUTH_FAILED' if mastership is not held
|
|
135
|
+
*/
|
|
136
|
+
async setControllerState(state) {
|
|
137
|
+
try {
|
|
138
|
+
const { path, body } = mapSetControllerState(state);
|
|
139
|
+
await this.session.post(path, body);
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
if (e instanceof RwsError)
|
|
143
|
+
throw e;
|
|
144
|
+
throw new RwsError(`setControllerState failed: ${String(e)}`, 'UNKNOWN');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
92
147
|
/**
|
|
93
148
|
* Read the current operation mode.
|
|
94
149
|
*
|
|
@@ -106,6 +161,123 @@ export class RwsClient {
|
|
|
106
161
|
throw new RwsError(`getOperationMode failed: ${String(e)}`, 'UNKNOWN');
|
|
107
162
|
}
|
|
108
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Read the collision detection state.
|
|
166
|
+
* Returns INIT (no collision), TRIGGERED, CONFIRMED, or TRIGGERED_ACK.
|
|
167
|
+
* Requires the Collision Detection option on the controller.
|
|
168
|
+
*/
|
|
169
|
+
async getCollisionDetectionState() {
|
|
170
|
+
try {
|
|
171
|
+
const { body } = await this.session.get(pathCollisionDetectionState());
|
|
172
|
+
return parseCollisionDetectionState(body);
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
if (e instanceof RwsError)
|
|
176
|
+
throw e;
|
|
177
|
+
throw new RwsError(`getCollisionDetectionState failed: ${String(e)}`, 'UNKNOWN');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Restart (or warm-start) the controller.
|
|
182
|
+
*
|
|
183
|
+
* **Modes:**
|
|
184
|
+
* - `restart` — Normal restart; saves state and activates changed system parameters
|
|
185
|
+
* - `istart` — Restart with original installation settings; discards all programs
|
|
186
|
+
* - `pstart` — Restart preserving system parameters; removes programs
|
|
187
|
+
* - `bstart` — Boot with last auto-saved state (crash recovery)
|
|
188
|
+
*
|
|
189
|
+
* @param mode - Restart mode; default 'restart'
|
|
190
|
+
*/
|
|
191
|
+
async restartController(mode = 'restart') {
|
|
192
|
+
try {
|
|
193
|
+
const { path, body } = mapRestartController(mode);
|
|
194
|
+
await this.session.post(path, body);
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
if (e instanceof RwsError)
|
|
198
|
+
throw e;
|
|
199
|
+
throw new RwsError(`restartController failed: ${String(e)}`, 'UNKNOWN');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Lock the operation mode selector on the FlexPendant.
|
|
204
|
+
* @param pin - 4-digit PIN code
|
|
205
|
+
* @param permanent - true = permanent lock; false = temporary
|
|
206
|
+
*/
|
|
207
|
+
async lockOperationMode(pin, permanent = false) {
|
|
208
|
+
try {
|
|
209
|
+
const { path, body } = mapLockOperationMode(pin, permanent);
|
|
210
|
+
await this.session.post(path, body);
|
|
211
|
+
}
|
|
212
|
+
catch (e) {
|
|
213
|
+
if (e instanceof RwsError)
|
|
214
|
+
throw e;
|
|
215
|
+
throw new RwsError(`lockOperationMode failed: ${String(e)}`, 'UNKNOWN');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Unlock the operation mode selector. */
|
|
219
|
+
async unlockOperationMode() {
|
|
220
|
+
try {
|
|
221
|
+
const { path, body } = mapUnlockOperationMode();
|
|
222
|
+
await this.session.post(path, body);
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
if (e instanceof RwsError)
|
|
226
|
+
throw e;
|
|
227
|
+
throw new RwsError(`unlockOperationMode failed: ${String(e)}`, 'UNKNOWN');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Switch the controller's operation mode. **Virtual controllers only** — on
|
|
232
|
+
* real IRC5 hardware the physical key switch on the FlexPendant is the
|
|
233
|
+
* source of truth and the controller will reject this with 403.
|
|
234
|
+
*
|
|
235
|
+
* RWS 1.0 endpoint: POST /rw/panel/opmode with body `opmode=auto|man|manfs`
|
|
236
|
+
* (note the lowercase pre-OmniCore values).
|
|
237
|
+
*/
|
|
238
|
+
async setOperationMode(mode) {
|
|
239
|
+
const wire = mode === 'AUTO' ? 'auto' : mode === 'MANR' ? 'man' : 'manfs';
|
|
240
|
+
try {
|
|
241
|
+
await this.session.post('/rw/panel/opmode', `opmode=${wire}`);
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
if (e instanceof RwsError) {
|
|
245
|
+
throw e;
|
|
246
|
+
}
|
|
247
|
+
throw new RwsError(`setOperationMode failed: ${String(e)}`, 'UNKNOWN');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// ─── Speed ratio ────────────────────────────────────────────────────────────
|
|
251
|
+
/**
|
|
252
|
+
* Read the current speed ratio (0–100).
|
|
253
|
+
* Represents override percentage applied to all robot speeds.
|
|
254
|
+
*/
|
|
255
|
+
async getSpeedRatio() {
|
|
256
|
+
try {
|
|
257
|
+
const { body } = await this.session.get(pathSpeedRatio());
|
|
258
|
+
return parseSpeedRatio(body);
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
if (e instanceof RwsError)
|
|
262
|
+
throw e;
|
|
263
|
+
throw new RwsError(`getSpeedRatio failed: ${String(e)}`, 'UNKNOWN');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Set the speed ratio override (0–100). Only valid in AUTO mode.
|
|
268
|
+
* @param ratio - Integer 0–100 (clamped automatically)
|
|
269
|
+
*/
|
|
270
|
+
async setSpeedRatio(ratio) {
|
|
271
|
+
try {
|
|
272
|
+
const { path, body } = mapSetSpeedRatio(ratio);
|
|
273
|
+
await this.session.post(path, body);
|
|
274
|
+
}
|
|
275
|
+
catch (e) {
|
|
276
|
+
if (e instanceof RwsError)
|
|
277
|
+
throw e;
|
|
278
|
+
throw new RwsError(`setSpeedRatio failed: ${String(e)}`, 'UNKNOWN');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
109
281
|
// ─── RAPID execution ────────────────────────────────────────────────────────
|
|
110
282
|
/**
|
|
111
283
|
* Read the current RAPID execution state.
|
|
@@ -123,6 +295,22 @@ export class RwsClient {
|
|
|
123
295
|
throw new RwsError(`getRapidExecutionState failed: ${String(e)}`, 'UNKNOWN');
|
|
124
296
|
}
|
|
125
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Read the full RAPID execution info including state and current cycle mode.
|
|
300
|
+
*
|
|
301
|
+
* @returns ExecutionInfo with state ('running'|'stopped') and cycle ('once'|'forever'|'asis'|'oncedone')
|
|
302
|
+
*/
|
|
303
|
+
async getRapidExecutionInfo() {
|
|
304
|
+
try {
|
|
305
|
+
const { body } = await this.session.get(pathRapidExecutionState());
|
|
306
|
+
return parseExecutionInfo(body);
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
if (e instanceof RwsError)
|
|
310
|
+
throw e;
|
|
311
|
+
throw new RwsError(`getRapidExecutionInfo failed: ${String(e)}`, 'UNKNOWN');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
126
314
|
/**
|
|
127
315
|
* Retrieve all RAPID tasks and their current states.
|
|
128
316
|
*
|
|
@@ -191,6 +379,222 @@ export class RwsClient {
|
|
|
191
379
|
throw new RwsError(`resetRapid failed: ${String(e)}`, 'UNKNOWN');
|
|
192
380
|
}
|
|
193
381
|
}
|
|
382
|
+
/**
|
|
383
|
+
* Set the RAPID execution cycle mode.
|
|
384
|
+
* @param cycle - 'once' (run once then stop) | 'forever' (loop) | 'asis' (keep current)
|
|
385
|
+
*/
|
|
386
|
+
async setExecutionCycle(cycle) {
|
|
387
|
+
try {
|
|
388
|
+
const { path, body } = mapSetExecutionCycle(cycle);
|
|
389
|
+
await this.session.post(path, body);
|
|
390
|
+
}
|
|
391
|
+
catch (e) {
|
|
392
|
+
if (e instanceof RwsError)
|
|
393
|
+
throw e;
|
|
394
|
+
throw new RwsError(`setExecutionCycle failed: ${String(e)}`, 'UNKNOWN');
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// ─── RAPID variables ────────────────────────────────────────────────────────
|
|
398
|
+
/**
|
|
399
|
+
* Read the value of a RAPID symbol (variable, persistent, or constant).
|
|
400
|
+
* Returns the raw string as the controller formats it (e.g. '42', '"hello"', '[1,2,3]').
|
|
401
|
+
*
|
|
402
|
+
* @param taskName - RAPID task name, e.g. 'T_ROB1'
|
|
403
|
+
* @param moduleName - Module name, e.g. 'user'
|
|
404
|
+
* @param symbolName - Symbol name, e.g. 'reg1'
|
|
405
|
+
*/
|
|
406
|
+
async getRapidVariable(taskName, moduleName, symbolName) {
|
|
407
|
+
try {
|
|
408
|
+
const { body } = await this.session.get(pathRapidSymbol(taskName, moduleName, symbolName));
|
|
409
|
+
return parseRapidSymbolValue(body);
|
|
410
|
+
}
|
|
411
|
+
catch (e) {
|
|
412
|
+
if (e instanceof RwsError)
|
|
413
|
+
throw e;
|
|
414
|
+
throw new RwsError(`getRapidVariable failed: ${String(e)}`, 'UNKNOWN');
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Write a value to a RAPID variable or persistent.
|
|
419
|
+
* Value must be a RAPID-formatted string: e.g. '42', '3.14', '"hello"', '[1,0,0,0]'.
|
|
420
|
+
*
|
|
421
|
+
* @param taskName - RAPID task name
|
|
422
|
+
* @param moduleName - Module name
|
|
423
|
+
* @param symbolName - Symbol name
|
|
424
|
+
* @param value - New value in RAPID syntax
|
|
425
|
+
*/
|
|
426
|
+
async setRapidVariable(taskName, moduleName, symbolName, value) {
|
|
427
|
+
try {
|
|
428
|
+
const { path, body } = mapSetRapidSymbol(taskName, moduleName, symbolName, value);
|
|
429
|
+
await this.session.post(path, body);
|
|
430
|
+
}
|
|
431
|
+
catch (e) {
|
|
432
|
+
if (e instanceof RwsError)
|
|
433
|
+
throw e;
|
|
434
|
+
throw new RwsError(`setRapidVariable failed: ${String(e)}`, 'UNKNOWN');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Activate a RAPID task (for multitasking systems).
|
|
439
|
+
* Mastership is taken internally by the controller.
|
|
440
|
+
* @param task - Task name, e.g. 'T_ROB2'
|
|
441
|
+
*/
|
|
442
|
+
async activateRapidTask(task) {
|
|
443
|
+
try {
|
|
444
|
+
const { path, body } = mapActivateRapidTask(task);
|
|
445
|
+
await this.session.post(path, body);
|
|
446
|
+
}
|
|
447
|
+
catch (e) {
|
|
448
|
+
if (e instanceof RwsError)
|
|
449
|
+
throw e;
|
|
450
|
+
throw new RwsError(`activateRapidTask failed: ${String(e)}`, 'UNKNOWN');
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Deactivate a RAPID task (for multitasking systems).
|
|
455
|
+
* @param task - Task name
|
|
456
|
+
*/
|
|
457
|
+
async deactivateRapidTask(task) {
|
|
458
|
+
try {
|
|
459
|
+
const { path, body } = mapDeactivateRapidTask(task);
|
|
460
|
+
await this.session.post(path, body);
|
|
461
|
+
}
|
|
462
|
+
catch (e) {
|
|
463
|
+
if (e instanceof RwsError)
|
|
464
|
+
throw e;
|
|
465
|
+
throw new RwsError(`deactivateRapidTask failed: ${String(e)}`, 'UNKNOWN');
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
/** Activate ALL RAPID tasks. */
|
|
469
|
+
async activateAllRapidTasks() {
|
|
470
|
+
try {
|
|
471
|
+
const { path, body } = mapActivateAllRapidTasks();
|
|
472
|
+
await this.session.post(path, body);
|
|
473
|
+
}
|
|
474
|
+
catch (e) {
|
|
475
|
+
if (e instanceof RwsError)
|
|
476
|
+
throw e;
|
|
477
|
+
throw new RwsError(`activateAllRapidTasks failed: ${String(e)}`, 'UNKNOWN');
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
/** Deactivate ALL RAPID tasks. */
|
|
481
|
+
async deactivateAllRapidTasks() {
|
|
482
|
+
try {
|
|
483
|
+
const { path, body } = mapDeactivateAllRapidTasks();
|
|
484
|
+
await this.session.post(path, body);
|
|
485
|
+
}
|
|
486
|
+
catch (e) {
|
|
487
|
+
if (e instanceof RwsError)
|
|
488
|
+
throw e;
|
|
489
|
+
throw new RwsError(`deactivateAllRapidTasks failed: ${String(e)}`, 'UNKNOWN');
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Get the currently active RAPID UI instruction.
|
|
494
|
+
* Returns null if no UI instruction is waiting for input.
|
|
495
|
+
* Used to detect when RAPID is waiting for operator input (TPReadNum, TPReadFK, etc.).
|
|
496
|
+
*/
|
|
497
|
+
async getActiveUiInstruction() {
|
|
498
|
+
try {
|
|
499
|
+
const { body } = await this.session.get(pathActiveUiInstruction());
|
|
500
|
+
return parseActiveUiInstruction(body);
|
|
501
|
+
}
|
|
502
|
+
catch (e) {
|
|
503
|
+
if (e instanceof RwsError)
|
|
504
|
+
throw e;
|
|
505
|
+
throw new RwsError(`getActiveUiInstruction failed: ${String(e)}`, 'UNKNOWN');
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Respond to an active RAPID UI instruction (e.g. send the answer to a TPReadNum).
|
|
510
|
+
* Get the stackurl from getActiveUiInstruction().stack.
|
|
511
|
+
*
|
|
512
|
+
* Common parameter names:
|
|
513
|
+
* - 'Result' — the answer value for TPReadNum, TPReadFK
|
|
514
|
+
* - 'TPFK1' … 'TPFK5' — individual function key states (0/1)
|
|
515
|
+
* - 'TPCompleted' — set to 'TRUE' when done
|
|
516
|
+
*
|
|
517
|
+
* @param stackurl - Stack URL from UiInstruction.stack (e.g. 'RAPID/T_ROB1/%$104')
|
|
518
|
+
* @param uiparam - Parameter name, e.g. 'Result'
|
|
519
|
+
* @param value - Value to set, e.g. '42' or 'TRUE'
|
|
520
|
+
*/
|
|
521
|
+
async setUiInstructionParam(stackurl, uiparam, value) {
|
|
522
|
+
try {
|
|
523
|
+
const { path, body } = mapSetUiInstructionParam(stackurl, uiparam, value);
|
|
524
|
+
await this.session.post(path, body);
|
|
525
|
+
}
|
|
526
|
+
catch (e) {
|
|
527
|
+
if (e instanceof RwsError)
|
|
528
|
+
throw e;
|
|
529
|
+
throw new RwsError(`setUiInstructionParam failed: ${String(e)}`, 'UNKNOWN');
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Search for RAPID symbols matching filter criteria.
|
|
534
|
+
*
|
|
535
|
+
* @param params - Search parameters (task is required; all others are optional filters)
|
|
536
|
+
* @returns Array of matching symbols with abbreviated properties
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```ts
|
|
540
|
+
* // Find all persistent variables in T_ROB1
|
|
541
|
+
* const persistents = await client.searchRapidSymbols({ task: 'T_ROB1', symtyp: 'per' });
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
544
|
+
async searchRapidSymbols(params) {
|
|
545
|
+
try {
|
|
546
|
+
const { path, body } = mapSearchRapidSymbols(params);
|
|
547
|
+
const { body: responseBody } = await this.session.post(path, body);
|
|
548
|
+
return parseRapidSymbolSearch(responseBody);
|
|
549
|
+
}
|
|
550
|
+
catch (e) {
|
|
551
|
+
if (e instanceof RwsError)
|
|
552
|
+
throw e;
|
|
553
|
+
throw new RwsError(`searchRapidSymbols failed: ${String(e)}`, 'UNKNOWN');
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Validate a value against a RAPID data type without writing it.
|
|
558
|
+
* Useful for validating user input before calling setRapidVariable.
|
|
559
|
+
*
|
|
560
|
+
* @param task - RAPID task name, e.g. 'T_ROB1'
|
|
561
|
+
* @param value - Value in RAPID syntax, e.g. '[1,0,0,0]'
|
|
562
|
+
* @param datatype - RAPID data type name, e.g. 'tooldata', 'robtarget', 'num'
|
|
563
|
+
* @returns true if valid, false if invalid (no exception thrown for invalid values)
|
|
564
|
+
*/
|
|
565
|
+
async validateRapidValue(task, value, datatype) {
|
|
566
|
+
try {
|
|
567
|
+
const { path, body } = mapValidateRapidValue(task, value, datatype);
|
|
568
|
+
const { status } = await this.session.post(path, body);
|
|
569
|
+
return status === 204;
|
|
570
|
+
}
|
|
571
|
+
catch (e) {
|
|
572
|
+
if (e instanceof RwsError && e.httpStatus === 400)
|
|
573
|
+
return false;
|
|
574
|
+
if (e instanceof RwsError)
|
|
575
|
+
throw e;
|
|
576
|
+
throw new RwsError(`validateRapidValue failed: ${String(e)}`, 'UNKNOWN');
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Read RAPID symbol properties (type, dimensions, storage class, etc.).
|
|
581
|
+
* Useful for introspecting variables, persistents, constants, and records.
|
|
582
|
+
*
|
|
583
|
+
* @param taskName - RAPID task name, e.g. 'T_ROB1'
|
|
584
|
+
* @param moduleName - Module name, e.g. 'user'
|
|
585
|
+
* @param symbolName - Symbol name, e.g. 'reg1'
|
|
586
|
+
*/
|
|
587
|
+
async getRapidSymbolProperties(taskName, moduleName, symbolName) {
|
|
588
|
+
try {
|
|
589
|
+
const { body } = await this.session.get(pathRapidSymbolProperties(taskName, moduleName, symbolName));
|
|
590
|
+
return parseRapidSymbolProperties(body);
|
|
591
|
+
}
|
|
592
|
+
catch (e) {
|
|
593
|
+
if (e instanceof RwsError)
|
|
594
|
+
throw e;
|
|
595
|
+
throw new RwsError(`getRapidSymbolProperties failed: ${String(e)}`, 'UNKNOWN');
|
|
596
|
+
}
|
|
597
|
+
}
|
|
194
598
|
// ─── Motion ─────────────────────────────────────────────────────────────────
|
|
195
599
|
/**
|
|
196
600
|
* Read the current joint-space positions for a mechanical unit.
|
|
@@ -228,6 +632,24 @@ export class RwsClient {
|
|
|
228
632
|
throw new RwsError(`getCartesianPosition failed: ${String(e)}`, 'UNKNOWN');
|
|
229
633
|
}
|
|
230
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* Read the current Cartesian position including robot configuration flags.
|
|
637
|
+
* Uses /cartesian endpoint (no tool/wobj override — uses active tool/wobj).
|
|
638
|
+
* Returns j1/j4/j6/jx configuration integers in addition to pose.
|
|
639
|
+
*
|
|
640
|
+
* @param mechunit - Default 'ROB_1'
|
|
641
|
+
*/
|
|
642
|
+
async getCartesianFull(mechunit) {
|
|
643
|
+
try {
|
|
644
|
+
const { body } = await this.session.get(pathCartesianFull(mechunit));
|
|
645
|
+
return parseCartesianFull(body);
|
|
646
|
+
}
|
|
647
|
+
catch (e) {
|
|
648
|
+
if (e instanceof RwsError)
|
|
649
|
+
throw e;
|
|
650
|
+
throw new RwsError(`getCartesianFull failed: ${String(e)}`, 'UNKNOWN');
|
|
651
|
+
}
|
|
652
|
+
}
|
|
231
653
|
// ─── Modules ────────────────────────────────────────────────────────────────
|
|
232
654
|
/**
|
|
233
655
|
* Download a file from the controller filesystem as a UTF-8 string.
|
|
@@ -249,13 +671,14 @@ export class RwsClient {
|
|
|
249
671
|
}
|
|
250
672
|
}
|
|
251
673
|
/**
|
|
252
|
-
* Upload a
|
|
253
|
-
* The
|
|
674
|
+
* Upload a file to the controller filesystem.
|
|
675
|
+
* The content is uploaded as UTF-8 bytes via PUT /fileservice/{remotePath}.
|
|
676
|
+
* Works for any file type — RAPID modules, .cfg files, plain text, etc.
|
|
254
677
|
*
|
|
255
678
|
* @param remotePath - Controller path, e.g. '$HOME/MyMod.mod'
|
|
256
|
-
* @param content -
|
|
679
|
+
* @param content - File content as a string
|
|
257
680
|
*/
|
|
258
|
-
async
|
|
681
|
+
async uploadFile(remotePath, content) {
|
|
259
682
|
try {
|
|
260
683
|
const path = pathUploadFile(remotePath);
|
|
261
684
|
const bytes = new TextEncoder().encode(content);
|
|
@@ -264,9 +687,13 @@ export class RwsClient {
|
|
|
264
687
|
catch (e) {
|
|
265
688
|
if (e instanceof RwsError)
|
|
266
689
|
throw e;
|
|
267
|
-
throw new RwsError(`
|
|
690
|
+
throw new RwsError(`uploadFile failed: ${String(e)}`, 'UNKNOWN');
|
|
268
691
|
}
|
|
269
692
|
}
|
|
693
|
+
/** @deprecated use uploadFile() — same behavior, neutral name. Kept for backward compat. */
|
|
694
|
+
uploadModule(remotePath, content) {
|
|
695
|
+
return this.uploadFile(remotePath, content);
|
|
696
|
+
}
|
|
270
697
|
/**
|
|
271
698
|
* Unload a RAPID module from a task (remove it from memory).
|
|
272
699
|
* RAPID must be stopped before calling this.
|
|
@@ -324,6 +751,71 @@ export class RwsClient {
|
|
|
324
751
|
throw new RwsError(`listModules failed: ${String(e)}`, 'UNKNOWN');
|
|
325
752
|
}
|
|
326
753
|
}
|
|
754
|
+
/**
|
|
755
|
+
* Download a directory listing from the controller filesystem.
|
|
756
|
+
* Returns entries sorted: directories first, then files.
|
|
757
|
+
*
|
|
758
|
+
* @param remotePath - Controller path, e.g. '$HOME' or '$HOME/Dispense'
|
|
759
|
+
*/
|
|
760
|
+
async listDirectory(remotePath) {
|
|
761
|
+
try {
|
|
762
|
+
const { body } = await this.session.get(fileServicePath(remotePath));
|
|
763
|
+
return parseDirectory(body);
|
|
764
|
+
}
|
|
765
|
+
catch (e) {
|
|
766
|
+
if (e instanceof RwsError)
|
|
767
|
+
throw e;
|
|
768
|
+
throw new RwsError(`listDirectory failed: ${String(e)}`, 'UNKNOWN');
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Delete a file from the controller filesystem.
|
|
773
|
+
* @param remotePath - Controller path, e.g. '$HOME/OldMod.mod'
|
|
774
|
+
*/
|
|
775
|
+
async deleteFile(remotePath) {
|
|
776
|
+
try {
|
|
777
|
+
await this.session.delete(pathDeleteFile(remotePath));
|
|
778
|
+
}
|
|
779
|
+
catch (e) {
|
|
780
|
+
if (e instanceof RwsError)
|
|
781
|
+
throw e;
|
|
782
|
+
throw new RwsError(`deleteFile failed: ${String(e)}`, 'UNKNOWN');
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Create a directory on the controller filesystem.
|
|
787
|
+
* @param parentPath - Parent directory path, e.g. '$HOME'
|
|
788
|
+
* @param dirName - New directory name, e.g. 'Backup'
|
|
789
|
+
*/
|
|
790
|
+
async createDirectory(parentPath, dirName) {
|
|
791
|
+
try {
|
|
792
|
+
const path = fileServicePath(parentPath);
|
|
793
|
+
// RWS 1.0 fileservice expects params in the body, not the query string.
|
|
794
|
+
// Putting fs-action in the URL returns 400 "Invalid/No Query Parameter".
|
|
795
|
+
await this.session.post(path, `fs-action=create&fs-newname=${encodeURIComponent(dirName)}`);
|
|
796
|
+
}
|
|
797
|
+
catch (e) {
|
|
798
|
+
if (e instanceof RwsError)
|
|
799
|
+
throw e;
|
|
800
|
+
throw new RwsError(`createDirectory failed: ${String(e)}`, 'UNKNOWN');
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Copy a file on the controller filesystem.
|
|
805
|
+
* @param sourcePath - Source file path, e.g. '$HOME/MyMod.mod'
|
|
806
|
+
* @param destPath - Destination path (full path including filename), e.g. '$HOME/Backup/MyMod.mod'
|
|
807
|
+
*/
|
|
808
|
+
async copyFile(sourcePath, destPath) {
|
|
809
|
+
try {
|
|
810
|
+
const { path, body } = mapCopyFile(sourcePath, destPath);
|
|
811
|
+
await this.session.post(path, body);
|
|
812
|
+
}
|
|
813
|
+
catch (e) {
|
|
814
|
+
if (e instanceof RwsError)
|
|
815
|
+
throw e;
|
|
816
|
+
throw new RwsError(`copyFile failed: ${String(e)}`, 'UNKNOWN');
|
|
817
|
+
}
|
|
818
|
+
}
|
|
327
819
|
// ─── I/O signals ────────────────────────────────────────────────────────────
|
|
328
820
|
/**
|
|
329
821
|
* Read an I/O signal value.
|
|
@@ -363,6 +855,202 @@ export class RwsClient {
|
|
|
363
855
|
throw new RwsError(`writeSignal failed: ${String(e)}`, 'UNKNOWN');
|
|
364
856
|
}
|
|
365
857
|
}
|
|
858
|
+
/**
|
|
859
|
+
* List all configured I/O signals (paginated).
|
|
860
|
+
* The controller returns up to `limit` signals per call; use `start` to page through.
|
|
861
|
+
*
|
|
862
|
+
* @param start - Starting index (default 0)
|
|
863
|
+
* @param limit - Results per page (default 100)
|
|
864
|
+
*/
|
|
865
|
+
async listAllSignals(start = 0, limit = 100) {
|
|
866
|
+
try {
|
|
867
|
+
const { body } = await this.session.get(pathAllSignals(start, limit));
|
|
868
|
+
return parseSignalList(body);
|
|
869
|
+
}
|
|
870
|
+
catch (e) {
|
|
871
|
+
if (e instanceof RwsError)
|
|
872
|
+
throw e;
|
|
873
|
+
throw new RwsError(`listAllSignals failed: ${String(e)}`, 'UNKNOWN');
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* List all configured I/O networks.
|
|
878
|
+
*/
|
|
879
|
+
async listNetworks() {
|
|
880
|
+
try {
|
|
881
|
+
const { body } = await this.session.get(pathNetworks());
|
|
882
|
+
return parseNetworks(body);
|
|
883
|
+
}
|
|
884
|
+
catch (e) {
|
|
885
|
+
if (e instanceof RwsError)
|
|
886
|
+
throw e;
|
|
887
|
+
throw new RwsError(`listNetworks failed: ${String(e)}`, 'UNKNOWN');
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* List all I/O devices on a network.
|
|
892
|
+
* @param network - Network name, e.g. 'Local'
|
|
893
|
+
*/
|
|
894
|
+
async listDevices(network) {
|
|
895
|
+
try {
|
|
896
|
+
const { body } = await this.session.get(pathDevices(network));
|
|
897
|
+
return parseDevices(body);
|
|
898
|
+
}
|
|
899
|
+
catch (e) {
|
|
900
|
+
if (e instanceof RwsError)
|
|
901
|
+
throw e;
|
|
902
|
+
throw new RwsError(`listDevices failed: ${String(e)}`, 'UNKNOWN');
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
// ─── Controller info ────────────────────────────────────────────────────────
|
|
906
|
+
/**
|
|
907
|
+
* Read RobotWare system information (version, options, system ID).
|
|
908
|
+
*/
|
|
909
|
+
async getSystemInfo() {
|
|
910
|
+
try {
|
|
911
|
+
const { body } = await this.session.get(pathSystemInfo());
|
|
912
|
+
return parseSystemInfo(body);
|
|
913
|
+
}
|
|
914
|
+
catch (e) {
|
|
915
|
+
if (e instanceof RwsError)
|
|
916
|
+
throw e;
|
|
917
|
+
throw new RwsError(`getSystemInfo failed: ${String(e)}`, 'UNKNOWN');
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Read controller hardware identity (name, ID, type, MAC address).
|
|
922
|
+
*/
|
|
923
|
+
async getControllerIdentity() {
|
|
924
|
+
try {
|
|
925
|
+
const { body } = await this.session.get(pathControllerIdentity());
|
|
926
|
+
return parseControllerIdentity(body);
|
|
927
|
+
}
|
|
928
|
+
catch (e) {
|
|
929
|
+
if (e instanceof RwsError)
|
|
930
|
+
throw e;
|
|
931
|
+
throw new RwsError(`getControllerIdentity failed: ${String(e)}`, 'UNKNOWN');
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Read the controller date and time.
|
|
936
|
+
* Returns a ControllerClock with the datetime string in 'YYYY-MM-DD T HH:MM:SS' format (UTC).
|
|
937
|
+
*/
|
|
938
|
+
async getControllerClock() {
|
|
939
|
+
try {
|
|
940
|
+
const { body } = await this.session.get(pathClockInfo());
|
|
941
|
+
return parseControllerClock(body);
|
|
942
|
+
}
|
|
943
|
+
catch (e) {
|
|
944
|
+
if (e instanceof RwsError)
|
|
945
|
+
throw e;
|
|
946
|
+
throw new RwsError(`getControllerClock failed: ${String(e)}`, 'UNKNOWN');
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* Set the controller date and time (UTC).
|
|
951
|
+
* @param year - Full year, e.g. 2024
|
|
952
|
+
* @param month - Month 1–12
|
|
953
|
+
* @param day - Day 1–31
|
|
954
|
+
* @param hour - Hour 0–23
|
|
955
|
+
* @param min - Minute 0–59
|
|
956
|
+
* @param sec - Second 0–59
|
|
957
|
+
*/
|
|
958
|
+
async setControllerClock(year, month, day, hour, min, sec) {
|
|
959
|
+
try {
|
|
960
|
+
const { path, body } = mapSetControllerClock(year, month, day, hour, min, sec);
|
|
961
|
+
await this.session.put(path, new TextEncoder().encode(body));
|
|
962
|
+
}
|
|
963
|
+
catch (e) {
|
|
964
|
+
if (e instanceof RwsError)
|
|
965
|
+
throw e;
|
|
966
|
+
throw new RwsError(`setControllerClock failed: ${String(e)}`, 'UNKNOWN');
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
// ─── Event log ──────────────────────────────────────────────────────────────
|
|
970
|
+
/**
|
|
971
|
+
* Retrieve event log messages from the controller.
|
|
972
|
+
* Domain 0 is the main system log (up to 1000 entries).
|
|
973
|
+
* Messages are returned newest-first (LIFO order).
|
|
974
|
+
*
|
|
975
|
+
* @param domain - Log domain number; default 0 (main system log)
|
|
976
|
+
* @param lang - Language for message text; default 'en'
|
|
977
|
+
*/
|
|
978
|
+
async getEventLog(domain = 0, lang = 'en') {
|
|
979
|
+
try {
|
|
980
|
+
const { body } = await this.session.get(pathElogMessages(domain, lang));
|
|
981
|
+
return parseElogMessages(body);
|
|
982
|
+
}
|
|
983
|
+
catch (e) {
|
|
984
|
+
if (e instanceof RwsError)
|
|
985
|
+
throw e;
|
|
986
|
+
throw new RwsError(`getEventLog failed: ${String(e)}`, 'UNKNOWN');
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Clear event log messages in a specific domain.
|
|
991
|
+
* @param domain - Log domain number; default 0 (main system log)
|
|
992
|
+
*/
|
|
993
|
+
async clearEventLog(domain = 0) {
|
|
994
|
+
try {
|
|
995
|
+
const { path, body } = mapClearElogDomain(domain);
|
|
996
|
+
await this.session.post(path, body);
|
|
997
|
+
}
|
|
998
|
+
catch (e) {
|
|
999
|
+
if (e instanceof RwsError)
|
|
1000
|
+
throw e;
|
|
1001
|
+
throw new RwsError(`clearEventLog failed: ${String(e)}`, 'UNKNOWN');
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Clear ALL event log messages across all domains.
|
|
1006
|
+
*/
|
|
1007
|
+
async clearAllEventLogs() {
|
|
1008
|
+
try {
|
|
1009
|
+
const { path, body } = mapClearAllElogs();
|
|
1010
|
+
await this.session.post(path, body);
|
|
1011
|
+
}
|
|
1012
|
+
catch (e) {
|
|
1013
|
+
if (e instanceof RwsError)
|
|
1014
|
+
throw e;
|
|
1015
|
+
throw new RwsError(`clearAllEventLogs failed: ${String(e)}`, 'UNKNOWN');
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
// ─── Mastership ──────────────────────────────────────────────────────────────
|
|
1019
|
+
/**
|
|
1020
|
+
* Request mastership on a domain.
|
|
1021
|
+
* Must call releaseMastership when done. Operations that modify controller state
|
|
1022
|
+
* (motor on/off, speed ratio, etc.) require mastership on the appropriate domain.
|
|
1023
|
+
*
|
|
1024
|
+
* @param domain - 'cfg' | 'motion' | 'rapid'
|
|
1025
|
+
*/
|
|
1026
|
+
async requestMastership(domain) {
|
|
1027
|
+
try {
|
|
1028
|
+
const { path, body } = mapRequestMastership(domain);
|
|
1029
|
+
await this.session.post(path, body);
|
|
1030
|
+
}
|
|
1031
|
+
catch (e) {
|
|
1032
|
+
if (e instanceof RwsError)
|
|
1033
|
+
throw e;
|
|
1034
|
+
throw new RwsError(`requestMastership failed: ${String(e)}`, 'UNKNOWN');
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Release mastership on a domain.
|
|
1039
|
+
* Always call this after requestMastership, even if the operation failed.
|
|
1040
|
+
*
|
|
1041
|
+
* @param domain - 'cfg' | 'motion' | 'rapid'
|
|
1042
|
+
*/
|
|
1043
|
+
async releaseMastership(domain) {
|
|
1044
|
+
try {
|
|
1045
|
+
const { path, body } = mapReleaseMastership(domain);
|
|
1046
|
+
await this.session.post(path, body);
|
|
1047
|
+
}
|
|
1048
|
+
catch (e) {
|
|
1049
|
+
if (e instanceof RwsError)
|
|
1050
|
+
throw e;
|
|
1051
|
+
throw new RwsError(`releaseMastership failed: ${String(e)}`, 'UNKNOWN');
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
366
1054
|
// ─── Subscriptions ──────────────────────────────────────────────────────────
|
|
367
1055
|
/**
|
|
368
1056
|
* Subscribe to one or more RWS resource events via WebSocket.
|