abb-rws-client 0.7.2 → 1.0.0

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +17 -8
  3. package/dist/HalJsonParser.d.ts +55 -0
  4. package/dist/HalJsonParser.d.ts.map +1 -0
  5. package/dist/HalJsonParser.js +155 -0
  6. package/dist/HalJsonParser.js.map +1 -0
  7. package/dist/HttpSession.d.ts.map +1 -1
  8. package/dist/HttpSession.js +13 -2
  9. package/dist/HttpSession.js.map +1 -1
  10. package/dist/IRWSAdapter.d.ts +7 -1
  11. package/dist/IRWSAdapter.d.ts.map +1 -1
  12. package/dist/MdnsDiscovery.d.ts +57 -0
  13. package/dist/MdnsDiscovery.d.ts.map +1 -0
  14. package/dist/MdnsDiscovery.js +313 -0
  15. package/dist/MdnsDiscovery.js.map +1 -0
  16. package/dist/MultiRobotManager.d.ts +5 -2
  17. package/dist/MultiRobotManager.d.ts.map +1 -1
  18. package/dist/MultiRobotManager.js +8 -3
  19. package/dist/MultiRobotManager.js.map +1 -1
  20. package/dist/RWS1Adapter.d.ts +60 -2
  21. package/dist/RWS1Adapter.d.ts.map +1 -1
  22. package/dist/RWS1Adapter.js +152 -4
  23. package/dist/RWS1Adapter.js.map +1 -1
  24. package/dist/ResourceMapper.d.ts +4 -0
  25. package/dist/ResourceMapper.d.ts.map +1 -1
  26. package/dist/ResourceMapper.js +9 -1
  27. package/dist/ResourceMapper.js.map +1 -1
  28. package/dist/RobotManager.d.ts +72 -12
  29. package/dist/RobotManager.d.ts.map +1 -1
  30. package/dist/RobotManager.js +255 -50
  31. package/dist/RobotManager.js.map +1 -1
  32. package/dist/RwsClient2.d.ts +150 -10
  33. package/dist/RwsClient2.d.ts.map +1 -1
  34. package/dist/RwsClient2.js +599 -236
  35. package/dist/RwsClient2.js.map +1 -1
  36. package/dist/WsSubscriber.d.ts +31 -5
  37. package/dist/WsSubscriber.d.ts.map +1 -1
  38. package/dist/WsSubscriber.js +104 -50
  39. package/dist/WsSubscriber.js.map +1 -1
  40. package/dist/detect.d.ts +12 -3
  41. package/dist/detect.d.ts.map +1 -1
  42. package/dist/detect.js +69 -25
  43. package/dist/detect.js.map +1 -1
  44. package/dist/index.d.ts +3 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +2 -0
  47. package/dist/index.js.map +1 -1
  48. package/dist/types.js +3 -3
  49. package/dist/types.js.map +1 -1
  50. package/examples/05-remote-control-rmmp.mjs +10 -12
  51. package/examples/06-pull-module-source.mjs +13 -20
  52. package/package.json +62 -60
  53. package/src/HalJsonParser.ts +137 -0
  54. package/src/HttpSession.ts +460 -0
  55. package/src/IRWSAdapter.ts +422 -0
  56. package/src/Logger.ts +54 -0
  57. package/src/MdnsDiscovery.ts +336 -0
  58. package/src/MultiRobotManager.ts +159 -0
  59. package/src/RWS1Adapter.ts +1018 -0
  60. package/src/RWS2Adapter.ts +19 -0
  61. package/src/ResourceMapper.ts +517 -0
  62. package/src/ResponseParser.ts +710 -0
  63. package/src/RobotManager.ts +1705 -0
  64. package/src/RwsClient.ts +1150 -0
  65. package/src/RwsClient2.ts +2214 -0
  66. package/src/WsSubscriber.ts +350 -0
  67. package/src/XhtmlParser.ts +53 -0
  68. package/src/detect.ts +261 -0
  69. package/src/index.ts +83 -0
  70. package/src/types.ts +336 -0
@@ -0,0 +1,422 @@
1
+ import type {
2
+ ControllerState, OperationMode, ExecutionState, ExecutionCycle,
3
+ ExecutionInfo, CollisionDetectionState, RapidTask, JointTarget,
4
+ CartesianFull, RobTarget, SystemInfo, ControllerIdentity, ControllerClock,
5
+ ElogMessage, Signal, IoNetwork, IoDevice, FileEntry,
6
+ RapidSymbolProperties, RapidSymbolInfo, RapidSymbolSearchParams,
7
+ UiInstruction, RestartMode, MastershipDomain,
8
+ SubscriptionResource, SubscriptionEvent,
9
+ } from './types.js';
10
+
11
+ /** Common interface for both RWS1Adapter (IRC5 / RW6) and RWS2Adapter (OmniCore / RW7). */
12
+ export interface IRWSAdapter {
13
+ // ── Connection ───────────────────────────────────────────────────────────
14
+ connect(): Promise<void>;
15
+ disconnect(): Promise<void>;
16
+ getSessionCookie(): string | null;
17
+
18
+ // ── Panel ────────────────────────────────────────────────────────────────
19
+ getControllerState(): Promise<ControllerState>;
20
+ setControllerState(state: 'motoron' | 'motoroff'): Promise<void>;
21
+ getOperationMode(): Promise<OperationMode>;
22
+ getSpeedRatio(): Promise<number>;
23
+ setSpeedRatio(ratio: number): Promise<void>;
24
+ getCollisionDetectionState(): Promise<CollisionDetectionState>;
25
+ lockOperationMode(pin: string, permanent?: boolean): Promise<void>;
26
+ unlockOperationMode(): Promise<void>;
27
+ /**
28
+ * Switch the controller's operation mode (AUTO/MANR/MANF).
29
+ * **Virtual controllers only** — real hardware respects the FlexPendant key
30
+ * switch and will reject this with 403 (or silently keep the current mode).
31
+ */
32
+ setOperationMode?(mode: 'AUTO' | 'MANR' | 'MANF'): Promise<void>;
33
+
34
+ // ── RAPID execution ──────────────────────────────────────────────────────
35
+ getRapidExecutionState(): Promise<ExecutionState>;
36
+ getRapidExecutionInfo(): Promise<ExecutionInfo>;
37
+ startRapid(): Promise<void>;
38
+ stopRapid(): Promise<void>;
39
+ resetRapid(): Promise<void>;
40
+ setExecutionCycle(cycle: ExecutionCycle): Promise<void>;
41
+ getRapidTasks(): Promise<RapidTask[]>;
42
+ activateRapidTask(task: string): Promise<void>;
43
+ deactivateRapidTask(task: string): Promise<void>;
44
+ activateAllRapidTasks(): Promise<void>;
45
+ deactivateAllRapidTasks(): Promise<void>;
46
+
47
+ // ── RAPID modules & variables ────────────────────────────────────────────
48
+ listModules(task: string): Promise<string[]>;
49
+ /**
50
+ * Detailed module list — returns each module's name AND type
51
+ * (`SysMod` for system modules / `ProgMod` for program modules / etc.).
52
+ * Optional — adapter may return an empty array if the underlying API is
53
+ * unavailable. Callers should fall back to `listModules` for the names.
54
+ */
55
+ listModulesDetailed?(task: string): Promise<Array<{ name: string; type: string }>>;
56
+ loadModule(task: string, path: string, replace?: boolean): Promise<void>;
57
+ unloadModule(task: string, name: string): Promise<void>;
58
+ getRapidVariable(task: string, module: string, symbol: string): Promise<string>;
59
+ setRapidVariable(task: string, module: string, symbol: string, value: string): Promise<void>;
60
+ validateRapidValue(task: string, value: string, datatype: string): Promise<boolean>;
61
+ getRapidSymbolProperties(task: string, module: string, symbol: string): Promise<RapidSymbolProperties>;
62
+ searchRapidSymbols(params: RapidSymbolSearchParams): Promise<RapidSymbolInfo[]>;
63
+ getActiveUiInstruction(): Promise<UiInstruction | null>;
64
+ setUiInstructionParam(stackurl: string, uiparam: string, value: string): Promise<void>;
65
+
66
+ // ── Motion ───────────────────────────────────────────────────────────────
67
+ getJointPositions(mechunit?: string): Promise<JointTarget>;
68
+ getCartesianFull(mechunit?: string): Promise<CartesianFull>;
69
+ listMechunits(): Promise<string[]>;
70
+
71
+ /**
72
+ * Inverse kinematics: compute joint angles from a Cartesian position.
73
+ * Uses the current joint positions as a seed for the solution.
74
+ * Tool and work-object default to tool0/wobj0 (base frame, no offset).
75
+ *
76
+ * Confirmed parameter format (both RWS versions, tested by sequential field probing):
77
+ * curr_position, curr_orientation, curr_ext_joints, old_rob_joints, old_ext_joints,
78
+ * robot_fixed_object, tool_frame_position/orientation, wobj_frame_position/orientation,
79
+ * robot_configuration, elog_at_error
80
+ *
81
+ * Note: virtual controllers (RobotStudio) reject every input with HTTP 400
82
+ * "Position outside of reach" (SYS_CTRL_E_POSE_OUTSIDE_REACH, -1073436654) —
83
+ * even the controller's own current pose. This is a VC-only limitation: the
84
+ * standard VC ships without the PC Interface (616-1) option that enables the
85
+ * full kinematic solver, and wobj0 can desync from the displayed mechanism.
86
+ * Real IRC5 / OmniCore hardware with PC Interface licensed returns valid
87
+ * joint angles for any reachable pose.
88
+ */
89
+ calcJointsFromCartesian(
90
+ pos: RobTarget,
91
+ seedJoints?: JointTarget,
92
+ mechunit?: string,
93
+ ): Promise<JointTarget>;
94
+
95
+ /**
96
+ * Jog the robot by specified increments. Requires:
97
+ * - Controller in MANR or MANF mode (not AUTO)
98
+ * - Motors ON
99
+ * - Motion-domain mastership held (callers should wrap with requestMastership('motion'))
100
+ *
101
+ * @param mode 'Joint' for axis-by-axis (degrees), 'Cartesian' for X/Y/Z + orientation (mm)
102
+ * @param axes 6 increment values, one per axis. Zero means don't move that axis.
103
+ * @param speed Jog speed percentage (0-100). 0 sends the request without moving.
104
+ * @param mechunit Mechanical unit name (defaults to ROB_1).
105
+ */
106
+ jog(params: {
107
+ mode: 'Joint' | 'Cartesian';
108
+ axes: [number, number, number, number, number, number];
109
+ speed: number;
110
+ mechunit?: string;
111
+ }): Promise<void>;
112
+
113
+ /**
114
+ * Get the current Remote Mastership Privilege state for the connected user.
115
+ * 'none' = no privilege, 'pending modify' = request waiting for FlexPendant approval,
116
+ * 'modify' = approved (can send modifying ops like jog), 'exclusive' = full control.
117
+ */
118
+ getRmmpPrivilege?(): Promise<string>;
119
+
120
+ /** Request 'modify' RMMP. Triggers a FlexPendant approval popup. Returns immediately. */
121
+ requestRmmp?(level?: 'modify' | 'exclusive'): Promise<void>;
122
+
123
+ // ── System info ──────────────────────────────────────────────────────────
124
+ getSystemInfo(): Promise<SystemInfo>;
125
+ getControllerIdentity(): Promise<ControllerIdentity>;
126
+ getControllerClock(): Promise<ControllerClock>;
127
+ setControllerClock(year: number, month: number, day: number, hour: number, min: number, sec: number): Promise<void>;
128
+ restartController(mode: RestartMode): Promise<void>;
129
+
130
+ // ── System detail endpoints ──────────────────────────────────────────────
131
+ /** Active license info from `/rw/system/license`. */
132
+ getLicenseInfo?(): Promise<{ entries: Array<Record<string, string>> }>;
133
+ /** Installed RobotWare products from `/rw/system/products`. */
134
+ listProducts?(): Promise<Array<Record<string, string>>>;
135
+ /** Robot type identifier from `/rw/system/robottype`. */
136
+ getRobotType?(): Promise<{ type: string; variant?: string }>;
137
+ /** Power-consumption stats from `/rw/system/energy` (RW7+). */
138
+ getEnergyStats?(): Promise<Record<string, string>>;
139
+
140
+ // ── Return-code lookup ───────────────────────────────────────────────────
141
+ /** Translate a numeric controller return code to its title/description via `/rw/retcode?code=N&lang=en`. */
142
+ getReturnCode?(code: number, lang?: string): Promise<{ code: number; title: string; desc: string } | null>;
143
+
144
+ // ── Controller detail endpoints ──────────────────────────────────────────
145
+ /** Detailed installed-options list from `/ctrl/options` (richer than getSystemInfo's options array). */
146
+ listControllerOptions?(): Promise<Array<{ name: string; description?: string }>>;
147
+ /** Optional hardware/firmware features from `/ctrl/features`. */
148
+ listFeatures?(): Promise<Array<Record<string, string>>>;
149
+
150
+ // ── Motion detail endpoints ─────────────────────────────────────────────
151
+ /** Read the motion-system change counter (required by jog `ccount`). */
152
+ getMotionChangeCount?(): Promise<number>;
153
+ /** Current motion-error state from `/rw/motionsystem/errorstate`. */
154
+ getMotionErrorState?(): Promise<{ state: string; details?: Record<string, string> }>;
155
+ /** Get/set non-motion-execution mode (dry-run). */
156
+ getNonMotionExecution?(): Promise<boolean>;
157
+ setNonMotionExecution?(enabled: boolean): Promise<void>;
158
+ /** OmniCore-only: collision-prediction mode. */
159
+ getCollisionPredictionMode?(): Promise<string>;
160
+ setCollisionPredictionMode?(mode: string): Promise<void>;
161
+
162
+ // ── Panel detail endpoints ──────────────────────────────────────────────
163
+ /** Read the enable-request state (relates to deadman / safety chain). */
164
+ getEnableRequest?(): Promise<{ state: string; raw: Record<string, string> }>;
165
+
166
+ // ── RAPID detail endpoints ──────────────────────────────────────────────
167
+ /** I/O alias mapping from `/rw/rapid/aliasio`. */
168
+ listAliasIO?(): Promise<Array<{ alias: string; signal: string }>>;
169
+ /** Active task selector from `/rw/rapid/taskselection`. */
170
+ getTaskSelection?(): Promise<{ selected: string[]; available: string[] }>;
171
+ setTaskSelection?(tasks: string[]): Promise<void>;
172
+ /** Program-pointer position for a task. */
173
+ getProgramPointer?(task: string): Promise<{ module?: string; routine?: string; row?: number; col?: number }>;
174
+ /** Motion-pointer (ahead of PP — what the motion planner is executing). */
175
+ getMotionPointer?(task: string): Promise<{ module?: string; routine?: string; row?: number; col?: number }>;
176
+
177
+ // ── Event log ────────────────────────────────────────────────────────────
178
+ getEventLog(domain?: number, lang?: string): Promise<ElogMessage[]>;
179
+ clearEventLog(domain?: number): Promise<void>;
180
+ clearAllEventLogs(): Promise<void>;
181
+
182
+ // ── I/O ──────────────────────────────────────────────────────────────────
183
+ listAllSignals(start?: number, limit?: number): Promise<Signal[]>;
184
+ readSignal(network: string, device: string, name: string): Promise<Signal>;
185
+ writeSignal(network: string, device: string, name: string, value: string): Promise<void>;
186
+ listNetworks(): Promise<IoNetwork[]>;
187
+ listDevices(network: string): Promise<IoDevice[]>;
188
+
189
+ // ── File system ──────────────────────────────────────────────────────────
190
+ listDirectory(path: string): Promise<FileEntry[]>;
191
+ readFile(path: string): Promise<string>;
192
+ uploadFile(path: string, content: string): Promise<void>;
193
+ deleteFile(path: string): Promise<void>;
194
+ createDirectory(parentPath: string, dirName: string): Promise<void>;
195
+ copyFile(sourcePath: string, destPath: string): Promise<void>;
196
+
197
+ // ── Configuration database `/rw/cfg` ─────────────────────────────────────
198
+ // 6 domains: EIO, MMC, MOC, PROC, SIO, SYS — each with many types (e.g. MOC has
199
+ // ARM, ARM_TYPE, JOINT, MOTOR, ROBOT_TYPE, SINGLE, etc.).
200
+
201
+ /** List the 6 configuration domains. */
202
+ listCfgDomains?(): Promise<string[]>;
203
+ /** List the types defined in a domain (e.g. ['ARM', 'JOINT', 'MOTOR'] for MOC). */
204
+ listCfgTypes?(domain: string): Promise<string[]>;
205
+ /** List instance names of a given type (e.g. ROB_1, ROB_L1 under MOC/ARM). */
206
+ listCfgInstances?(domain: string, type: string): Promise<string[]>;
207
+ /** Read a single configuration instance — returns the named attributes for that instance. */
208
+ getCfgInstance?(domain: string, type: string, instance: string): Promise<Record<string, string>>;
209
+ /** Update an existing configuration instance. Requires 'edit' mastership. */
210
+ setCfgInstance?(domain: string, type: string, instance: string, attributes: Record<string, string>): Promise<void>;
211
+ /** Create a new instance of a type. Requires 'edit' mastership. */
212
+ createCfgInstance?(domain: string, type: string, instance: string, attributes: Record<string, string>): Promise<void>;
213
+ /** Delete an instance. Requires 'edit' mastership. */
214
+ removeCfgInstance?(domain: string, type: string, instance: string): Promise<void>;
215
+ /** Load configuration from a `.cfg` file already on the controller's filesystem. Requires 'edit' mastership. */
216
+ loadCfgFile?(filepath: string, action?: 'add' | 'replace' | 'add-with-reset'): Promise<void>;
217
+ /** Save a domain's current state to a `.cfg` file. Requires 'edit' mastership. */
218
+ saveCfgFile?(domain: string, filepath: string): Promise<void>;
219
+
220
+ // ── Backup / Restore `/ctrl/backup` ──────────────────────────────────────
221
+
222
+ /** List existing backups in the BACKUP volume. */
223
+ listBackups?(): Promise<Array<{ name: string; created?: string; size?: number }>>;
224
+ /** Trigger a backup. Returns a promise that resolves when the backup is initiated;
225
+ * use `getBackupStatus()` to poll for completion. */
226
+ createBackup?(name: string): Promise<void>;
227
+ /** Restore from a previous backup. Long-running — controller may restart afterwards. */
228
+ restoreBackup?(name: string): Promise<void>;
229
+ /** Get current backup-or-restore operation status. */
230
+ getBackupStatus?(): Promise<{ active: boolean; progress?: number; phase?: string }>;
231
+
232
+ // ── Tool / WObj management ───────────────────────────────────────────────
233
+
234
+ /** Currently active tool/wobj/payload for a mechunit. */
235
+ getActiveTool?(mechunit?: string): Promise<{ name: string; data?: Record<string, string> }>;
236
+ getActiveWobj?(mechunit?: string): Promise<{ name: string; data?: Record<string, string> }>;
237
+ getActivePayload?(mechunit?: string): Promise<{ name: string; data?: Record<string, string> }>;
238
+ /** Switch the active tool/wobj — both delegate to the corresponding RAPID symbol. */
239
+ setActiveTool?(mechunit: string, toolName: string): Promise<void>;
240
+ setActiveWobj?(mechunit: string, wobjName: string): Promise<void>;
241
+
242
+ // ── Service routine / PROC call ──────────────────────────────────────────
243
+
244
+ /** Execute a PROC remotely (typically a service routine). Async — returns once execution starts. */
245
+ callServiceRoutine?(task: string, routineName: string, args?: Record<string, string>): Promise<void>;
246
+
247
+ // ── DIPC (Distributed Inter-Process Communication) `/rw/dipc` ────────────
248
+
249
+ /** List active DIPC queues. */
250
+ listDipcQueues?(): Promise<Array<{ name: string; size?: number }>>;
251
+ /** Create a DIPC queue (caller's identity becomes the owner). */
252
+ createDipcQueue?(name: string, options?: { maxsize?: number; maxmessages?: number }): Promise<void>;
253
+ /** Send a DIPC message that a RAPID program can read via `RecvDipc`. */
254
+ sendDipcMessage?(queue: string, payload: string, type?: 'string' | 'num' | 'dnum' | 'bool'): Promise<void>;
255
+ /** Read a DIPC message that a RAPID program sent via `SendDipc`. */
256
+ readDipcMessage?(queue: string, timeoutMs?: number): Promise<{ payload: string; type: string } | null>;
257
+ removeDipcQueue?(name: string): Promise<void>;
258
+
259
+ // ── Mastership ───────────────────────────────────────────────────────────
260
+ requestMastership(domain: MastershipDomain): Promise<void>;
261
+ releaseMastership(domain: MastershipDomain): Promise<void>;
262
+ /** Request mastership on ALL domains at once. */
263
+ requestMastershipAll?(): Promise<void>;
264
+ /** Release mastership on ALL domains at once. */
265
+ releaseMastershipAll?(): Promise<void>;
266
+ /** Request mastership and receive a numeric ID token (token-based mastership outlives the session that acquired it). */
267
+ requestMastershipWithId?(domain: MastershipDomain): Promise<number>;
268
+ /** Release token-acquired mastership using the ID returned by `requestMastershipWithId()`. */
269
+ releaseMastershipWithId?(domain: MastershipDomain, id: number): Promise<void>;
270
+ /** Reset the edit-mastership watchdog (RobotWare 7.8+) — call ~every 1s while holding mastership during a long RAPID run. */
271
+ resetMastershipWatchdog?(): Promise<void>;
272
+ /** Read mastership status for one domain. */
273
+ getMastershipStatus?(domain: MastershipDomain): Promise<{ mastership: string; uid?: string; application?: string }>;
274
+ /** List the mastership domains the controller exposes. */
275
+ listMastershipDomains?(): Promise<string[]>;
276
+
277
+ // ── Devices `/rw/devices` and `/rw/iosystem/devices` ─────────────────────
278
+
279
+ /** Top-level device groupings (e.g. HW_DEVICES, SW_RESOURCES). */
280
+ listSystemDevices?(): Promise<Array<{ id: string; name: string }>>;
281
+ /** Drill into a system-device group — returns the raw XHTML sub-tree. */
282
+ getDeviceTree?(group: string): Promise<string>;
283
+ /** All configured I/O devices across every network in one call. */
284
+ listAllIoDevices?(): Promise<Array<{ name: string; network: string; lstate: string; pstate: string; address: string }>>;
285
+
286
+ // ── Forward kinematics ────────────────────────────────────────────────────
287
+
288
+ /**
289
+ * Forward kinematics: joint angles → Cartesian pose. Mirror of
290
+ * `calcJointsFromCartesian()`. Same VC-license caveat applies.
291
+ */
292
+ calcCartesianFromJoints?(
293
+ joints: JointTarget,
294
+ mechunit?: string,
295
+ tool?: string,
296
+ wobj?: string,
297
+ ): Promise<RobTarget>;
298
+
299
+ // ── Vision system `/rw/vision` ───────────────────────────────────────────
300
+
301
+ /** List configured vision systems (Integrated Vision option). */
302
+ listVisionSystems?(): Promise<Array<{ name: string; status?: string }>>;
303
+ /** Per-system info. */
304
+ getVisionSystemInfo?(name: string): Promise<Record<string, string>>;
305
+ /** List vision jobs (recipes) for a system. */
306
+ listVisionJobs?(system: string): Promise<Array<{ name: string; active?: boolean }>>;
307
+ /** Trigger a vision job. */
308
+ triggerVisionJob?(system: string, job: string): Promise<void>;
309
+
310
+ // ── Safety controller `/ctrl/safety` ────────────────────────────────────
311
+
312
+ /** Status of the integrated safety controller (PSC option). */
313
+ getSafetyStatus?(): Promise<{ state: string; details?: Record<string, string> }>;
314
+ /** List safety zones (configured cells/limits). */
315
+ listSafetyZones?(): Promise<Array<Record<string, string>>>;
316
+ /** Trigger a cyclic brake check. */
317
+ runCyclicBrakeCheck?(): Promise<void>;
318
+
319
+ // ── Virtual time `/ctrl/virtualtime` (VC-only) ───────────────────────────
320
+
321
+ /** Get current virtual time (only meaningful on virtual controllers). */
322
+ getVirtualTime?(): Promise<{ time: number; running: boolean }>;
323
+ /** Pause/resume virtual time — fast-forward simulation. */
324
+ setVirtualTimeRunning?(running: boolean): Promise<void>;
325
+ /** Set scaling factor (1.0 = real-time, 10.0 = 10x faster, 0 = paused). */
326
+ setVirtualTimeScale?(scale: number): Promise<void>;
327
+
328
+ // ── Certificate store `/ctrl/certstore` ──────────────────────────────────
329
+
330
+ /** List installed TLS certificates. */
331
+ listCertificates?(): Promise<Array<{ name: string; subject?: string; expires?: string }>>;
332
+ /** Upload a PEM-encoded certificate. */
333
+ uploadCertificate?(name: string, pem: string): Promise<void>;
334
+ /** Remove a certificate. */
335
+ removeCertificate?(name: string): Promise<void>;
336
+
337
+ // ── Registry `/ctrl/registry` (ABB-internal) ─────────────────────────────
338
+
339
+ /** Read controller registry (mostly ABB internal — limited use). */
340
+ getRegistry?(): Promise<Record<string, string>>;
341
+
342
+ // ── Compress `/ctrl/compress` ────────────────────────────────────────────
343
+
344
+ /** Compress a file/directory on the controller. Returns the new archive path. */
345
+ compressPath?(source: string, destination: string): Promise<void>;
346
+
347
+ // ── File service — additional volumes ───────────────────────────────────
348
+
349
+ /** List all available file volumes (HOME, BACKUP, DATA, ADDINDATA, PRODUCTS, RAMDISK, TEMP). */
350
+ listFileVolumes?(): Promise<string[]>;
351
+
352
+ // ── PP control & RAPID debugger backbone ─────────────────────────────────
353
+
354
+ /** Move PP to a specific routine (or a specific row/col within it). */
355
+ setProgramPointer?(task: string, params: { module?: string; routine: string; row?: number; col?: number }): Promise<void>;
356
+ /** Move PP to cursor position in a module. */
357
+ setPPToCursor?(task: string, module: string, row: number, col: number): Promise<void>;
358
+ /** Step Into / Over / Out — RAPID single-step. */
359
+ stepRapid?(task: string, mode: 'into' | 'over' | 'out'): Promise<void>;
360
+ /** Hold-to-run mode. */
361
+ holdToRun?(task: string, action: 'press' | 'release'): Promise<void>;
362
+
363
+ /** List all breakpoints in a task. */
364
+ listBreakpoints?(task: string): Promise<Array<{ module: string; row: number; col?: number }>>;
365
+ /** Set a breakpoint at module/row[/col]. */
366
+ setBreakpoint?(task: string, module: string, row: number, col?: number): Promise<void>;
367
+ /** Remove a breakpoint. */
368
+ removeBreakpoint?(task: string, module: string, row: number, col?: number): Promise<void>;
369
+
370
+ // ── Mechunit detailed endpoints ──────────────────────────────────────────
371
+
372
+ /** Get the base frame transform for a mechunit. */
373
+ getMechunitBaseFrame?(mechunit?: string): Promise<{ x: number; y: number; z: number; q1: number; q2: number; q3: number; q4: number }>;
374
+ /** Set the base frame transform. Requires 'edit' mastership. */
375
+ setMechunitBaseFrame?(mechunit: string, frame: { x: number; y: number; z: number; q1: number; q2: number; q3: number; q4: number }): Promise<void>;
376
+ /** Per-axis info (count, types, limits). */
377
+ getMechunitAxes?(mechunit?: string): Promise<Array<Record<string, string>>>;
378
+ /** Permanent joint positions (typically external-axes scenarios). */
379
+ getMechunitPjoints?(mechunit?: string): Promise<Record<string, number>>;
380
+ /** Detailed mechunit info (status, mode, sync state, type, axes count). */
381
+ getMechunitInfo?(mechunit?: string): Promise<Record<string, string>>;
382
+
383
+ // ── Module detailed endpoints ────────────────────────────────────────────
384
+
385
+ /** Get a module's source code via fileservice (returns the full RAPID text). */
386
+ getModuleSource?(task: string, moduleName: string): Promise<string>;
387
+ /** Get a module's metadata (path, attributes, type, lines). */
388
+ getModuleInfo?(task: string, moduleName: string): Promise<Record<string, string>>;
389
+ /** List all symbols (procs/funcs/vars/persistents/consts) defined in a module. */
390
+ listModuleSymbols?(task: string, moduleName: string): Promise<Array<{ name: string; type: string; dattyp?: string }>>;
391
+
392
+ // ── Per-task additional endpoints (live-discovered) ─────────────────────
393
+
394
+ /** Per-task structural-change counter — increments when symbols/modules change. */
395
+ getTaskStructuralChangeCount?(task: string): Promise<number>;
396
+ /** Per-task motion data (current state of motion in this task). */
397
+ getTaskMotion?(task: string): Promise<Record<string, string>>;
398
+ /** Per-task activation record (call stack / current routine). */
399
+ getTaskActivationRecord?(task: string): Promise<Record<string, string>>;
400
+ /** Per-task program info (loaded program metadata). */
401
+ getTaskProgramInfo?(task: string): Promise<Record<string, string>>;
402
+
403
+ // ── Real-time subscriptions ───────────────────────────────────────────────
404
+ /**
405
+ * Subscribe to real-time RWS resource events via WebSocket.
406
+ * Returns an async unsubscribe function — call it on disconnect.
407
+ * Falls back gracefully: if the controller does not support subscriptions,
408
+ * implementations should throw so callers can fall back to polling.
409
+ *
410
+ * `onLost` (optional) is invoked at most once, when the event stream is
411
+ * terminally lost — i.e. the connection dropped and the adapter's reconnect
412
+ * attempts have all failed. Callers should treat it as "events stopped
413
+ * flowing; switch to polling or reconnect". Adapters without reconnect
414
+ * logic may ignore it.
415
+ */
416
+ subscribe(
417
+ resources: SubscriptionResource[],
418
+ handler: (event: SubscriptionEvent) => void,
419
+ onLost?: () => void,
420
+ ): Promise<() => Promise<void>>;
421
+ }
422
+
package/src/Logger.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Pluggable logger interface used by RobotManager, MultiRobotManager, and
3
+ * both protocol clients (HTTP req/res tracing flows through here too).
4
+ *
5
+ * The lib ships with a no-op default. Hosts (e.g. the VS Code extension) can
6
+ * install their own backend by calling `setLogger(myImpl)`. The extension
7
+ * routes log lines into a VS Code output channel AND a persistent file; a
8
+ * CLI might just `console.log`.
9
+ *
10
+ * Methods:
11
+ * - info(msg): lifecycle events (connect/disconnect/poll)
12
+ * - warn(msg): recoverable issues (subscription fallback)
13
+ * - error(msg, err?): failures the user needs to see
14
+ * - trace(category, msg, data?): structured debug lines (HTTP req/res, WS frames,
15
+ * command dispatches). Optional — implementers can
16
+ * ignore for terse output. Categories used by the
17
+ * lib: 'http.req', 'http.res', 'http.err', 'ws',
18
+ * 'subscription', 'mastership'.
19
+ * - show(): bring the log surface to the front
20
+ */
21
+ export interface Logger {
22
+ info(msg: string): void;
23
+ warn(msg: string): void;
24
+ error(msg: string, err?: unknown): void;
25
+ trace?(category: string, msg: string, data?: unknown): void;
26
+ show(): void;
27
+ }
28
+
29
+ const noopLogger: Logger = {
30
+ info() { /* no-op */ },
31
+ warn() { /* no-op */ },
32
+ error() { /* no-op */ },
33
+ trace() { /* no-op */ },
34
+ show() { /* no-op */ },
35
+ };
36
+
37
+ let activeLogger: Logger = noopLogger;
38
+
39
+ /** Install a custom logger. Call once at startup; subsequent calls replace it. */
40
+ export function setLogger(impl: Logger): void {
41
+ activeLogger = impl;
42
+ }
43
+
44
+ /**
45
+ * Internal accessor used throughout the lib. Goes through getters so a later
46
+ * `setLogger()` call takes effect for code that imported `Logger` earlier.
47
+ */
48
+ export const Logger: Logger = {
49
+ info(msg) { activeLogger.info(msg); },
50
+ warn(msg) { activeLogger.warn(msg); },
51
+ error(msg, err) { activeLogger.error(msg, err); },
52
+ trace(category, msg, d) { activeLogger.trace?.(category, msg, d); },
53
+ show() { activeLogger.show(); },
54
+ };