@synapticon/motion-master-client 2.3.0-beta.0 → 6.0.0-alpha.110

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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api-error.d.ts +25 -0
  3. package/dist/api-error.js +52 -0
  4. package/dist/client.d.ts +20 -0
  5. package/dist/client.js +37 -0
  6. package/dist/constants.d.ts +2 -0
  7. package/dist/constants.js +8 -0
  8. package/dist/eni.d.ts +197 -0
  9. package/dist/eni.js +61 -0
  10. package/dist/generated/Api.d.ts +1886 -0
  11. package/dist/generated/Api.js +1293 -0
  12. package/dist/generated/data-contracts.d.ts +2282 -0
  13. package/dist/generated/data-contracts.js +12 -0
  14. package/dist/generated/http-client.d.ts +60 -0
  15. package/dist/generated/http-client.js +171 -0
  16. package/dist/hex.d.ts +2 -0
  17. package/dist/hex.js +20 -0
  18. package/dist/index.d.ts +13 -7
  19. package/dist/index.js +20 -22
  20. package/dist/lan.d.ts +4 -0
  21. package/dist/lan.js +59 -0
  22. package/dist/mmpd.d.ts +53 -0
  23. package/dist/mmpd.js +322 -0
  24. package/dist/sdo.d.ts +17 -0
  25. package/dist/sdo.js +219 -0
  26. package/dist/web-socket-connection.d.ts +70 -0
  27. package/dist/web-socket-connection.js +237 -0
  28. package/dist/wire-time.d.ts +2 -0
  29. package/dist/wire-time.js +18 -0
  30. package/package.json +29 -35
  31. package/.vscode/launch.json +0 -23
  32. package/README.md +0 -118
  33. package/box.config.json +0 -7
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js.map +0 -1
  36. package/dist/motion-master-client-web-socket-connection.d.ts +0 -43
  37. package/dist/motion-master-client-web-socket-connection.d.ts.map +0 -1
  38. package/dist/motion-master-client-web-socket-connection.js +0 -91
  39. package/dist/motion-master-client-web-socket-connection.js.map +0 -1
  40. package/dist/motion-master-client.d.ts +0 -105
  41. package/dist/motion-master-client.d.ts.map +0 -1
  42. package/dist/motion-master-client.js +0 -348
  43. package/dist/motion-master-client.js.map +0 -1
  44. package/dist/motion-master-notification-subscribe-data.d.ts +0 -8
  45. package/dist/motion-master-notification-subscribe-data.d.ts.map +0 -1
  46. package/dist/motion-master-notification-subscribe-data.js +0 -3
  47. package/dist/motion-master-notification-subscribe-data.js.map +0 -1
  48. package/dist/motion-master-notification-web-socket-connection.d.ts +0 -56
  49. package/dist/motion-master-notification-web-socket-connection.d.ts.map +0 -1
  50. package/dist/motion-master-notification-web-socket-connection.js +0 -115
  51. package/dist/motion-master-notification-web-socket-connection.js.map +0 -1
  52. package/dist/motion-master-notification.d.ts +0 -31
  53. package/dist/motion-master-notification.d.ts.map +0 -1
  54. package/dist/motion-master-notification.js +0 -44
  55. package/dist/motion-master-notification.js.map +0 -1
  56. package/dist/util.d.ts +0 -16
  57. package/dist/util.d.ts.map +0 -1
  58. package/dist/util.js +0 -24
  59. package/dist/util.js.map +0 -1
  60. package/licenses.format.json +0 -4
  61. package/motion-master-client.config.json +0 -7
  62. package/smm_data_dic.json +0 -1213
  63. package/src/index.ts +0 -7
  64. package/src/motion-master-client-web-socket-connection.ts +0 -104
  65. package/src/motion-master-client.ts +0 -468
  66. package/src/motion-master-notification-subscribe-data.ts +0 -7
  67. package/src/motion-master-notification-web-socket-connection.ts +0 -143
  68. package/src/motion-master-notification.ts +0 -51
  69. package/src/util.ts +0 -22
  70. package/test.sh +0 -122
  71. package/tsconfig.json +0 -63
  72. package/tslint.json +0 -118
@@ -0,0 +1,1886 @@
1
+ import { AlStatusCode, AutoTuningError, AutoTuningRunRequest, AutoTuningRunResponse, AutoTuningStatus, BrakeState, CaptureSummary, Cia402Status, DcSyncStatus, DeviceDiagnostics, DeviceFile, DeviceParameter, Encoders, EscRegister, EsiParseResult, FirmwareCompatibility, FirmwarePackageName, FoeErrorCode, GameLoopHealth, HardwareDescription, HrdRecording, IntegroVariant, IntegroVariantOption, MailboxErrorCode, Monitoring, ObjectDataTypeInfo, OperationModes, OutputStageResult, ParameterCacheEntry, ParameterValue, PdoMapping, PdoMappingRequest, ProcedureListing, ProcedureRequest, ProcedureSnapshot, ProcessDataWatchdog, ProcessImageObject, SdoAbortCode, SlaveConfig, SlaveInformationInterface, UserCacheListing } from "./data-contracts.js";
2
+ import { HttpClient, RequestParams } from "./http-client.js";
3
+ export declare class Api<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
4
+ /**
5
+ * No description
6
+ *
7
+ * @name GetAdapters
8
+ * @summary List network adapters on the host
9
+ * @request GET:/api/adapters
10
+ */
11
+ getAdapters: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
12
+ /**
13
+ * MAC address in colon-separated uppercase format
14
+ * @example "AA:BB:CC:DD:EE:FF"
15
+ */
16
+ macLinux: string;
17
+ /**
18
+ * MAC address in dash-separated uppercase format
19
+ * @example "AA-BB-CC-DD-EE-FF"
20
+ */
21
+ macWindows: string;
22
+ /**
23
+ * OS interface name (e.g. eth0 on Linux, \\Device\\NPF_{GUID} on Windows)
24
+ * @example "eth0"
25
+ */
26
+ name: string;
27
+ /**
28
+ * Human-readable hardware description. Populated on Windows, where the interface name is a GUID device path that identifies nothing; empty on Linux and macOS, where the interface name is the identification. Clients must fall back to `name` when it is empty.
29
+ * @example "Realtek USB GbE Family Controller"
30
+ */
31
+ description: string;
32
+ }[], any>>;
33
+ /**
34
+ * No description
35
+ *
36
+ * @name GetVersion
37
+ * @summary Get Motion Master version
38
+ * @request GET:/api/version
39
+ */
40
+ getVersion: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
41
+ /** @example "6.0.0" */
42
+ version: string;
43
+ }, any>>;
44
+ /**
45
+ * @description Returns this document — the OpenAPI specification embedded in the running binary — as YAML. Lets a client discover the exact API contract of the server it is talking to without a packaged file or a matching source checkout; the served spec always matches the running version.
46
+ *
47
+ * @name GetSwaggerYml
48
+ * @summary Get this OpenAPI specification
49
+ * @request GET:/api/swagger.yml
50
+ */
51
+ getSwaggerYml: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<string, any>>;
52
+ /**
53
+ * @description The effective configuration after merging the JSONC config file (if any) over the built-in defaults — the same `Config` the server booted with. The config file is either the one passed via `--config` or a `motion-master.jsonc` auto-discovered next to the executable (`--config` wins). Read-only; changing it requires editing the config file and restarting. The shape mirrors the config file (server, fieldbus, logging, tls, gameLoop, recorder, parameterCache, parameters).
54
+ *
55
+ * @name GetStartedConfig
56
+ * @summary Get the configuration Motion Master was started with
57
+ * @request GET:/api/config
58
+ */
59
+ getStartedConfig: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Record<string, any>, any>>;
60
+ /**
61
+ * @description A best-effort snapshot of the operating system and hardware Motion Master is running on, for the Connection page's System panel. Every field is best-effort: one that cannot be determined on the current platform is returned empty (strings) or zero (numbers) rather than failing the request. Collected on demand — not cached.
62
+ *
63
+ * @name GetSystemInfo
64
+ * @summary Get host OS and hardware information
65
+ * @request GET:/api/system-info
66
+ */
67
+ getSystemInfo: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
68
+ /**
69
+ * Friendly OS name.
70
+ * @example "Ubuntu 24.04 LTS"
71
+ */
72
+ osName: string;
73
+ /**
74
+ * Kernel or OS build identifier.
75
+ * @example "6.8.0-31-generic"
76
+ */
77
+ kernel: string;
78
+ /**
79
+ * Machine architecture.
80
+ * @example "x86_64"
81
+ */
82
+ architecture: string;
83
+ /**
84
+ * Network host name.
85
+ * @example "motion-master-pi"
86
+ */
87
+ hostname: string;
88
+ /**
89
+ * CPU brand string.
90
+ * @example "Intel(R) Core(TM) i7-1185G7 @ 3.00GHz"
91
+ */
92
+ cpuModel: string;
93
+ /**
94
+ * Logical processor count.
95
+ * @example 8
96
+ */
97
+ cpuCores: number;
98
+ /**
99
+ * Total physical RAM in bytes (0 if unknown).
100
+ * @format int64
101
+ * @example 16777216000
102
+ */
103
+ totalMemoryBytes: number;
104
+ /**
105
+ * Capacity of the filesystem holding the working directory, in bytes.
106
+ * @format int64
107
+ * @example 250790436864
108
+ */
109
+ diskTotalBytes: number;
110
+ /**
111
+ * Space available to an unprivileged process on that filesystem, in bytes.
112
+ * @format int64
113
+ * @example 98765432100
114
+ */
115
+ diskFreeBytes: number;
116
+ /**
117
+ * Container runtime when running inside one ("docker", "podman", "containerd", "kubernetes", "lxc"); empty on bare metal.
118
+ * @example "docker"
119
+ */
120
+ container: string;
121
+ /**
122
+ * Docker version reported by `docker --version` on the host; empty if the docker CLI is not installed/on PATH (including inside Motion Master's own image).
123
+ * @example "27.1.1"
124
+ */
125
+ dockerVersion: string;
126
+ }, any>>;
127
+ /**
128
+ * @description Reports the validity window and identity of the certificate the server is currently serving. `expiresSoon` trips within 7 days of `notAfter`, so the PWA can prompt the user to refresh. Note that an already-expired certificate blocks the browser from reaching this endpoint at all; the binary self-heals an expired/missing certificate at startup (fetching from the rolling release) and exposes `--update-cert` for manual refresh. Returns 500 if the certificate file cannot be read or parsed.
129
+ *
130
+ * @name GetCert
131
+ * @summary Get the TLS certificate validity window
132
+ * @request GET:/api/cert
133
+ */
134
+ getCert: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
135
+ /**
136
+ * Filesystem path of the certificate being served.
137
+ * @example "/opt/motion-master/cert.pem"
138
+ */
139
+ path: string;
140
+ /**
141
+ * Subject common name (CN).
142
+ * @example "local.motion-master.synapticon.com"
143
+ */
144
+ subject: string;
145
+ /**
146
+ * The certificate's subjectAltName DNS entries — the hostnames it is valid for, and what a browser actually checks (the CN is legacy and ignored). The bundled certificate covers both the loopback name and the `*.ip.…` wildcard used by off-loopback deployments, so one file serves either. Empty for a certificate with no SAN extension.
147
+ * @example ["local.motion-master.synapticon.com","*.ip.motion-master.synapticon.com"]
148
+ */
149
+ dnsNames?: string[];
150
+ /**
151
+ * Issuer common name (CN).
152
+ * @example "R10"
153
+ */
154
+ issuer: string;
155
+ /**
156
+ * Start of the validity window (ISO 8601 UTC).
157
+ * @format date-time
158
+ * @example "2026-05-01T00:00:00Z"
159
+ */
160
+ notBefore: string;
161
+ /**
162
+ * End of the validity window / expiry (ISO 8601 UTC).
163
+ * @format date-time
164
+ * @example "2026-08-01T00:00:00Z"
165
+ */
166
+ notAfter: string;
167
+ /**
168
+ * Whole days until expiry; negative once expired.
169
+ * @example 56
170
+ */
171
+ daysRemaining: number;
172
+ /**
173
+ * Whether the certificate is already past notAfter.
174
+ * @example false
175
+ */
176
+ expired: boolean;
177
+ /**
178
+ * True when expired or within 7 days of notAfter.
179
+ * @example false
180
+ */
181
+ expiresSoon: boolean;
182
+ /** Every certificate present in the served PEM file, leaf first, in chain order (leaf → intermediate(s)). A fullchain PEM usually stops at the intermediate — the root lives in the OS trust store and is not transmitted — but the last entry's `issuer` still names that root. */
183
+ chain?: {
184
+ /**
185
+ * Subject common name (CN) of this certificate.
186
+ * @example "local.motion-master.synapticon.com"
187
+ */
188
+ subject: string;
189
+ /**
190
+ * Issuer common name (CN) — the subject of the next link up.
191
+ * @example "R10"
192
+ */
193
+ issuer: string;
194
+ /**
195
+ * Subject organization (O) — the friendly CA name (e.g. "Let's Encrypt") that the short CN does not carry; empty if absent (leaf certs often have no O).
196
+ * @example "Let's Encrypt"
197
+ */
198
+ organization: string;
199
+ /**
200
+ * Issuer organization (O) — names the next link's (or, for the last link, the root's) organization; empty if absent.
201
+ * @example "Internet Security Research Group"
202
+ */
203
+ issuerOrganization: string;
204
+ }[];
205
+ }, {
206
+ /**
207
+ * Human-readable reason the certificate could not be read.
208
+ * @example "cannot parse PEM certificate: /opt/motion-master/cert.pem"
209
+ */
210
+ error: string;
211
+ }>>;
212
+ /**
213
+ * @description Downloads a fresh certificate and key from the rolling release, validates the pair (parses, CN matches, not expired, key matches cert), and atomically installs them next to the binary. The new certificate only takes effect after a restart (the TLS listener loads the certificate once at startup), indicated by `restartRequired` in the response. Use the still-valid proactive case; an already-expired certificate is healed by the binary at startup instead.
214
+ *
215
+ * @name RefreshCert
216
+ * @summary Fetch and install a fresh TLS certificate
217
+ * @request POST:/api/cert/refresh
218
+ */
219
+ refreshCert: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
220
+ /** @example "/opt/motion-master/cert.pem" */
221
+ path?: string;
222
+ /** @example "local.motion-master.synapticon.com" */
223
+ subject?: string;
224
+ /** @example "R10" */
225
+ issuer?: string;
226
+ /** @format date-time */
227
+ notBefore?: string;
228
+ /** @format date-time */
229
+ notAfter: string;
230
+ /** @example 89 */
231
+ daysRemaining: number;
232
+ /** @example false */
233
+ expired?: boolean;
234
+ /** @example false */
235
+ expiresSoon?: boolean;
236
+ /**
237
+ * Always true — restart Motion Master to serve the new certificate.
238
+ * @example true
239
+ */
240
+ restartRequired: boolean;
241
+ }, {
242
+ /** @example "downloaded key does not match certificate" */
243
+ error: string;
244
+ } | {
245
+ /** @example "certificate refresh is not configured" */
246
+ error: string;
247
+ }>>;
248
+ /**
249
+ * No description
250
+ *
251
+ * @name GetDevice
252
+ * @summary Get a single fieldbus device by bus position
253
+ * @request GET:/api/devices/{slavePosition}
254
+ */
255
+ getDevice: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
256
+ /**
257
+ * 1-based position on the fieldbus
258
+ * @example 1
259
+ */
260
+ slavePosition: number;
261
+ /**
262
+ * Human-readable device name from SII EEPROM. For SOMANET drives this is the generic group name "SOMANET"; use productName to distinguish products.
263
+ * @example "SOMANET"
264
+ */
265
+ name: string;
266
+ /**
267
+ * Canonical product name, independent of the SII EEPROM. For a recognised SOMANET product this distinguishes the product (e.g. "SOMANET Circulo"); otherwise it falls back to name.
268
+ * @example "SOMANET Node"
269
+ */
270
+ productName: string;
271
+ /**
272
+ * Vendor ID from EEPROM
273
+ * @format int64
274
+ * @example 131073
275
+ */
276
+ vendorId: number;
277
+ /**
278
+ * Product code from EEPROM
279
+ * @format int64
280
+ * @example 5570560
281
+ */
282
+ productCode: number;
283
+ /**
284
+ * Revision number from EEPROM
285
+ * @format int64
286
+ * @example 1
287
+ */
288
+ revisionNumber: number;
289
+ /**
290
+ * Serial number from EEPROM
291
+ * @format int64
292
+ * @example 12345
293
+ */
294
+ serialNumber: number;
295
+ /**
296
+ * Whether the device implements the CiA402 drive profile (both controlword 0x6040 and statusword 0x6041 present in its object dictionary). Gates the CiA402 motion-control endpoints under /api/devices/{slavePosition}/cia402.
297
+ * @example true
298
+ */
299
+ isCia402: boolean;
300
+ /**
301
+ * Whether the device is a SOMANET device, which runs SOMANET firmware. The server decides this from the vendor ID: Synapticon (0x22D2) or Sensodrive (0x063A). Gates the SOMANET features, such as the SOMANET files and the SOMANET procedures.
302
+ * @example true
303
+ */
304
+ isSomanet: boolean;
305
+ /**
306
+ * Whether an object-dictionary read for this device has failed since it was scanned. The automatic read on reaching a mailbox-active state is attempted once, so a device flagged here keeps an empty parameter list until `POST /api/devices/{slavePosition}/parameters/init` is called; that clears the flag on success.
307
+ * @example false
308
+ */
309
+ parametersUnavailable: boolean;
310
+ /**
311
+ * The low byte of ESC register 0x0000, which names the slave controller family: 0x85 is a netX (Integro), 0xC0 the controller of a Circulo, 0x90 a TI PRU-ICSS (Jasper). Null when the register could not be read at the scan, and over SPoE.
312
+ * @format int32
313
+ * @example 192
314
+ */
315
+ escType?: number | null;
316
+ /**
317
+ * Whether Motion Master writes each mailbox request to this device once and never sends it again. True for a Synapticon or Sensodrive device whose ESC type is not 0x85, because its EtherCAT stack locks its receive mailbox when it gets one request twice. False for a netX, which discards a repeat, and for every other vendor, where a write with no frame back is sent again.
318
+ * @example true
319
+ */
320
+ mailboxWriteOnce?: boolean;
321
+ /**
322
+ * Whether the device has an EtherCAT Slave Controller: SII, ESC registers, distributed clocks and the ESC diagnostics. False over SPoE, where those endpoints answer 409.
323
+ * @example true
324
+ */
325
+ supportsEsc?: boolean;
326
+ /**
327
+ * Whether the transport can blink the device's LEDs, which is what the `device-locate` procedure does. True over SPoE.
328
+ * @example false
329
+ */
330
+ supportsLocate?: boolean;
331
+ }, void>>;
332
+ /**
333
+ * @description Constructs the requested fieldbus driver and makes it available for subsequent calls to /api/scan. The body is the `fieldbus` block of the config file, and the same rules check it. The driver defaults to SOEM when omitted. SOEM opens the network interface. It has no adapter auto-detect: a network adapter must be supplied, otherwise init fails. SPoE connects to each drive at scan time. It needs `ipAddresses`, one address per drive, and the list order is the position order.
334
+ *
335
+ * @name Init
336
+ * @summary Initialise the fieldbus driver
337
+ * @request POST:/api/init
338
+ */
339
+ init: (data?: {
340
+ /**
341
+ * Fieldbus driver to use
342
+ * @default "soem"
343
+ * @example "soem"
344
+ */
345
+ driver?: "soem" | "spoe";
346
+ /**
347
+ * SOEM only. Network interface name or MAC address. Required for SOEM — there is no auto-detect, so an empty value makes init fail.
348
+ * @example "eth0"
349
+ */
350
+ adapter?: string;
351
+ /**
352
+ * SPoE only. One IP address per drive, at least one. The list order is the position order, and a drive that does not answer keeps its position.
353
+ * @example ["192.168.0.10"]
354
+ */
355
+ ipAddresses?: string[];
356
+ /** SPoE only. */
357
+ spoe?: {
358
+ /**
359
+ * Who owns the drive's state. In `monitor` mode a PLC owns it, Motion Master only parametrises and observes, and a state change answers 409. In `control` mode Motion Master owns it.
360
+ * @default "monitor"
361
+ */
362
+ mode?: "monitor" | "control";
363
+ /**
364
+ * Control mode only. The drive faults when no SPoE message arrives for this long. At least 50. Firmware with SPoE protocol 1.0 cannot set it and uses a fixed watchdog.
365
+ * @min 50
366
+ * @default 75
367
+ */
368
+ watchdogMs?: number;
369
+ /**
370
+ * The TCP port of the SPoE server on every drive.
371
+ * @min 1
372
+ * @max 65535
373
+ * @default 8080
374
+ */
375
+ port?: number;
376
+ };
377
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
378
+ /** @example true */
379
+ ok: boolean;
380
+ }, void | {
381
+ /** @example "already initialised — call reset() first" */
382
+ error: string;
383
+ } | {
384
+ /**
385
+ * Human-readable error message from the driver
386
+ * @example "FPRD slave 1: wkc=0"
387
+ */
388
+ error: string;
389
+ }>>;
390
+ /**
391
+ * @description Compares the bus with the last scan. Two changes make that scan wrong. A device that resets, for example after a power cycle, loses the station address the scan gave it, and no longer answers at it. A device added to or removed from the chain changes the number of devices on the wire, even when every known device still answers. The server reads the AL state of every scanned device, as `GET /api/devices/state` does, and with SOEM it counts the devices on the wire with one broadcast read. A device that lost its station address still answers a broadcast, so it is counted. Before the first scan, `devicesScanned` is 0, so any device on the wire makes `required` true. A device swapped for another at the same position without a reset is not detected, because it keeps the old address and answers normally.
392
+ *
393
+ * @name GetScanStatus
394
+ * @summary Read whether the bus needs a new scan
395
+ * @request GET:/api/scan
396
+ */
397
+ getScanStatus: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
398
+ /**
399
+ * True when `unreachable` is not empty, or when `devicesOnWire` is not null and differs from `devicesScanned`.
400
+ * @example true
401
+ */
402
+ required: boolean;
403
+ /**
404
+ * The number of devices on the wire now. Null over SPoE, which cannot count them.
405
+ * @example 3
406
+ */
407
+ devicesOnWire: number | null;
408
+ /**
409
+ * The number of devices the last scan found
410
+ * @example 2
411
+ */
412
+ devicesScanned: number;
413
+ /**
414
+ * Positions whose `reachability` is not `answering`, in position order. `GET /api/devices/state` tells why for each one.
415
+ * @example [2]
416
+ */
417
+ unreachable: number[];
418
+ }, {
419
+ /**
420
+ * Human-readable error message from the driver
421
+ * @example "FPRD slave 1: wkc=0"
422
+ */
423
+ error: string;
424
+ }>>;
425
+ /**
426
+ * @description Scans the fieldbus for slaves and configures their sync managers and FMMUs. Must be called after a successful POST /api/init. With SOEM, slaves remain in INIT state after this call, and state transitions are driven by subsequent API calls. An SPoE drive starts in OP. When a scan finds a device already in SAFE-OP or OP, it reads that device's object dictionary and publishes the process image, so the exchange starts with no state change. The dictionary comes from the parameter cache when the cache has it. Otherwise the first read of a drive model takes several seconds. If this step fails, the scan still returns 200 and the server logs a warning. A later state change to SAFE-OP or OP maps the image again. An empty bus is a successful scan returning 0 slaves, not an error: the master cannot distinguish a bus with no devices powered from a disconnected one, and the user recovers by powering devices on and scanning again. A 500 is returned only on a genuine driver failure (e.g. no driver initialised). A scan does not wait for work already in flight. A procedure that is running keeps running against the devices it started on, and fails at its next bus transfer. Retained procedure snapshots are discarded, because a position may name different hardware after a scan. A scan frees the recording, the retained process images and the previous device set, so it first waits up to 200 ms for the real-time loop to leave the cycle it is in. If the loop is stalled — a cyclic task that overruns, or severe CPU contention — the scan fails with 500 and changes nothing, rather than freeing memory the loop is still reading. `GET /api/game-loop` shows the stall. The same applies to `POST /api/process-data`, which re-allocates the recorder. `POST /api/reset` never fails this way: it holds the memory back instead and reclaims it later.
427
+ *
428
+ * @name Scan
429
+ * @summary Scan the bus for slaves
430
+ * @request POST:/api/scan
431
+ */
432
+ scan: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
433
+ /**
434
+ * Number of slaves discovered on the bus (0 if empty/unpowered)
435
+ * @example 3
436
+ */
437
+ slaves: number;
438
+ }, {
439
+ /**
440
+ * Human-readable error message from the driver
441
+ * @example "FPRD slave 1: wkc=0"
442
+ */
443
+ error: string;
444
+ }>>;
445
+ /**
446
+ * @description Tears down all master-side state — unpublishes the process image, frees the recorder, removes all Device objects, and closes the network interface (releasing the NIC). It does not command the slaves to any AL state; the master simply stops talking to the bus. After this returns, POST /api/init and POST /api/scan may be called again.
447
+ *
448
+ * @name Reset
449
+ * @summary Reset the fieldbus driver and clear the device list
450
+ * @request POST:/api/reset
451
+ */
452
+ reset: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
453
+ /** @example true */
454
+ ok: boolean;
455
+ }, any>>;
456
+ /**
457
+ * @description Returns the most recent in-memory log lines as plain text, one entry per line. The ring buffer holds up to 100 000 entries (~10 MB).
458
+ *
459
+ * @name GetLog
460
+ * @summary Get recent log output
461
+ * @request GET:/api/log
462
+ */
463
+ getLog: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<string, any>>;
464
+ /**
465
+ * @description Reports what Motion Master knows about the auto-tuning process. The tuning calculations run in a separate executable, which Motion Master starts at startup and reaches over loopback. That executable is downloaded by the install scripts rather than shipped in a release, so a machine may not have it — this endpoint is how a client tells the four cases apart: switched off in the configuration, not installed, installed but would not start, or running. The values are a startup snapshot. `started` says the process answered when Motion Master waited for it, not that it is alive now. Nothing polls it: a call is the honest test, and `POST /api/auto-tuning/run` makes one.
466
+ *
467
+ * @name GetAutoTuning
468
+ * @summary Auto-tuning process status
469
+ * @request GET:/api/auto-tuning
470
+ */
471
+ getAutoTuning: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<AutoTuningStatus, any>>;
472
+ /**
473
+ * @description Forwards the request to the auto-tuning process and returns its reply unchanged. The body is a JSON object with `run`, naming the function, and `data`, holding that function's inputs — the same shape the auto-tuning program takes on its own API. **A rejected input is reported with 200 and an `error` property**, not with a 4xx. The auto-tuning program keeps 4xx and 5xx for a malformed request, an unknown function name, and a routine that threw, so a client tests for `error` in the body rather than relying on the status alone. Motion Master passes both through untouched; only 400, 502 and 503 below are its own. Measurement data travels in the body. `identify_plant_model` takes the chirp measurements as `data.csv` text, and the bode data comes back inline as `bode`, so no file is written and nothing needs a shared filesystem view. The schemas here are a copy of the auto-tuning program's own, taken from version 3.1.1, and they exist so that the generated clients are typed. That program's current description is served verbatim at `GET /api/auto-tuning/swagger.yml`, which is the authority if the two ever disagree.
474
+ *
475
+ * @name RunAutoTuning
476
+ * @summary Run an auto-tuning function
477
+ * @request POST:/api/auto-tuning/run
478
+ */
479
+ runAutoTuning: (data: AutoTuningRunRequest, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<AutoTuningRunResponse, AutoTuningError | {
480
+ error: string;
481
+ }>>;
482
+ /**
483
+ * @description Serves the OpenAPI document the auto-tuning process carries, fetched from it on each request. The schemas under `/api/auto-tuning/run` above are a copy of these, so this is where to look when a version of the program disagrees with them.
484
+ *
485
+ * @name GetAutoTuningSpec
486
+ * @summary The auto-tuning program's own API description
487
+ * @request GET:/api/auto-tuning/swagger.yml
488
+ */
489
+ getAutoTuningSpec: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<string, {
490
+ error: string;
491
+ }>>;
492
+ /**
493
+ * @description Returns the static catalogue of EtherCAT AL Status Codes defined in ETG.1000.6 §6.4.1. These codes appear in the alStatusCode field of the device state response when an error is present and identify the cause of the state transition failure.
494
+ *
495
+ * @name GetAlStatusCodes
496
+ * @summary List all known AL Status Codes
497
+ * @request GET:/api/meta/al-status-codes
498
+ */
499
+ getAlStatusCodes: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<AlStatusCode[], any>>;
500
+ /**
501
+ * @description Returns the static catalogue of well-known EtherCAT Slave Controller registers from the Beckhoff ESC datasheet (Section II) and ETG.1000.4. Use the address and length fields as inputs to the device register read/write endpoints.
502
+ *
503
+ * @name GetRegisters
504
+ * @summary List all known ESC registers
505
+ * @request GET:/api/meta/esc-registers
506
+ */
507
+ getRegisters: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<EscRegister[], any>>;
508
+ /**
509
+ * @description Returns the static catalogue of standard File over EtherCAT (FoE) error codes defined in ETG.1000.6 §5.5. These codes appear in the FoE ERROR packet sent by the slave when a file transfer fails, and are surfaced in the error message returned by the file read endpoint. Vendor-specific codes outside the 0x8000 range are not listed here.
510
+ *
511
+ * @name GetFoeErrorCodes
512
+ * @summary List all known FoE error codes
513
+ * @request GET:/api/meta/foe-error-codes
514
+ */
515
+ getFoeErrorCodes: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<FoeErrorCode[], any>>;
516
+ /**
517
+ * @description Returns the static catalogue of CoE SDO abort codes defined in ETG.1000.6 §5.6.2.7.2, Table 41 (which reproduces the CANopen CiA 301 abort transfer codes). A slave returns one of these when a mailbox SDO read/write fails; the code is embedded in the error text returned by the SDO endpoints.
518
+ *
519
+ * @name GetSdoAbortCodes
520
+ * @summary List all known CoE SDO abort codes
521
+ * @request GET:/api/meta/sdo-abort-codes
522
+ */
523
+ getSdoAbortCodes: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<SdoAbortCode[], any>>;
524
+ /**
525
+ * @description The register maps of the two iC-Haus chips inside a Circulo's internal encoder — the reference tables for POST /api/devices/{slavePosition}/procedures/encoder-register-communication, and documentation in their own right. Static: they describe the chips, not any connected device, so no bus and no scan are needed. Two chips, and the iC-MU is the one in charge. The iC-MU is the position encoder proper, a magnetic off-axis absolute chip speaking BiSS-C to the drive. The iC-PVL is a battery-buffered Hall multiturn counter behind it, reached over I2C through the iC-MU rather than directly. The response is a list of register *spaces*, not of registers, because an address alone names nothing: the same iC-PVL address 0x00 is a configuration register in one space and the status register in another, depending on which I2C device id addressed it. Each space says which chip it belongs to and how it is reached. A row is one address, or the range the datasheet prints as one row — `address` and `lastAddress` are equal in the ordinary case. `fields` lists the named pieces of the register, most significant bit first, each with the datasheet's own one-line description; it is empty exactly when `reserved` is true. `layout` is those same fields rendered as the datasheet prints the row, e.g. `GC_M(1:0) | GF_M(5:0)`, derived rather than stored so it cannot disagree with them. `spiOnly` marks the iC-MU's 0x80-0xAF, which is reachable over SPI only and so beyond the drive's register communication service. A field's `bits` is its own bit slice as the register map prints it, not its position within the byte: `GC_M(1:0)` occupies bits 7:6 of address 0x00 and reads "1:0" because those are the field's two bits. A value wider than one register is spread across several, which is why `RESABZ` reads "7:0" at 0x13 and "15:8" at 0x14. Granularity follows each datasheet's own register map. The iC-PVL prints its status registers bit by bit, so those arrive as eight fields; the iC-MU prints its own as `STATUS0(7:0)`, so that is one field. Transcribed from the vendors' datasheets: iC-MU Series Rev B1 (Tables 90 and 91) and iC-PVL Rev F2 (Tables 5, 6 and 7), with descriptions from their CONFIGURATION PARAMETERS indexes and, for the iC-PVL status bytes, its status tables. The prose behind those one-liners is not reproduced.
526
+ *
527
+ * @name GetIcHausRegisters
528
+ * @summary The Circulo internal encoder's register maps
529
+ * @request GET:/api/meta/ic-haus-registers
530
+ */
531
+ getIcHausRegisters: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
532
+ /** @example "iC-MU" */
533
+ chip: "iC-MU" | "iC-PVL";
534
+ /**
535
+ * The datasheet's own name for the space.
536
+ * @example "CONF, bank 0, addresses 0x00-0x3F"
537
+ */
538
+ name: string;
539
+ /** How the space is reached, which is what decides whether the register communication service can read it at all. */
540
+ addressing: string;
541
+ registers: {
542
+ /**
543
+ * The address, or the first of a printed range.
544
+ * @example 15
545
+ */
546
+ address: number;
547
+ /**
548
+ * The last address of the range; equal to address for a single-address row.
549
+ * @example 15
550
+ */
551
+ lastAddress: number;
552
+ /**
553
+ * The fields rendered as the datasheet prints the row. "RESERVED" for a reserved row.
554
+ * @example "SPO_MT(3:0) | MPC(3:0)"
555
+ */
556
+ layout: string;
557
+ /** The named pieces of this register, most significant bit first. Empty when reserved. */
558
+ fields: {
559
+ /**
560
+ * The datasheet's own name for the field.
561
+ * @example "SPO_MT"
562
+ */
563
+ name: string;
564
+ /**
565
+ * The field's own bit slice as the register map prints it, empty where it prints a bare name. Not the position within the byte.
566
+ * @example "3:0"
567
+ */
568
+ bits: string;
569
+ /**
570
+ * The datasheet's one-line description of the field.
571
+ * @example "Offset external multiturn"
572
+ */
573
+ description: string;
574
+ }[];
575
+ /** @example false */
576
+ reserved: boolean;
577
+ /**
578
+ * Reachable over SPI only, so the register communication service cannot touch it.
579
+ * @example false
580
+ */
581
+ spiOnly: boolean;
582
+ }[];
583
+ }[], any>>;
584
+ /**
585
+ * @description The register map of the Integro's internal (Kübler) encoder — the reference table for POST /api/devices/{slavePosition}/procedures/kuebler-register-communication, and documentation in its own right. Static: it describes the encoder type, not any connected device, so it needs no bus and no scan. Transcribed from the vendor's own draft table, then corrected against what the encoder really does: the draft calls four registers not implemented that the encoder calibration sequence reads or writes, and leaves out four more. Each entry carries the width, the access type, whether the encoder implements it, and the vendor's bit definitions verbatim, which for a bit-field register is the only place its meaning is recorded. A register the draft does not document says so in `definition`, because a reader has nowhere else to look. `format` says how to read the assembled value, because signedness is not uniform and one register is not a single number at all: `unsigned`, `signed`, `bitField` (the number means nothing on its own), or `signedHalves` — two signed 16-bit values packed into 32 bits, which register 0x3C is the only case of. `readableInOneCommand` says whether one command can carry the register, since the command's length byte caps at 4 bytes. Every register fits today, so it is true for all of them.
586
+ *
587
+ * @name GetKueblerRegisters
588
+ * @summary The Integro internal encoder's register map
589
+ * @request GET:/api/meta/kuebler-registers
590
+ */
591
+ getKueblerRegisters: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
592
+ /**
593
+ * Register address, as OS command 19 carries it.
594
+ * @example 48
595
+ */
596
+ address: number;
597
+ /**
598
+ * Width in bits — 8, 16, 32, or 64.
599
+ * @example 32
600
+ */
601
+ bits: number;
602
+ /**
603
+ * The vendor's own name for the register.
604
+ * @example "Absolute position ST"
605
+ */
606
+ name: string;
607
+ /** @example "ro" */
608
+ access: "ro" | "wo" | "rw";
609
+ /**
610
+ * Whether the encoder implements it, per the vendor's draft.
611
+ * @example true
612
+ */
613
+ implemented: boolean;
614
+ /**
615
+ * How to read the assembled value.
616
+ * @example "unsigned"
617
+ */
618
+ format: "unsigned" | "signed" | "bitField" | "signedHalves";
619
+ /**
620
+ * The vendor's bit definitions, clauses joined with "; ".
621
+ * @example "Left aligned 32 bit singleturn position"
622
+ */
623
+ definition: string;
624
+ /**
625
+ * False only for the 64-bit register, which exceeds the command's 4-byte length field.
626
+ * @example true
627
+ */
628
+ readableInOneCommand: boolean;
629
+ }[], any>>;
630
+ /**
631
+ * @description Returns the static catalogue of CoE mailbox error codes defined in ETG.1000.4, Table 30 ("Error Reply Service Data"). A slave returns one of these when the mailbox layer (below a specific protocol such as CoE/FoE) rejects a transfer; the code is embedded in the error text the mailbox endpoints return.
632
+ *
633
+ * @name GetMailboxErrorCodes
634
+ * @summary List all known CoE mailbox error codes
635
+ * @request GET:/api/meta/mailbox-error-codes
636
+ */
637
+ getMailboxErrorCodes: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<MailboxErrorCode[], any>>;
638
+ /**
639
+ * @description Returns the static catalogue of ETG.1020 data type codes used in CoE object dictionary entries. Each entry of a `DeviceParameter` carries a `dataType` field whose value is one of the codes listed here.
640
+ *
641
+ * @name GetObjectDataTypes
642
+ * @summary List all known CoE object dictionary data types
643
+ * @request GET:/api/meta/object-data-types
644
+ */
645
+ getObjectDataTypes: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ObjectDataTypeInfo[], any>>;
646
+ /**
647
+ * @description Enumerates the entire CoE object dictionary of the device at `slavePosition` via the SDO Info service ("Get Object List" → "Get Object Description" → "Get Entry Description") and rebuilds its parameter map. The device must be in PRE-OP, SAFE-OP, or OP (mailbox communication active). On a fully populated drive the call can take several seconds. When `readValues=true` each entry is additionally read via SDO upload and the decoded value is stored on the parameter. An entry that fails to read keeps the value of an earlier read with `syncState` `stale`, or the type-appropriate default with `syncState` `unknown`, and the call still succeeds. Check `syncState` to find the entries that were not read.
648
+ *
649
+ * @name InitializeDeviceParameters
650
+ * @summary Initialise the parameter list for a device by enumerating its object dictionary
651
+ * @request POST:/api/devices/{slavePosition}/parameters/init
652
+ */
653
+ initializeDeviceParameters: (slavePosition: number, query?: {
654
+ /**
655
+ * When `true`, perform an SDO upload for every entry and decode the value. Defaults to `false` — only schema (name, type, access) is populated.
656
+ * @default false
657
+ */
658
+ readValues?: boolean;
659
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceParameter[], void | {
660
+ /**
661
+ * Human-readable error message from the driver
662
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
663
+ */
664
+ error: string;
665
+ }>>;
666
+ /**
667
+ * @description Re-reads the value of every readable parameter already loaded for the device at `slavePosition`, leaving the parameter list itself intact (it does not re-enumerate the object dictionary — use `POST …/parameters/init` for that). Each value is read PDO-aware: from the live process image when the device is exchanging and the object is PDO-mapped, otherwise via an SDO upload over the mailbox. Write-only objects are skipped. Best-effort: an entry that fails to read keeps its cached value, a `synced` entry becomes `stale`, and the call still succeeds. Returns the refreshed list, ordered by `(index, subindex)`.
668
+ *
669
+ * @name ReadAllDeviceParameters
670
+ * @summary Refresh the cached value of every parameter without re-enumerating the dictionary
671
+ * @request POST:/api/devices/{slavePosition}/parameters/read
672
+ */
673
+ readAllDeviceParameters: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceParameter[], void | {
674
+ /**
675
+ * Human-readable error message from the driver
676
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
677
+ */
678
+ error: string;
679
+ }>>;
680
+ /**
681
+ * @description Returns the parameter list populated by the most recent call to `POST /api/devices/{slavePosition}/parameters/init`. Empty before the first call. Entries are ordered ascending by `(index, subindex)`.
682
+ *
683
+ * @name GetDeviceParameters
684
+ * @summary Read the previously initialised parameter list for a device
685
+ * @request GET:/api/devices/{slavePosition}/parameters
686
+ */
687
+ getDeviceParameters: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceParameter[], void>>;
688
+ /**
689
+ * @description Reads one parameter of the device at `slavePosition` and returns the full `DeviceParameter` (value plus metadata: data type, access, sync state). Unlike the raw `GET …/sdo/{index}/{subindex}` endpoint, this is PDO-aware. With `source=auto` (the default) the value is taken from the live process image when the device is exchanging and the object is PDO-mapped, otherwise via an SDO upload, otherwise from the cache. With `source=cache` the cached value is served with no bus access at all. Both `index` and `subindex` accept decimal or hexadecimal notation; prefix with `0x` for hex (e.g. `0x6064` or `24676` for object 0x6064).
690
+ *
691
+ * @name ReadParameter
692
+ * @summary Read a single parameter value (PDO-aware, with optional cache-only mode)
693
+ * @request GET:/api/devices/{slavePosition}/parameters/{index}/{subindex}
694
+ */
695
+ readParameter: (slavePosition: number, index: number, subindex: number, query?: {
696
+ /**
697
+ * `auto` (default) reads PDO-when-exchanging else SDO else cache; `cache` returns the cached value with no bus access.
698
+ * @default "auto"
699
+ */
700
+ source?: "auto" | "cache";
701
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceParameter, void | {
702
+ /**
703
+ * Human-readable error message from the driver
704
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
705
+ */
706
+ error: string;
707
+ }>>;
708
+ /**
709
+ * @description Writes one parameter of the device at `slavePosition`. The value is converted to the parameter's declared data type, then routed: staged into the process image when the device is exchanging and the object is output (RxPDO) mapped — sent on the next cycle — otherwise written via an SDO download, otherwise held in the cache as pending until the device is back online. This is the endpoint to set a target (e.g. target torque 0x6071) or the modes of operation: it knows which objects are PDO-mapped and stages them into the process data, falling back to SDO transparently. Returns the updated `DeviceParameter` (with the converted value and resulting sync state). A value the data type cannot hold is refused with 400, and nothing is written. That is a number outside the limits of an integer type (300 or -1 for an UNSIGNED8), a number with a fraction for an integer type, or a number outside the range of a REAL32. Every value that fits the data type is sent unchanged, even one outside the object's documented range, because the drive decides whether a value is valid. To send arbitrary bytes, use `sdoDownload`. Both `index` and `subindex` accept decimal or hexadecimal notation; prefix with `0x` for hex.
710
+ *
711
+ * @name WriteParameter
712
+ * @summary Write a single parameter value (PDO-aware)
713
+ * @request PUT:/api/devices/{slavePosition}/parameters/{index}/{subindex}
714
+ */
715
+ writeParameter: (slavePosition: number, index: number, subindex: number, data: {
716
+ /**
717
+ * The value to set. The server converts it to the declared type of the parameter. `ParameterValue` says which JSON type each `dataType` uses.
718
+ * @example 100
719
+ */
720
+ value: ParameterValue;
721
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceParameter, void | {
722
+ /**
723
+ * Human-readable error message from the driver
724
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
725
+ */
726
+ error: string;
727
+ }>>;
728
+ /**
729
+ * @description Reads `length` bytes from the ESC register at `address` on the slave at `slavePosition` using a Configured-Address Read (FPRD) datagram. Pass `address` in decimal (e.g. 272 for DL Status at 0x0110).
730
+ *
731
+ * @name ReadRegister
732
+ * @summary Read bytes from an ESC register
733
+ * @request GET:/api/devices/{slavePosition}/registers/{address}
734
+ */
735
+ readRegister: (slavePosition: number, address: number, query: {
736
+ /**
737
+ * Number of bytes to read
738
+ * @min 1
739
+ * @example 2
740
+ */
741
+ length: number;
742
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
743
+ /**
744
+ * Register bytes in ascending address order
745
+ * @example [65,0]
746
+ */
747
+ data: number[];
748
+ }, void | {
749
+ error: string;
750
+ } | {
751
+ /**
752
+ * Human-readable error message from the driver
753
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
754
+ */
755
+ error: string;
756
+ }>>;
757
+ /**
758
+ * @description Writes bytes to the ESC register at `address` on the slave at `slavePosition` using a Configured-Address Write (FPWR) datagram. Pass `address` in decimal (e.g. 272 for DL Status at 0x0110).
759
+ *
760
+ * @name WriteRegister
761
+ * @summary Write bytes to an ESC register
762
+ * @request POST:/api/devices/{slavePosition}/registers/{address}
763
+ */
764
+ writeRegister: (slavePosition: number, address: number, data: {
765
+ /**
766
+ * Bytes to write in ascending address order
767
+ * @example [1,0]
768
+ */
769
+ data: number[];
770
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
771
+ /** @example true */
772
+ ok: boolean;
773
+ }, void | {
774
+ error: string;
775
+ } | {
776
+ /**
777
+ * Human-readable error message from the driver
778
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
779
+ */
780
+ error: string;
781
+ }>>;
782
+ /**
783
+ * @description Reads the process-data watchdog timeout the slave at `slavePosition` is configured with, decoded from the watchdog divider (0x0400) and process-data watchdog time (0x0420) ESC registers. This is the configured timeout itself, not the expiration counter exposed by `GET /api/devices/diagnostics`. A device in OP that misses process data past this timeout faults itself to SAFE-OP+error; raising it lets a device tolerate the brief PDO pause of a whole-bus re-map.
784
+ *
785
+ * @name GetProcessDataWatchdog
786
+ * @summary Read the process-data (sync-manager) watchdog configuration
787
+ * @request GET:/api/devices/{slavePosition}/watchdog
788
+ */
789
+ getProcessDataWatchdog: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ProcessDataWatchdog, void | {
790
+ error: string;
791
+ } | {
792
+ /**
793
+ * Human-readable error message from the driver
794
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
795
+ */
796
+ error: string;
797
+ }>>;
798
+ /**
799
+ * @description Sets the process-data watchdog timeout of the slave at `slavePosition`, writing the process-data watchdog time register (0x0420). The device's watchdog divider (0x0400) is left untouched (it is shared with the PDI watchdog), so the achieved timeout is rounded to that divider's tick base — the response reports the value actually programmed. A `timeoutMs` of 0 disables the watchdog. The write persists across re-maps and re-scans until the ESC reloads EEPROM (power cycle).
800
+ *
801
+ * @name SetProcessDataWatchdog
802
+ * @summary Set the process-data (sync-manager) watchdog timeout
803
+ * @request PUT:/api/devices/{slavePosition}/watchdog
804
+ */
805
+ setProcessDataWatchdog: (slavePosition: number, data: {
806
+ /**
807
+ * Desired watchdog timeout in milliseconds; 0 disables the watchdog
808
+ * @format double
809
+ * @min 0
810
+ * @example 200
811
+ */
812
+ timeoutMs: number;
813
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ProcessDataWatchdog, void | {
814
+ error: string;
815
+ } | {
816
+ /**
817
+ * Human-readable error message from the driver
818
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
819
+ */
820
+ error: string;
821
+ }>>;
822
+ /**
823
+ * @description Reads the PDO mapping of the slave at `slavePosition` over CoE, grouped by mapping object: the sync-manager assignment (0x1C12 outputs / 0x1C13 inputs) and, for each assigned mapping object (0x16xx / 0x1Axx), its `pdoIndex` and ordered entries. `outputs` are RxPDO objects (master→slave), `inputs` are TxPDO objects (slave→master). Each entry carries its derived `bitOffset` within the direction's window. This is the grouped, round-trippable counterpart of the flat, whole-bus `GET /api/process-image`. Reads fresh over SDO, so the device's mailbox must be active (PRE-OP, SAFE-OP, or OP); a device in INIT or BOOT yields 409.
824
+ *
825
+ * @name GetDevicePdoMapping
826
+ * @summary Read a device's PDO mapping grouped by object (CoE)
827
+ * @request GET:/api/devices/{slavePosition}/pdo-mapping
828
+ */
829
+ getDevicePdoMapping: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<PdoMapping, void | {
830
+ /**
831
+ * Human-readable error message from the driver
832
+ * @example "FPRD slave 1: wkc=0"
833
+ */
834
+ error: string;
835
+ }>>;
836
+ /**
837
+ * @description Reconfigures the PDO mapping of the slave at `slavePosition` over CoE: both directions' sync-manager assignment (0x1C12 outputs / 0x1C13 inputs) and the referenced mapping objects (0x16xx / 0x1Axx). `outputs` are RxPDO objects (master→slave), `inputs` are TxPDO objects (slave→master); the array order is the sync-manager assignment order, which fixes each object's position in the process image. Both directions must be present — an empty array clears that sync manager's assignment. **The device must be in PRE-OP.** The mapping and assignment objects are writable only in PRE-OP; in SAFE-OP/OP the sync managers are active and the slave rejects the write, and INIT/BOOT have no CoE mailbox. This is the "drop to PRE-OP, remap, climb back" flow: take the device to PRE-OP (`POST /api/devices/state`), call this, then transition it back to SAFE-OP/OP — at which point the whole-bus process image is re-mapped from the new mapping. The write follows the CoE ordering rule (clear assignment, rewrite each mapping object, then re-assign), is read back and verified, and is retried a few times so a dropped mailbox frame cannot leave the object dictionary half-configured. The response is the device's grouped read-back mapping (same shape as GET), whose `bitOffset` values are derived by the device (the request omits them). This endpoint does not itself change the AL state or re-map the process image.
838
+ *
839
+ * @name WriteDevicePdoMapping
840
+ * @summary Rewrite a device's PDO mapping (CoE)
841
+ * @request PUT:/api/devices/{slavePosition}/pdo-mapping
842
+ */
843
+ writeDevicePdoMapping: (slavePosition: number, data: PdoMappingRequest, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<PdoMapping, void | {
844
+ /**
845
+ * Human-readable error message from the driver
846
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
847
+ */
848
+ error: string;
849
+ }>>;
850
+ /**
851
+ * @description Returns the drive's current control state — the decoded state-machine state, the raw status (0x6041) and control (0x6040) words, and the active operation mode (display object 0x6061). The values are read live (from the process image when the device is exchanging, else over SDO), so poll this to drive a motion UI. Only valid for a CiA402 device (see the isCia402 flag on GET /api/devices).
852
+ *
853
+ * @name GetCia402Status
854
+ * @summary Read a device's CiA402 control snapshot
855
+ * @request GET:/api/devices/{slavePosition}/cia402
856
+ */
857
+ getCia402Status: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Cia402Status, void>>;
858
+ /**
859
+ * @description Every operation mode the device has, standard and manufacturer-specific, with what the drive says about each. The standard modes are CiA402's (ETG.6010 §6.8.1) and carry the bit of "Supported drive modes" (0x6502) that advertises them, decoded into `supported`. The manufacturer modes are the vendor's own — the negative half of 0x6060 — and are listed only for a device whose vendor this server knows; their `supported` is null, because 0x6502 reserves bits 16-31 for the vendor without defining them, so a drive has no way to advertise one that a master could read. That null means "the drive does not say", not "no". Read this once per device and cache it: it is a static property of the firmware, and the one thing that makes a negative value of 0x6061 nameable rather than "Unknown".
860
+ *
861
+ * @name GetOperationModes
862
+ * @summary List a device's operation modes
863
+ * @request GET:/api/devices/{slavePosition}/operation-modes
864
+ */
865
+ getOperationModes: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<OperationModes, void>>;
866
+ /**
867
+ * @description Writes the requested operation mode to 0x6060 and returns the resulting control snapshot. The drive reflects the accepted mode in 0x6061 (the modeOfOperation of the response) once it takes effect. Any value object 0x6060 can hold is accepted, standard or manufacturer-specific — the negative half of that range belongs to the vendor, so a SOMANET's diagnostics (-2) or system identification (-4) go through here like any other. Whether a given drive has the mode is the drive's answer, seen in the modeOfOperation of the response; GET /api/devices/{slavePosition}/operation-modes is what lists them beforehand.
868
+ *
869
+ * @name SetCia402OperationMode
870
+ * @summary Set a device's CiA402 operation mode
871
+ * @request POST:/api/devices/{slavePosition}/cia402/mode
872
+ */
873
+ setCia402OperationMode: (slavePosition: number, data: {
874
+ /**
875
+ * Operation mode to request (the 0x6060 value). Standard modes are 0 NoMode, 1 Profile Position, 2 Velocity, 3 Profile Velocity, 4 Profile Torque, 6 Homing, 7 Interpolated Position, 8 Cyclic Sync Position, 9 Cyclic Sync Velocity, 10 Cyclic Sync Torque, 11 Cyclic Sync Torque with Commutation Angle; negative values are the vendor's.
876
+ * @min -128
877
+ * @max 127
878
+ * @example 9
879
+ */
880
+ mode: number;
881
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Cia402Status, void>>;
882
+ /**
883
+ * @description Walks the CiA402 device-control state machine to the state you name, issuing whatever transitions that takes and re-reading the drive between each — so multi-hop paths are ordinary: Switch On Disabled up to Operation Enabled, Quick Stop Active back down to Ready To Switch On. Starting from Fault begins with a fault reset, and a fault whose cause is still present is reported as such (with the drive's 0x603F error code) rather than as a timeout. Only the five states a master can command are accepted. Not Ready To Switch On, Fault Reaction Active and Fault are entered by the drive itself and are rejected as a bad request. **Asking for Operation Enabled while the drive is in Quick Stop Active leaves that quick stop** (CiA402 transition 16), because naming the destination is an explicit instruction to go there. The "enable" command on the sibling endpoint deliberately does not, so a procedure preparing a drive cannot undo somebody's stop by accident. The device must be exchanging process data for any of this to progress — the statusword has to update between polls, and the firmware refuses Operation Enabled unless master communication is live. Returns the resulting control snapshot.
884
+ *
885
+ * @name TransitionToCia402State
886
+ * @summary Bring a drive to a CiA402 state
887
+ * @request POST:/api/devices/{slavePosition}/cia402/state
888
+ */
889
+ transitionToCia402State: (slavePosition: number, data: {
890
+ /**
891
+ * The state to bring the drive to.
892
+ * @example "OperationEnabled"
893
+ */
894
+ state: "SwitchOnDisabled" | "ReadyToSwitchOn" | "SwitchedOn" | "OperationEnabled" | "QuickStopActive";
895
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Cia402Status, void>>;
896
+ /**
897
+ * @description Drives the CiA402 device-control state machine. "enable" walks every intermediate transition to Operation Enabled (clearing a fault first if needed); "disable" goes to Switch On Disabled; "quickStop" triggers a quick stop; "faultReset" clears a latched fault. The device must be exchanging process data for "enable" to make progress. Returns the resulting control snapshot. Use POST /api/devices/{slavePosition}/cia402/state to name a destination instead of an action — it reaches states these four cannot, and it is the one that will leave a quick stop. "enable" here deliberately will not.
898
+ *
899
+ * @name RunCia402Command
900
+ * @summary Run a CiA402 state-machine command
901
+ * @request POST:/api/devices/{slavePosition}/cia402/command
902
+ */
903
+ runCia402Command: (slavePosition: number, data: {
904
+ /**
905
+ * The state-machine action to perform.
906
+ * @example "enable"
907
+ */
908
+ command: "enable" | "disable" | "quickStop" | "faultReset";
909
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Cia402Status, void>>;
910
+ /**
911
+ * @description Writes the one setpoint that matches the active operation mode — target position (0x607A, INTEGER32) in PP/CSP, target velocity (0x60FF, INTEGER32) in PV/CSV, or target torque (0x6071, INTEGER16, per-mille of rated) in PT/CST. All are signed: negative values command reverse motion or regenerative torque. Routes through the live process image when the object is PDO-mapped and the device is exchanging, else an SDO download.
912
+ *
913
+ * @name SetCia402Target
914
+ * @summary Set a CiA402 cyclic setpoint (target)
915
+ * @request POST:/api/devices/{slavePosition}/cia402/target
916
+ */
917
+ setCia402Target: (slavePosition: number, data: {
918
+ /**
919
+ * Which setpoint to write (pick the one matching the active mode).
920
+ * @example "velocity"
921
+ */
922
+ target: "position" | "velocity" | "torque";
923
+ /**
924
+ * The setpoint value in the object's own units (signed). For torque it is per-mille of rated and is narrowed to INTEGER16.
925
+ * @example 1000
926
+ */
927
+ value: number;
928
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<void, void>>;
929
+ /**
930
+ * @description Copies the actual value into the target of one kind: position actual value (0x6064) into target position (0x607A), velocity actual value (0x606C) into target velocity (0x60FF), or torque actual value (0x6077) into target torque (0x6071). Without `kind` the pair is the one the active operation mode (0x6061) acts on. A drive holds its actual position only until the first setpoint reaches it. In CSP the master sends 0x607A every cycle, so a drive enabled with a stale target position steps to it at once, and that step can pull the supply down. Call this before you enable a drive in CSP. Motion Master never does it on its own: an enable writes the controlword and nothing else.
931
+ *
932
+ * @name SetCia402TargetToActual
933
+ * @summary Set a CiA402 target to its actual value
934
+ * @request POST:/api/devices/{slavePosition}/cia402/target/actual
935
+ */
936
+ setCia402TargetToActual: (slavePosition: number, query?: {
937
+ /**
938
+ * Which pair to copy. Omit it to copy the pair of the active operation mode.
939
+ * @example "position"
940
+ */
941
+ kind?: "position" | "velocity" | "torque";
942
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
943
+ /**
944
+ * The pair that was copied.
945
+ * @example "position"
946
+ */
947
+ kind: "position" | "velocity" | "torque";
948
+ /**
949
+ * The value written, in the object's own units. Torque is per mille of rated, widened from INTEGER16.
950
+ * @example 123456
951
+ */
952
+ value: number;
953
+ }, void>>;
954
+ /**
955
+ * @description Returns every procedure available on the device, each with its descriptor and the state of its current or last run. One request is enough to render a whole per-device procedures view: the descriptor carries the title, description and caveats to display, and the snapshot says whether anything is running or how the last run went. The list is per device, not global — a procedure is offered only where it applies, so a third-party slave reports an empty list rather than controls that could only ever fail. A procedure that has never run reports an idle snapshot (`status` `idle`, `runCount` 0, every step `idle`), so every entry has the same shape.
956
+ *
957
+ * @name ListProcedures
958
+ * @summary List the procedures a device supports
959
+ * @request GET:/api/devices/{slavePosition}/procedures
960
+ */
961
+ listProcedures: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ProcedureListing[], void>>;
962
+ /**
963
+ * @description Starts the named procedure and returns as soon as the run is under way — this does **not** wait for it to finish. Poll `GET` on the same path for its outcome, or `DELETE` to cancel it. The request body carries the procedure's parameters, and each descriptor from `GET /api/devices/{slavePosition}/procedures` reports its own in `parameters` — name, type, bounds, default, and whether it is required — which is enough to build a form for any procedure without hard-coding one per name. A procedure that takes no parameters may be started with no body. Only one procedure may run on a device at a time; a second start is refused with 409 while the first is in flight. Most procedures require an active mailbox, so the device must be in PRE-OP, SAFE-OP or OP. A run the drive answers with an error is not a failure of *this* request — it is reported in the snapshot as a failed run.
964
+ *
965
+ * @name StartProcedure
966
+ * @summary Start a procedure on a device
967
+ * @request POST:/api/devices/{slavePosition}/procedures/{procedureName}
968
+ */
969
+ startProcedure: (slavePosition: number, procedureName: string, data?: ProcedureRequest, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ProcedureSnapshot, void>>;
970
+ /**
971
+ * @description Returns the current run, or the last one to have finished. This is the whole progress surface — there is no push channel — and polling it is lossless: every finished step keeps its terminal status and value, so a step that both starts and completes between two polls is still reported as succeeded. A polling loop is `while status == "running"`. A procedure that has never run is not an absence: it reports an idle snapshot built from the procedure's step template, so a client renders one shape and needs no empty-state branch. The snapshot is retained after a run ends, so a client that reconnects (or a user returning to a page) sees how the last run went. It is dropped when the device set is rebuilt by a scan or reset, because bus positions may then name different hardware.
972
+ *
973
+ * @name GetProcedure
974
+ * @summary Read the state of a procedure on a device
975
+ * @request GET:/api/devices/{slavePosition}/procedures/{procedureName}
976
+ */
977
+ getProcedure: (slavePosition: number, procedureName: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ProcedureSnapshot, void>>;
978
+ /**
979
+ * @description Asks the running procedure to stop and returns immediately. Where the procedure is waiting on the drive it also tells the drive to abort (for an OS command, 0x1024 = 3), so a run that is waiting stops when asked rather than carrying on to completion. The run then finishes with status `cancelled`. This cancels the *run*, not the record: the snapshot remains and reports how far it got.
980
+ *
981
+ * @name CancelProcedure
982
+ * @summary Cancel a running procedure on a device
983
+ * @request DELETE:/api/devices/{slavePosition}/procedures/{procedureName}
984
+ */
985
+ cancelProcedure: (slavePosition: number, procedureName: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<void, void>>;
986
+ /**
987
+ * @description Reports both encoder configuration records, 0x2110 (encoder 1) and 0x2112 (encoder 2), and the encoder each controller uses: position control from 0x2012:09, velocity control from 0x2011:05, commutation from 0x2010:0C. A record whose type is `none` is still listed, because the controller fields refer to the ordinal. Read this to learn what one revolution is in position counts. A position in 0x6064 or 0x607A is in counts of the position encoder, unscaled by the gear ratio (0x6091), so one revolution of that encoder is its `resolution`. The feed constant (0x6092) is not applied here.
988
+ *
989
+ * @name GetEncoders
990
+ * @summary Read a SOMANET drive's encoders and which controller uses which
991
+ * @request GET:/api/devices/{slavePosition}/encoders
992
+ */
993
+ getEncoders: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Encoders, void>>;
994
+ /**
995
+ * @description Reports the brake objects (0x2004) that decide what a release or engage will do: its current state, the release strategy, the pull time and the pull/hold voltages. Read this before commanding the brake. `softwareControllable` is false when the release strategy is `manualOutputVoltage`, meaning the firmware does not drive the brake at all and both commands below are no-ops. `releaseMovesShaft` is true for a pin brake, whose release procedure turns the motor to lift the load off the pin.
996
+ *
997
+ * @name GetBrake
998
+ * @summary Read a drive's brake configuration and state
999
+ * @request GET:/api/devices/{slavePosition}/brake
1000
+ */
1001
+ getBrake: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<BrakeState, void>>;
1002
+ /**
1003
+ * @description Reads the files the `hrd-streaming` procedure recorded, concatenates them in order and decodes them into samples. Run that procedure first; this endpoint only reads what is already on the drive. **`data` is required and must match what was recorded.** Nothing on the drive says which signal its files hold, so the wrong selection reinterprets the same bytes as a different layout and returns plausible nonsense. The procedure's `configure-stream` step reports the selection it used for exactly this reason. Samples travel positionally — `columns` names the fields of each row, once, the way a monitoring topic ships its parameter order once — because a full recording is up to ten thousand rows. `trailingBytes` is what was left over past the last whole sample: the drive allocates its files in fixed-size blocks, so a recording that does not fill the last block ends in padding rather than data. Answers **JSON or CSV**, chosen by the `Accept` header. CSV is the same numbers in the same column order, one header row then one row per sample — a file to open in a spreadsheet rather than JSON to read, which for ten thousand rows is usually what is wanted. Values are decoded, not raw: `velocityRpm` is converted out of the file's Q15 fixed point (exactly — multiply by 32768 to recover the stored integer), while `torquePermil` and the encoder's `raw` word are the file's own values. Blocks for the transfer, which is up to five 8 KB FoE reads plus the listing.
1004
+ *
1005
+ * @name ReadHrdRecording
1006
+ * @summary Read back a drive's high resolution data recording
1007
+ * @request GET:/api/devices/{slavePosition}/hrd
1008
+ */
1009
+ readHrdRecording: (slavePosition: number, query: {
1010
+ /**
1011
+ * Which layout the files hold — the same selection the recording was made with.
1012
+ * @example "encoder-raw"
1013
+ */
1014
+ data: "encoder-raw" | "system-identification";
1015
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<HrdRecording, void>>;
1016
+ /**
1017
+ * @description Writes "disengaged" to the brake state object (0x2004:07) and waits the drive's pull time (0x2004:03) plus `settle` before answering, because the firmware blocks motion — and motion-related OS commands — until the pull time expires. Answers with the brake state read back. **The release only actually happens while the drive is in OP ENABLED.** In any other state the write merely energises the brake output (phase D). Note also that entering OP ENABLED releases the brake automatically in normal operation but **not** in diagnostics mode, where the master owns the brake — which is why a diagnostics procedure has to call this. **On a pin brake this moves the shaft**: the controller raises current progressively until the load has lifted off the pin by the minimum displacement (0x2004:08), reversing direction if it reaches the current ceiling (0x2004:09, a percentage of rated current) first. Check `releaseMovesShaft` on `GET .../brake`. Brake release is open-loop — nothing confirms the brake let go — so the wait is the only margin there is. A brake whose release strategy is `manualOutputVoltage` is left alone and the returned state says so; that is not an error. **A released brake stays released**: nothing re-engages it for you, so on a vertical or loaded axis engage it again when you are done.
1018
+ *
1019
+ * @name ReleaseBrake
1020
+ * @summary Release (disengage) a drive's brake
1021
+ * @request POST:/api/devices/{slavePosition}/brake/release
1022
+ */
1023
+ releaseBrake: (slavePosition: number, query?: {
1024
+ /**
1025
+ * Extra wait in milliseconds on top of the drive's pull time. Size it for the machine — release is open-loop, so this is the only margin between "commanded" and "assumed released".
1026
+ * @min 0
1027
+ * @default 50
1028
+ * @example 50
1029
+ */
1030
+ settle?: number;
1031
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<BrakeState, void>>;
1032
+ /**
1033
+ * @description Writes "engaged" to the brake state object (0x2004:07) and waits `settle` before answering with the brake state read back. There is no pull time on the way in — a brake is spring-engaged, so engaging it is the removal of voltage — so the wait is only `settle`. As with release, a brake whose release strategy is `manualOutputVoltage` is left alone and the returned state says so.
1034
+ *
1035
+ * @name EngageBrake
1036
+ * @summary Engage a drive's brake
1037
+ * @request POST:/api/devices/{slavePosition}/brake/engage
1038
+ */
1039
+ engageBrake: (slavePosition: number, query?: {
1040
+ /**
1041
+ * How long to wait in milliseconds after commanding the brake before answering.
1042
+ * @min 0
1043
+ * @default 50
1044
+ * @example 50
1045
+ */
1046
+ settle?: number;
1047
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<BrakeState, void>>;
1048
+ /**
1049
+ * @description Performs a CoE SDO upload — reads the value of object `index:subindex` from the device at `slavePosition` and returns the raw bytes as a JSON array. Both `index` and `subindex` accept decimal or hexadecimal notation; prefix with `0x` for hex (e.g. `0x6064` or `24676` for object 0x6064).
1050
+ *
1051
+ * @name SdoUpload
1052
+ * @summary Upload an object dictionary entry from a device (CoE SDO upload)
1053
+ * @request GET:/api/devices/{slavePosition}/sdo/{index}/{subindex}
1054
+ */
1055
+ sdoUpload: (slavePosition: number, index: number, subindex: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1056
+ /**
1057
+ * Object bytes as transferred by the SDO upload
1058
+ * @example [0,0,0,0]
1059
+ */
1060
+ data: number[];
1061
+ }, void | {
1062
+ /**
1063
+ * Human-readable error message from the driver
1064
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1065
+ */
1066
+ error: string;
1067
+ }>>;
1068
+ /**
1069
+ * @description Performs a CoE SDO download — writes the raw bytes in the request body to object `index:subindex` on the device at `slavePosition`. The byte count must match the object's length. Requires the device to be in PRE-OP, SAFE-OP, or OP (mailbox communication active). Both `index` and `subindex` accept decimal or hexadecimal notation; prefix with `0x` for hex (e.g. `0x6064` or `24676`).
1070
+ *
1071
+ * @name SdoDownload
1072
+ * @summary Download an object dictionary entry to a device (CoE SDO download)
1073
+ * @request PUT:/api/devices/{slavePosition}/sdo/{index}/{subindex}
1074
+ */
1075
+ sdoDownload: (slavePosition: number, index: number, subindex: number, data: {
1076
+ /**
1077
+ * Object bytes to write (little-endian, must match the object length)
1078
+ * @example [100,0,0,0]
1079
+ */
1080
+ data: number[];
1081
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1082
+ /** @example true */
1083
+ ok: boolean;
1084
+ }, void | {
1085
+ /**
1086
+ * Human-readable error message from the driver
1087
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1088
+ */
1089
+ error: string;
1090
+ }>>;
1091
+ /**
1092
+ * @description Lists what the device holds — firmware images, the ESI, logs, configuration and any high resolution data recording — with the size it reports for each. **Vendor-specific despite reading like a filesystem listing.** EtherCAT defines no directory service, so SOMANET firmware serves its own as a pseudo-file (`fs-getlist`) read over FoE. A device that is not a SOMANET drive is refused rather than probed. `byteCount` is absent when the device reported a name without a size, which is a formatting quirk of one entry rather than a reason to hide the file.
1093
+ *
1094
+ * @name ListDeviceFiles
1095
+ * @summary List the files stored on a device
1096
+ * @request GET:/api/devices/{slavePosition}/files
1097
+ */
1098
+ listDeviceFiles: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceFile[], void>>;
1099
+ /**
1100
+ * @description Reads and decodes the device's `.hardware_description` file over FoE — its product id and revision, serial number, the components it is built from, and the assembly it was packaged into. It is also the only source of the descriptor that decides which firmware belongs on the device, which is what most callers want it for (see `/api/devices/{slavePosition}/firmware-compatibility`). **Readable in BOOT as well as PRE-OP and above.** The bootloader deliberately allows this one file, which is what lets a compatibility check work on a drive a failed install left stranded there — precisely when knowing whether the package was the right one matters most.
1101
+ *
1102
+ * @name GetDeviceHardwareDescription
1103
+ * @summary Read what a device says it is
1104
+ * @request GET:/api/devices/{slavePosition}/hardware-description
1105
+ */
1106
+ getDeviceHardwareDescription: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<HardwareDescription, void>>;
1107
+ /**
1108
+ * @description Reads and decodes the device's `.variant` file over FoE — which features the Integro was licensed with. **A 404 is the ordinary answer for most devices.** Only Integro drives carry this file, so the resource being absent is normal rather than a problem. Its one property that matters beyond inspection is `fieldbusProtocol`, which the hardware description deliberately does not carry and a full firmware descriptor ends with.
1109
+ *
1110
+ * @name GetDeviceIntegroVariant
1111
+ * @summary Read a device's Integro variant file
1112
+ * @request GET:/api/devices/{slavePosition}/variant
1113
+ */
1114
+ getDeviceIntegroVariant: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<IntegroVariant, void>>;
1115
+ /**
1116
+ * @description Reads the device's `.hardware_description` and `.variant`, assembles the full firmware descriptors it accepts, and compares them against the descriptor in `filename`. **A mismatch is a `200` carrying `compatible: false`**, not an error status: the client asked a question and got an answer, and the body names both descriptors so it can say which hardware the package was for. A `4xx` means the question could not be asked — the filename is not a package name, or the hardware description could not be read. **Nothing acts on the answer.** The firmware installation procedure writes whatever it is given, on purpose, so this exists to tell a user before they start.
1117
+ *
1118
+ * @name CheckDeviceFirmwareCompatibility
1119
+ * @summary Check whether a firmware package belongs on a device
1120
+ * @request GET:/api/devices/{slavePosition}/firmware-compatibility
1121
+ */
1122
+ checkDeviceFirmwareCompatibility: (slavePosition: number, query: {
1123
+ /**
1124
+ * The package filename, with no directory part.
1125
+ * @example "package_SOMANET-Circulo-7_8500-04-2332_motion-drive_v5.6.10.zip"
1126
+ */
1127
+ filename: string;
1128
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<FirmwareCompatibility, void>>;
1129
+ /**
1130
+ * @description Sends an FoE read request for `filename` to the device at `slavePosition` and returns the raw file bytes. FoE is available in Boot, Pre-Op, Safe-Op, and Op states (device-dependent); the caller is responsible for ensuring the device is in a suitable state before calling. The call blocks until the full file has been received. Over EtherCAT it waits up to 6 s for the device's answer and tries a read that gets no answer up to 3 times, so a device that never answers takes about 18 s to fail. A refusal from the device is not tried again. After a failure without an answer, Motion Master aborts the transfer on the device, so that the next request works. Over SPoE it waits the configured file timeout for each packet. When the device refuses the read, the error names the FoE error code it sent and its meaning, and the device's error text when that adds anything, e.g. `FOEread slave 1 'x.bin' failed (FoE error 0x8001: Not found)`. A device that never answered gives `(no response)`.
1131
+ *
1132
+ * @name FoeReadFile
1133
+ * @summary Read a file from a device via FoE (File over EtherCAT)
1134
+ * @request GET:/api/devices/{slavePosition}/files/{filename}
1135
+ */
1136
+ foeReadFile: (slavePosition: number, filename: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Blob, void | {
1137
+ /**
1138
+ * Human-readable error message from the driver
1139
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1140
+ */
1141
+ error: string;
1142
+ }>>;
1143
+ /**
1144
+ * @description Sends an FoE write request for `filename` to the device at `slavePosition`, streaming the raw request body as the file contents. FoE is available in Boot, Pre-Op, Safe-Op, and Op states (device-dependent); the caller is responsible for ensuring the device is in a suitable state before calling. Over EtherCAT it waits up to 10 s for the device to acknowledge each packet. A write that fails without an answer is aborted on the device and is not tried again.
1145
+ *
1146
+ * @name FoeWriteFile
1147
+ * @summary Write a file to a device via FoE (File over EtherCAT)
1148
+ * @request PUT:/api/devices/{slavePosition}/files/{filename}
1149
+ */
1150
+ foeWriteFile: (slavePosition: number, filename: string, data: File, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1151
+ /** @example true */
1152
+ ok?: boolean;
1153
+ }, void | {
1154
+ /**
1155
+ * Human-readable error message from the driver
1156
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1157
+ */
1158
+ error: string;
1159
+ }>>;
1160
+ /**
1161
+ * @description Deletes `filename` from the flash of the device at `slavePosition`. Motion Master waits up to 10 s for the device to answer, and 30 s for the ESI (`SOMANET_CiA_402.xml.zip`), because the device answers only after it has erased the file. **Vendor-specific despite reading like a filesystem operation.** FoE has no delete, so SOMANET firmware acts on a pseudo-file instead: reading the name `fs-remove=<filename>` removes that file. This endpoint exists so no client has to know that, and a device that is not a SOMANET drive is refused rather than probed. **A file that was not there answers 200.** The caller asked for the file to be gone, and it is. Every other FoE failure is a 500 naming the reason. The file is gone from flash immediately. Deleting `config.csv` discards the stored parameter values, so the drive falls back to its defaults on the next power cycle.
1162
+ *
1163
+ * @name DeleteDeviceFile
1164
+ * @summary Delete a file from a device
1165
+ * @request DELETE:/api/devices/{slavePosition}/files/{filename}
1166
+ */
1167
+ deleteDeviceFile: (slavePosition: number, filename: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1168
+ /** @example true */
1169
+ ok?: boolean;
1170
+ }, void | {
1171
+ /**
1172
+ * Human-readable error message from the driver
1173
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1174
+ */
1175
+ error: string;
1176
+ }>>;
1177
+ /**
1178
+ * @description Reads the raw SII EEPROM image of the device at `slavePosition` through the ESC's EEPROM-control registers and returns either the parsed structure or the raw bytes, selected by the `Accept` request header. With `Accept: application/json` (or `*\/*`, or no `Accept` header) the parsed `SlaveInformationInterface` is returned — the 128-byte fixed header plus the decoded category section (strings, general info, FMMU/Sync-Manager and PDO defaults, distributed-clock settings). With `Accept: application/octet-stream` the raw EEPROM image is returned unparsed, suitable for a hex dump or archival. EEPROM access is a control-plane operation and is most reliable while the device is in INIT or PRE-OP. String-index fields in the parsed structure (e.g. `general.nameIdx`) are 1-based references into `category.strings`.
1179
+ *
1180
+ * @name ReadSii
1181
+ * @summary Read a device's SII (Slave Information Interface / EEPROM)
1182
+ * @request GET:/api/devices/{slavePosition}/sii
1183
+ */
1184
+ readSii: (slavePosition: number, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<SlaveInformationInterface, void | {
1185
+ error: string;
1186
+ } | {
1187
+ /**
1188
+ * Human-readable error message from the driver
1189
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1190
+ */
1191
+ error: string;
1192
+ }>>;
1193
+ /**
1194
+ * @description Writes the raw SII image in the request body to the device's EEPROM, one 16-bit word at a time. The image is parse-validated first and rejected if it is not a well-formed SII (a guard against bricking the device). **Destructive:** a wrong image can leave the device unidentifiable until re-flashed. The device adopts the new contents only after a **power cycle**, and the write is most reliable while the device is in INIT or PRE-OP. Intended for restoring a previously downloaded image.
1195
+ *
1196
+ * @name WriteSii
1197
+ * @summary Write a raw SII (EEPROM) image to a device
1198
+ * @request PUT:/api/devices/{slavePosition}/sii
1199
+ */
1200
+ writeSii: (slavePosition: number, data: File, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1201
+ /** @example true */
1202
+ ok?: boolean;
1203
+ }, void | {
1204
+ error: string;
1205
+ } | {
1206
+ /**
1207
+ * Human-readable error message from the driver
1208
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1209
+ */
1210
+ error: string;
1211
+ }>>;
1212
+ /**
1213
+ * @description Decodes a raw SII EEPROM image supplied in the request body and returns the parsed structure — the same decoder the device read path uses, exposed as a bus-independent utility. No device is involved; the Tools SII page uses this to view previously downloaded `.bin` files offline.
1214
+ *
1215
+ * @name ParseSii
1216
+ * @summary Parse a raw SII (EEPROM) image
1217
+ * @request POST:/api/sii/parse
1218
+ */
1219
+ parseSii: (data: File, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<SlaveInformationInterface, void>>;
1220
+ /**
1221
+ * @description Breaks a firmware package filename into the five fields the SOMANET naming convention defines (Hardware description specification §3.4.2) — `package_<hardware>_<fullFirmwareDescriptor>_<software>_v<version>.zip` — and, where the descriptor is the numeric `<id>-<version>[-<key>[-<fieldbus>]]` kind, decodes it further. The specification allows a descriptor that is not (its own example `Branded-Drive-Elite` carries `MyProduct-v25-key3-ecat`), so those four fields are omitted rather than guessed. Bus-independent, like `/api/sii/parse` and `/api/esi/parse`, but a `GET` with a query because there is no file to upload — only a short string. This is the same decoder firmware installation uses to decide whether a package can be cached, so what it reports is what that will do.
1222
+ *
1223
+ * @name GetFirmwarePackageName
1224
+ * @summary Decode a SOMANET firmware package filename
1225
+ * @request GET:/api/firmware-package-name
1226
+ */
1227
+ getFirmwarePackageName: (query: {
1228
+ /**
1229
+ * The package filename, with no directory part.
1230
+ * @example "package_SOMANET-Circulo-7_8500-04-2332_motion-drive_v5.6.10.zip"
1231
+ */
1232
+ filename: string;
1233
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<FirmwarePackageName, void>>;
1234
+ /**
1235
+ * @description Decodes a `.hardware_description` supplied in the request body. No device is involved — the same parse a device read uses, so a file saved from one device can be inspected with no hardware present. Three things fail a parse: content that is not JSON, content with no `device` object, and a device carrying no `id` or no `version`. Everything else is accepted as written. Those three required fields are exactly what a descriptor is built from, which is also what makes this a usable type check — arbitrary JSON is rejected rather than yielding an empty descriptor. The `fileVersion` major is reported but not enforced: a bump means "a new parser is needed", but refusing an unknown one would make a drive flashed with a future file unreadable today.
1236
+ *
1237
+ * @name ParseHardwareDescription
1238
+ * @summary Parse a .hardware_description file
1239
+ * @request POST:/api/hardware-description/parse
1240
+ */
1241
+ parseHardwareDescription: (data: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<HardwareDescription, void>>;
1242
+ /**
1243
+ * @description Decodes a `.variant` file supplied in the request body. Binary rather than text, hence a `POST` with bytes like `/api/sii/parse` rather than a query like `/api/firmware-package-name`. Trailing bytes past the last option are accepted: the firmware reads only as many options as the count claims and ignores the rest, so refusing padding would reject a file the drive is happy with.
1244
+ *
1245
+ * @name ParseIntegroVariant
1246
+ * @summary Parse a .variant file
1247
+ * @request POST:/api/integro-variant/parse
1248
+ */
1249
+ parseIntegroVariant: (data: File, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<IntegroVariant, void>>;
1250
+ /**
1251
+ * @description Every option an Integro can be licensed with, in code order. Static data: no device, no bus, no request body. Served so a client can explain a decoded file — or simply show what is available — without carrying a second copy of a table that belongs to the firmware. The codes ascend with real gaps, and the catalogue keeps codes current firmware no longer implements, because files written years ago still carry them.
1252
+ *
1253
+ * @name ListIntegroVariantOptions
1254
+ * @summary The whole Integro variant option catalogue
1255
+ * @request GET:/api/integro-variant/options
1256
+ */
1257
+ listIntegroVariantOptions: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<IntegroVariantOption[], any>>;
1258
+ /**
1259
+ * @description Decodes an ENI document supplied in the request body. No device is involved, and that is the point: the useful case is reading a configuration somebody else's tool wrote — acontis EC-Engineer, TwinCAT — rather than the one this master exports from `GET /api/eni`. **An ENI is a script, not a description.** Every configuration step in it is an EtherCAT datagram or a CoE download tagged with the AL-state transition it belongs to, so a listing of the raw elements would show `FPWR to 2064, data 0018060064000100` and leave the reading undone. Each datagram therefore carries a `register` object naming what its `ado` selects, with the instance for a repeating block, and `decoded` fields where the payload is a sync-manager or FMMU register block. A write to AL Control reports `requestsState`, and the read that follows it reports `waitsForState`. Every enumeration is spelled out beside its value — `cmd` 5 with `cmdName` `FPWR`, transitions as `IP`/`PS`/`SO` — and every payload carries its hex beside its byte count, because the reader of this JSON is a person rather than a master. Tolerant by design. Only three things fail: XML that will not parse, a root that is not `EtherCATConfig`, and a missing `Config`. Anything else costs that value and a line in `warnings`, including an element this model has no room for. The sample documents ETG itself ships need that tolerance: two of them omit elements their own schema marks mandatory, and a previous port of `A` is spec-legal while ENI Schema 1.7 enumerates only `B`, `C` and `D`.
1260
+ *
1261
+ * @name ParseEni
1262
+ * @summary Parse an EtherCAT Network Information (ENI) file
1263
+ * @request POST:/api/eni/parse
1264
+ */
1265
+ parseEni: (data: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1266
+ /** The master, every device, the cyclic frame and the process image, keyed by the model's own field names. */
1267
+ network: object;
1268
+ /** One line per element seen and not modelled, or per value that would not decode. Each names a place in the document. */
1269
+ warnings: string[];
1270
+ summary: {
1271
+ /** Devices in the document */
1272
+ devices: number;
1273
+ /** EtherCAT init commands, master and devices together */
1274
+ datagrams: number;
1275
+ /** CoE init commands, which live under a device's mailbox */
1276
+ coeTransfers: number;
1277
+ };
1278
+ }, void>>;
1279
+ /**
1280
+ * @description Decodes a vendor's ESI XML supplied in the request body. No device is involved — the Tools page uses this to inspect an ESI with no hardware present, which is the only way to see object descriptions, enum option labels, engineering units and min/max bounds: the CoE SDO-Information service reports none of them. The response carries the vendor, every module, and **every device with its own assembled `entries` table** — one row per addressable `(index, subindex)`, merged from the device's own dictionary plus the dictionaries of the modules its slots reference, with each row recording in `source` where it came from. Object-level annotation (an object's description and raw properties) is attached to **subindex 0 only** — that row *is* the object — rather than repeated onto every subindex. A RECORD member still carries its own description on its own row; an ARRAY element carries none, because the ESI describes an array once rather than per element. To read an object's text for any subindex, look at subindex 0 of the same index. Where a slot offers mutually exclusive module variants the merge necessarily collides; it is resolved last-wins and reported in that device's `warnings`. Pass `modules` to model one concrete configuration instead.
1281
+ *
1282
+ * @name ParseEsi
1283
+ * @summary Parse an EtherCAT Slave Information (ESI) file
1284
+ * @request POST:/api/esi/parse
1285
+ */
1286
+ parseEsi: (data: string, query?: {
1287
+ /** Comma-separated `ModuleIdent` values (hexadecimal or decimal) restricting the merge, applied to every device by intersection with the idents that device's slots actually reference. Omit to merge every module each device references. */
1288
+ modules?: string;
1289
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<EsiParseResult, void>>;
1290
+ /**
1291
+ * @description Reads live link-quality and watchdog diagnostics from each slave's EtherCAT Slave Controller (DL Status 0x0110, error-counter block 0x0300–0x0313, watchdog block 0x0440–0x0443) via FPRD. Counters are 8-bit, saturate at 255, and are cleared only by a power cycle or explicit write — poll this endpoint and watch for a rising delta rather than an absolute value. The per-port counters localise a degrading link to a specific cable/connector; the watchdog counters distinguish a slave that stopped receiving process data from a master-side problem. Omit `positions` to query all discovered devices. Returns 500 for transports without an ESC (e.g. SPoE).
1292
+ *
1293
+ * @name GetDeviceDiagnostics
1294
+ * @summary Read live ESC health diagnostics for devices
1295
+ * @request GET:/api/devices/diagnostics
1296
+ */
1297
+ getDeviceDiagnostics: (query?: {
1298
+ /**
1299
+ * Comma-separated list of 1-based slave positions to query (e.g. `1,2,3`). Omit to query all discovered devices.
1300
+ * @example "1,2"
1301
+ */
1302
+ positions?: string;
1303
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DeviceDiagnostics[], void | {
1304
+ error: string;
1305
+ } | {
1306
+ /**
1307
+ * Human-readable error message from the driver
1308
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1309
+ */
1310
+ error: string;
1311
+ }>>;
1312
+ /**
1313
+ * @description Reads each slave's distributed-clock unit live from its EtherCAT Slave Controller (system-time delay 0x0928 and system-time difference 0x092C) via FPRD. The reference clock is the first DC-capable slave; every other DC slave continuously corrects its local clock toward it, and `systemTimeDifference` is the live deviation in nanoseconds. The figure is meaningful only while the bus is exchanging process data in SAFE-OP/OP (the reference time is distributed in the cyclic frame) and converges toward zero as the slaves' drift loops settle — poll this endpoint and watch for a slave whose deviation stays large or grows rather than an absolute value. Non-DC slaves report `dcCapable` false with zeroed values. Omit `positions` to query all discovered devices. Returns 500 for transports without an ESC (e.g. SPoE).
1314
+ *
1315
+ * @name GetDcSync
1316
+ * @summary Read live distributed-clock synchronisation status for devices
1317
+ * @request GET:/api/dc-sync
1318
+ */
1319
+ getDcSync: (query?: {
1320
+ /**
1321
+ * Comma-separated list of 1-based slave positions to query (e.g. `1,2,3`). Omit to query all discovered devices.
1322
+ * @example "1,2"
1323
+ */
1324
+ positions?: string;
1325
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<DcSyncStatus[], void | {
1326
+ error: string;
1327
+ } | {
1328
+ /**
1329
+ * Human-readable error message from the driver
1330
+ * @example "SDOread slave 1 0x2345:01 failed (no response — mailbox timeout)"
1331
+ */
1332
+ error: string;
1333
+ }>>;
1334
+ /**
1335
+ * @description Runs the capture program `motion-master-capture`, which ships beside the server binary, on the adapter the bus is on, waits for it to exit, and answers the summary. The program records every EtherCAT frame that leaves or enters the adapter with a kernel timestamp and writes them as a pcap file under `captures/` in the user cache, so the file is listed, downloaded and deleted through the `/api/user-cache` routes and opens in Wireshark. The summary matches each frame the master sent to the frame that came back for it, by the index and the header of its first datagram, and reports per kind of frame how late the returns were. The cyclic process-data frame is one kind; mailbox and register datagrams, the control plane, are the other. The bands are the three waits the driver uses, 2 ms, 20 ms and 100 ms, and they are cumulative: a frame later than 100 ms counts in all three. A frame sent again with the same index and header while its first copy had no answer counts once, as `resent`, and its return is timed from the first copy. The time is the kernel's, taken at the boundary to the NIC driver on both sides: when the frame is handed to the driver, and when the driver hands its return back. So the number covers the NIC, the wire and the device, and not the host's own queues and scheduling between that boundary and Motion Master. A capture that shows late frames puts the delay on the wire or in the device. A clean capture beside the server's own warnings, "mailbox write(s) got no frame back", puts it inside the host. Read the two together. One capture at a time. The capture adds no frame to the bus and runs on a thread of its own, so the bus is not touched. The program needs `CAP_NET_RAW`, which the packages grant it at install.
1336
+ *
1337
+ * @name RunCapture
1338
+ * @summary Record the EtherCAT frames of the bus adapter for a number of seconds
1339
+ * @request POST:/api/captures
1340
+ */
1341
+ runCapture: (data?: {
1342
+ /**
1343
+ * How long to record. A capture is a measurement a person starts.
1344
+ * @min 1
1345
+ * @max 120
1346
+ * @default 30
1347
+ */
1348
+ seconds?: number;
1349
+ /**
1350
+ * The adapter to record, when no bus is up. Defaults to the adapter of the bus.
1351
+ * @example "enp0s13f0u1u2"
1352
+ */
1353
+ adapter?: string;
1354
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1355
+ /**
1356
+ * The pcap file, relative to the user-cache root
1357
+ * @example "captures/capture-20261022-143005-enp0s13f0u1u2.pcap"
1358
+ */
1359
+ path: string;
1360
+ /** @example "enp0s13f0u1u2" */
1361
+ adapter: string;
1362
+ /** @example 30 */
1363
+ seconds: number;
1364
+ /** How late the frames of a capture came back. See `POST /api/captures`. */
1365
+ summary: CaptureSummary;
1366
+ }, void | {
1367
+ error: string;
1368
+ }>>;
1369
+ /**
1370
+ * @description Reads `captures/{name}` from the user cache and answers the summary that `POST /api/captures` answers, over any Ethernet pcap: a file the server recorded, or one from `tcpdump` on another host that a user put into `captures/` with `PUT /api/user-cache/captures/{name}`. Microsecond and nanosecond timestamps and both byte orders are read.
1371
+ *
1372
+ * @name GetCaptureSummary
1373
+ * @summary Summarise a pcap file in the user cache
1374
+ * @request GET:/api/captures/{name}
1375
+ */
1376
+ getCaptureSummary: (name: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1377
+ /** @example "captures/capture-20261022-143005-enp0s13f0u1u2.pcap" */
1378
+ path: string;
1379
+ /** How late the frames of a capture came back. See `POST /api/captures`. */
1380
+ summary: CaptureSummary;
1381
+ }, void>>;
1382
+ /**
1383
+ * @description Reads the current EtherCAT Application Layer state for one or more devices. Omit the `positions` query parameter to query all discovered devices.
1384
+ *
1385
+ * @name GetDeviceStates
1386
+ * @summary Read current AL state for devices
1387
+ * @request GET:/api/devices/state
1388
+ */
1389
+ getDeviceStates: (query?: {
1390
+ /**
1391
+ * Comma-separated list of 1-based slave positions to query (e.g. `1,2,3`). Omit to query all discovered devices.
1392
+ * @example "1,2"
1393
+ */
1394
+ positions?: string;
1395
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1396
+ /**
1397
+ * 1-based position on the fieldbus
1398
+ * @example 1
1399
+ */
1400
+ slavePosition: number;
1401
+ /**
1402
+ * Raw AL Status register value (ETG.1000.6 §6.4.1). Bits 3:0 encode the state; bit 4 is the error indicator.
1403
+ * @example 17
1404
+ */
1405
+ alStatus: number;
1406
+ /**
1407
+ * Current AL state decoded from alStatus (ETG.1000.6 encoding): 1 = Init, 2 = PreOp, 3 = Boot, 4 = SafeOp, 8 = Op. 0 when the device does not answer (see `reachability`).
1408
+ * @example 1
1409
+ */
1410
+ alState: 0 | 1 | 2 | 3 | 4 | 8;
1411
+ /**
1412
+ * True when the AL Status error indicator bit (bit 4) is set
1413
+ * @example true
1414
+ */
1415
+ error: boolean;
1416
+ /**
1417
+ * AL Status Code register (ETG.1000.6 §6.4.1). Non-zero when error is true; identifies the error cause (e.g. 0x0014 = No valid firmware).
1418
+ * @example 20
1419
+ */
1420
+ alStatusCode: number;
1421
+ /**
1422
+ * Whether the device answers at the station address the master gave it. `addressLost`: nothing answers at that address, but a device answers at its wire position. A reset, such as a power cycle, clears the address. Run `POST /api/scan` to command it again. `notAnswering`: nothing answers at that address or at its wire position. Check the cabling and the power. If devices were removed from the chain, run a scan. The wire position is checked by position only, so after a change to the chain the device that answers there can be a different one. When the value is not `answering`, the state of the device is unknown, and `alStatus`, `alState` and `alStatusCode` are 0.
1423
+ * @example "answering"
1424
+ */
1425
+ reachability: "answering" | "addressLost" | "notAnswering";
1426
+ }[], void | {
1427
+ /**
1428
+ * Human-readable error message from the driver
1429
+ * @example "FPRD slave 1: wkc=0"
1430
+ */
1431
+ error: string;
1432
+ }>>;
1433
+ /**
1434
+ * @description Commands one or more devices to the requested EtherCAT Application Layer state and blocks until all targeted devices arrive or the timeout elapses. The settled state of every targeted device is then read back and returned in `devices`, each with a `reached` flag; `ok` is true only when every device reached the target. A device that did not reach it carries an `alStatusCode` explaining why. A device that does not answer at its address is not commanded, so the request does not wait out the timeout for it. Its `reachability` says why, and the other devices are still commanded. Omit `positions` or pass an empty array to target all discovered devices. State values are the standard AL state register encodings from ETG.1000.6: 1 (Init), 2 (PreOp), 3 (Boot), 4 (SafeOp), 8 (Op).
1435
+ *
1436
+ * @name TransitionToState
1437
+ * @summary Transition devices to an EtherCAT AL state
1438
+ * @request POST:/api/devices/state
1439
+ */
1440
+ transitionToState: (data: {
1441
+ /**
1442
+ * 1-based slave positions to target. Omit or pass an empty array to target all discovered devices.
1443
+ * @example [1,2]
1444
+ */
1445
+ positions?: number[];
1446
+ /**
1447
+ * Target EtherCAT AL state (ETG.1000.6 AL control register encoding): 1 = Init, 2 = PreOp, 3 = Boot, 4 = SafeOp, 8 = Op.
1448
+ * @example 8
1449
+ */
1450
+ state: 1 | 2 | 3 | 4 | 8;
1451
+ /**
1452
+ * Maximum time to wait for all devices, in milliseconds
1453
+ * @default 5000
1454
+ * @example 5000
1455
+ */
1456
+ timeout?: number;
1457
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1458
+ /**
1459
+ * True only when every targeted device reached the target state.
1460
+ * @example true
1461
+ */
1462
+ ok: boolean;
1463
+ /** Settled state of each targeted device, in the order targeted. */
1464
+ devices: {
1465
+ /**
1466
+ * 1-based position on the fieldbus
1467
+ * @example 1
1468
+ */
1469
+ slavePosition: number;
1470
+ /**
1471
+ * Raw AL Status register value (ETG.1000.6 §6.4.1). Bits 3:0 encode the state; bit 4 is the error indicator.
1472
+ * @example 2
1473
+ */
1474
+ alStatus: number;
1475
+ /**
1476
+ * Current AL state decoded from alStatus (ETG.1000.6 encoding): 1 = Init, 2 = PreOp, 3 = Boot, 4 = SafeOp, 8 = Op. 0 when the device does not answer (see `reachability`).
1477
+ * @example 2
1478
+ */
1479
+ alState: 0 | 1 | 2 | 3 | 4 | 8;
1480
+ /**
1481
+ * True when the AL Status error indicator bit (bit 4) is set
1482
+ * @example false
1483
+ */
1484
+ error: boolean;
1485
+ /**
1486
+ * AL Status Code register (ETG.1000.6 §6.4.1). Non-zero when error is true; identifies the error cause (e.g. 0x0014 = No valid firmware).
1487
+ * @example 0
1488
+ */
1489
+ alStatusCode: number;
1490
+ /**
1491
+ * Whether the device answers at the station address the master gave it. `addressLost`: nothing answers at that address, but a device answers at its wire position. A reset, such as a power cycle, clears the address. Run `POST /api/scan` to command it again. `notAnswering`: nothing answers at that address or at its wire position. Check the cabling and the power. If devices were removed from the chain, run a scan. The wire position is checked by position only, so after a change to the chain the device that answers there can be a different one. When the value is not `answering`, the state of the device is unknown, and `alStatus`, `alState` and `alStatusCode` are 0.
1492
+ * @example "answering"
1493
+ */
1494
+ reachability: "answering" | "addressLost" | "notAnswering";
1495
+ /**
1496
+ * True when this device reached the requested target state (error clear and alState equal to the requested state).
1497
+ * @example true
1498
+ */
1499
+ reached: boolean;
1500
+ }[];
1501
+ }, void | {
1502
+ /** Why the driver refuses state changes */
1503
+ error: string;
1504
+ } | {
1505
+ /**
1506
+ * Human-readable error message from the driver
1507
+ * @example "FPRD slave 1: wkc=0"
1508
+ */
1509
+ error: string;
1510
+ }>>;
1511
+ /**
1512
+ * No description
1513
+ *
1514
+ * @name GetDevices
1515
+ * @summary List all fieldbus devices
1516
+ * @request GET:/api/devices
1517
+ */
1518
+ getDevices: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1519
+ /**
1520
+ * 1-based position on the fieldbus
1521
+ * @example 1
1522
+ */
1523
+ slavePosition: number;
1524
+ /**
1525
+ * Human-readable device name from SII EEPROM. For SOMANET drives this is the generic group name "SOMANET"; use productName to distinguish products.
1526
+ * @example "SOMANET"
1527
+ */
1528
+ name: string;
1529
+ /**
1530
+ * Canonical product name, independent of the SII EEPROM. For a recognised SOMANET product this distinguishes the product (e.g. "SOMANET Circulo"); otherwise it falls back to name.
1531
+ * @example "SOMANET Node"
1532
+ */
1533
+ productName: string;
1534
+ /**
1535
+ * Vendor ID from EEPROM
1536
+ * @format int64
1537
+ * @example 131073
1538
+ */
1539
+ vendorId: number;
1540
+ /**
1541
+ * Product code from EEPROM
1542
+ * @format int64
1543
+ * @example 5570560
1544
+ */
1545
+ productCode: number;
1546
+ /**
1547
+ * Revision number from EEPROM
1548
+ * @format int64
1549
+ * @example 1
1550
+ */
1551
+ revisionNumber: number;
1552
+ /**
1553
+ * Serial number from EEPROM
1554
+ * @format int64
1555
+ * @example 12345
1556
+ */
1557
+ serialNumber: number;
1558
+ /**
1559
+ * Whether the device implements the CiA402 drive profile (both controlword 0x6040 and statusword 0x6041 present in its object dictionary). Gates the CiA402 motion-control endpoints under /api/devices/{slavePosition}/cia402.
1560
+ * @example true
1561
+ */
1562
+ isCia402: boolean;
1563
+ /**
1564
+ * Whether the device is a SOMANET device, which runs SOMANET firmware. The server decides this from the vendor ID: Synapticon (0x22D2) or Sensodrive (0x063A). Gates the SOMANET features, such as the SOMANET files and the SOMANET procedures.
1565
+ * @example true
1566
+ */
1567
+ isSomanet: boolean;
1568
+ /**
1569
+ * Whether an object-dictionary read for this device has failed since it was scanned. The automatic read on reaching a mailbox-active state is attempted once, so a device flagged here keeps an empty parameter list until `POST /api/devices/{slavePosition}/parameters/init` is called; that clears the flag on success.
1570
+ * @example false
1571
+ */
1572
+ parametersUnavailable: boolean;
1573
+ /**
1574
+ * The low byte of ESC register 0x0000, which names the slave controller family: 0x85 is a netX (Integro), 0xC0 the controller of a Circulo, 0x90 a TI PRU-ICSS (Jasper). Null when the register could not be read at the scan, and over SPoE.
1575
+ * @format int32
1576
+ * @example 192
1577
+ */
1578
+ escType?: number | null;
1579
+ /**
1580
+ * Whether Motion Master writes each mailbox request to this device once and never sends it again. True for a Synapticon or Sensodrive device whose ESC type is not 0x85, because its EtherCAT stack locks its receive mailbox when it gets one request twice. False for a netX, which discards a repeat, and for every other vendor, where a write with no frame back is sent again.
1581
+ * @example true
1582
+ */
1583
+ mailboxWriteOnce?: boolean;
1584
+ /**
1585
+ * Whether the device has an EtherCAT Slave Controller: SII, ESC registers, distributed clocks and the ESC diagnostics. False over SPoE, where those endpoints answer 409.
1586
+ * @example true
1587
+ */
1588
+ supportsEsc?: boolean;
1589
+ /**
1590
+ * Whether the transport can blink the device's LEDs, which is what the `device-locate` procedure does. True over SPoE.
1591
+ * @example false
1592
+ */
1593
+ supportsLocate?: boolean;
1594
+ }[], any>>;
1595
+ /**
1596
+ * @description Returns the whole-bus process image: the byte sizes of each direction, the expected and last working counters and overall health, the number of retained image generations (one per re-map since the last reset), and every mapped object resolved to its absolute bit offset. While an image is live `configured` is true and the layout describes it. When no image is published (no device is in SAFE-OP/OP) but at least one generation has been mapped, `configured` is false and the layout describes the most recent retained generation — the last-known mapping — so a bus that has dropped out of SAFE-OP/OP stays inspectable; `lastWkc` then holds the final exchange value and working-counter health does not apply. The object lists are empty only before any image has ever been mapped. Object `name` is populated only for devices whose object dictionary has been enumerated.
1597
+ *
1598
+ * @name GetProcessImage
1599
+ * @summary Inspect the published EtherCAT process image
1600
+ * @request GET:/api/process-image
1601
+ */
1602
+ getProcessImage: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1603
+ /**
1604
+ * Whether an image is currently published for exchange
1605
+ * @example true
1606
+ */
1607
+ configured: boolean;
1608
+ /**
1609
+ * Size of the output image (master→slave) in bytes
1610
+ * @example 12
1611
+ */
1612
+ outputBytes: number;
1613
+ /**
1614
+ * Size of the input image (slave→master) in bytes
1615
+ * @example 16
1616
+ */
1617
+ inputBytes: number;
1618
+ /**
1619
+ * Working counter expected from the devices currently exchanging. A device in SAFE-OP or OP counts 2 for mapped outputs and 1 for mapped inputs. A device below SAFE-OP, or with the AL error flag set, counts 0.
1620
+ * @example 3
1621
+ */
1622
+ expectedWkc: number;
1623
+ /**
1624
+ * Working counter from the most recent exchange (0 before any)
1625
+ * @example 3
1626
+ */
1627
+ lastWkc: number;
1628
+ /**
1629
+ * Whether the last working counter meets the expected value
1630
+ * @example true
1631
+ */
1632
+ healthy: boolean;
1633
+ /**
1634
+ * Cycles that answered with a working counter below the value expected at the time, counted since `POST /api/init` and cleared only by `POST /api/reset`. `healthy` is a sample of the most recent cycle and so cannot see a fault that has already cleared; this count can.
1635
+ *
1636
+ * It spans every re-map rather than resetting per image, because a re-map happens whenever a device is brought into or out of SAFE-OP/OP — which is exactly when someone is chasing a fault. `generations` says how many images the count spans. Cycles missed while a device was being deliberately commanded out of an exchange state are not counted: the expectation is lowered before the transition is commanded.
1637
+ * @format int64
1638
+ * @example 0
1639
+ */
1640
+ shortWkcCycles: number;
1641
+ /**
1642
+ * Input frames the driver dropped since the process data was configured, summed over all devices. Only a transport that buffers input frames can drop one: a SPoE drive returns its frames in batches, and the oldest are dropped when the real-time loop falls more than 30 cycles behind. Every other transport reports 0.
1643
+ * @format int64
1644
+ * @example 0
1645
+ */
1646
+ droppedInputFrames: number;
1647
+ /**
1648
+ * Epoch microseconds of the first such cycle, 0 if there has been none
1649
+ * @format int64
1650
+ * @example 0
1651
+ */
1652
+ firstShortWkcUs: number;
1653
+ /**
1654
+ * Epoch microseconds of the most recent such cycle, 0 if there has been none
1655
+ * @format int64
1656
+ * @example 0
1657
+ */
1658
+ lastShortWkcUs: number;
1659
+ /**
1660
+ * Number of process images retained since the last reset
1661
+ * @example 1
1662
+ */
1663
+ generations: number;
1664
+ /** Output-mapped objects (RxPDO), in image order */
1665
+ outputs: ProcessImageObject[];
1666
+ /** Input-mapped objects (TxPDO), in image order */
1667
+ inputs: ProcessImageObject[];
1668
+ }, any>>;
1669
+ /**
1670
+ * @description Returns a point-in-time snapshot of the RT cyclic loop: the configured period and target rate, the cumulative achieved rate since start, the executed- and skipped-cycle counters, per-cycle task-execution timing (last / worst / mean), and whether real-time scheduling was acquired. Skipped cycles accumulate whenever the loop cannot meet its period (common on non-RT hosts such as Windows userspace) — a steadily rising `skippedCycles`, or an `achievedHz` well below `targetHz`, means the configured period is too aggressive for the hardware. Poll this endpoint and diff `executedCycles`/`skippedCycles` against `timestampUs` to chart the instantaneous rate over time.
1671
+ *
1672
+ * @name GetGameLoop
1673
+ * @summary Inspect real-time game-loop health
1674
+ * @request GET:/api/game-loop
1675
+ */
1676
+ getGameLoop: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<GameLoopHealth, any>>;
1677
+ /**
1678
+ * @description Retimes the running RT loop to a new cycle period, in microseconds. The change takes effect within one cycle and is transient — it is not written back to the config file, so a restart reverts to the configured `gameLoop.periodUs`. Intended for tuning on hosts that cannot sustain the configured rate: if `skippedCycles` climbs steadily (common on Windows userspace), raise the period (e.g. from 1000 to 2000 µs) until the loop meets its grid. Only the master cadence is retimed — the process-data recorder ring is not resized, and no drive-side watchdog is touched, so raising the period toward a drive's PDO/SM watchdog window can fault that drive. Applying a period starts a fresh health epoch: the cumulative counters (`executedCycles`, `skippedCycles`, the `achievedHz` average, and `maxExecNs`/`avgExecNs`) reset so the snapshot reflects only the new period — letting you see straight away whether the change improved the loop's health. Returns the updated health snapshot.
1679
+ *
1680
+ * @name SetGameLoopPeriod
1681
+ * @summary Change the real-time cycle period
1682
+ * @request PUT:/api/game-loop
1683
+ */
1684
+ setGameLoopPeriod: (data: {
1685
+ /**
1686
+ * New cycle period in microseconds. Must be greater than 0.
1687
+ * @format int64
1688
+ * @min 1
1689
+ * @example 2000
1690
+ */
1691
+ periodUs: number;
1692
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<GameLoopHealth, void>>;
1693
+ /**
1694
+ * @description Streams the same `.mmpd` serialisation as the POST variant (the recorder's current span, with the process image embedded as a header) directly in the response body instead of writing a file — for the client SDK / browser, which parses the bytes offline. Request with `Accept: application/octet-stream`. Same span semantics as the POST; works in any state.
1695
+ *
1696
+ * @name StreamProcessDataDump
1697
+ * @summary Stream the recorder ring as a binary .mmpd
1698
+ * @request GET:/api/process-data/dump
1699
+ */
1700
+ streamProcessDataDump: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Blob, {
1701
+ /** Human-readable reason the dump could not be produced */
1702
+ error: string;
1703
+ }>>;
1704
+ /**
1705
+ * @description Serialises the process-data recorder's current span — every cycle from the oldest still in the ring up to the newest at the instant of the call — to a `.mmpd` file and returns its path. Each cycle's full raw input and output images, sequence, and epoch-nanosecond timestamp are written, with the process image (per-device identity and PDO object layout, including object names and data types where the object dictionary has been enumerated) embedded as a header, so the file decodes fully offline with no running Motion Master and no live bus. Works in any state: while devices are exchanging (SAFE-OP/OP) it captures tail→head at that moment and ignores cycles recorded afterwards; after the bus has left the exchange states it uses the most recent retained image layout. The file is written under the configured `recorder.dumpDir`, created if absent; by default that is a `dumps` subdirectory of the user-cache root, so the written file is also reachable through the `/api/user-cache` endpoints — list it, download it, or delete it there. Only the path is returned here. (Setting an explicit `recorder.dumpDir` outside the cache root opts out of that; the file is then only reachable from a shell on the server.)
1706
+ *
1707
+ * @name DumpProcessData
1708
+ * @summary Dump the recorder ring to a binary .mmpd file
1709
+ * @request POST:/api/process-data/dump
1710
+ */
1711
+ dumpProcessData: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1712
+ /**
1713
+ * Absolute path of the written .mmpd file
1714
+ * @example "/tmp/motion-master/dump-20260610T141530Z-300123.mmpd"
1715
+ */
1716
+ path: string;
1717
+ }, {
1718
+ /**
1719
+ * Human-readable reason the dump could not be produced
1720
+ * @example "the recorder is empty — no cycles have been recorded yet"
1721
+ */
1722
+ error: string;
1723
+ }>>;
1724
+ /**
1725
+ * @description Stages many output (RxPDO) objects at once — the "send all" action of the Process Data page. Each value is converted to the object's declared data type and, when the object is output-mapped and its device is exchanging (SAFE-OP/OP), written into the output image so it is sent on the next real-time cycle and re-sent every cycle thereafter (set-once, sent-continuously). The batch is best-effort atomic: values are staged sequentially, so a batch can straddle two consecutive ~1 ms cycles. The request never fails as a whole — each object gets its own result, so the client can flag any object that was not cyclically staged (unknown device, a value the data type cannot hold, object not output-mapped, or bus not exchanging; in the last two cases the value is still written via SDO/cache, just not cyclically driven). A value the data type cannot hold is refused in its own result and nothing is written for it, by the same rule as `writeParameter`.
1726
+ *
1727
+ * @name StageProcessDataOutputs
1728
+ * @summary Stage a batch of output values into the process image
1729
+ * @request POST:/api/process-data/outputs
1730
+ */
1731
+ stageProcessDataOutputs: (data: any[][], params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1732
+ results: OutputStageResult[];
1733
+ }, {
1734
+ error: string;
1735
+ }>>;
1736
+ /**
1737
+ * @description Returns the static ESC configuration the master programmed into every slave during the last scan: station/alias addresses, mapped process-data sizes, the mailbox transport windows, the distributed-clock setup, and the configured Sync Managers and FMMUs. Read from cached state with no bus I/O and valid once the bus has been scanned. The list is empty before any scan, or when the active transport has no ESC (e.g. SPoE). Numeric fields (SM/FMMU type, mailbox protocol bits, SM flags) are raw register values; the client decodes them. `deviceName` is empty when no known device occupies the slave.
1738
+ *
1739
+ * @name GetBusConfig
1740
+ * @summary Inspect each slave's static EtherCAT Slave Controller configuration
1741
+ * @request GET:/api/bus-config
1742
+ */
1743
+ getBusConfig: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<SlaveConfig[], any>>;
1744
+ /**
1745
+ * @description Returns the bus as an ENI document, the vendor-neutral configuration a third-party master (acontis EC-Master, TwinCAT, CODESYS) replays to bring the same bus up. Where an ESI file describes one device family, an ENI describes one assembled network, and it is imperative rather than declarative: every configuration step is an EtherCAT datagram or a CoE download tagged with the AL-state transition it belongs to. The document carries each device's identity and addresses, its Sync Manager and FMMU register writes, its mailbox windows, its PDO assignment as CoE downloads, the AL-state walk with a read that holds the master until the device arrives, the cyclic frame, and the named process image. Conforms to ENI Schema 1.7 (ETG.2100). The bus must be configured. FMMUs and logical addresses come into being at the SAFE-OP transition, so a bus in PRE-OP has no mapping to describe and the call returns 409. **This drives the bus.** Each device's SII is read for its port layout and bootstrap mailbox, and its PDO assignment is read over CoE, so the call costs one EEPROM read and a short burst of SDO uploads per device. It is an export action, not an accessor. Distributed clocks are left out, so the generated configuration runs in free-run — which is how Motion Master runs the bus itself. The `DC` element needs an `AssignActivate` word, and a SOMANET drive does not carry the SII category that holds one. `X-Eni-Warnings` counts the parts that were asked for and not answered; each is also logged. A warning costs one optional element, never the document: a device whose SII will not read keeps every init command.
1746
+ *
1747
+ * @name ExportEni
1748
+ * @summary Export the bus as an EtherCAT Network Information (ENI) file
1749
+ * @request GET:/api/eni
1750
+ */
1751
+ exportEni: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<File, {
1752
+ /** Human-readable reason the export could not be produced */
1753
+ error: string;
1754
+ } | {
1755
+ /** The field that could not be written */
1756
+ error: string;
1757
+ } | {
1758
+ error: string;
1759
+ }>>;
1760
+ /**
1761
+ * @description Returns every registered monitoring as a resource — its configuration plus, per parameter, how its value is sourced, and the current buffer fill.
1762
+ *
1763
+ * @name ListMonitorings
1764
+ * @summary List all monitorings
1765
+ * @request GET:/api/monitorings
1766
+ */
1767
+ listMonitorings: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Monitoring[], any>>;
1768
+ /**
1769
+ * @description Registers a monitoring and starts sampling it off the real-time thread. Each parameter is classified once against the published process image: PDO-mapped objects are decoded from the live image; the rest are polled over SDO in the background. Create monitorings after the bus is operational so PDO objects are recognised as PDO. Monitoring is live-only — a parameter samples `null` while its owning device is not exchanging (SAFE-OP/OP).
1770
+ *
1771
+ * @name CreateMonitoring
1772
+ * @summary Create a monitoring
1773
+ * @request POST:/api/monitorings
1774
+ */
1775
+ createMonitoring: (data: {
1776
+ /**
1777
+ * URL-safe unique id; also the WebSocket topic.
1778
+ * @pattern ^[A-Za-z0-9._-]{1,64}$
1779
+ * @example "left-leg"
1780
+ */
1781
+ topic: string;
1782
+ /**
1783
+ * Optional human-readable label.
1784
+ * @example "Left Leg"
1785
+ */
1786
+ name?: string;
1787
+ /**
1788
+ * Flush cadence in milliseconds (5–2000). Not a sample rate: every recorded cycle since the last flush is delivered, so a longer interval yields a larger batch rather than fewer samples. 16 ms (~one batch per 60 Hz display frame) is a good default for live plotting.
1789
+ * @min 5
1790
+ * @max 2000
1791
+ * @example 16
1792
+ */
1793
+ interval: number;
1794
+ /**
1795
+ * Objects to sample, each as `[devicePosition, index, subindex]`.
1796
+ * @minItems 1
1797
+ * @example [[1,8240,1],[1,24676,0]]
1798
+ */
1799
+ parameters: number[][];
1800
+ }, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Monitoring, {
1801
+ error: string;
1802
+ }>>;
1803
+ /**
1804
+ * No description
1805
+ *
1806
+ * @name GetMonitoring
1807
+ * @summary Get a monitoring
1808
+ * @request GET:/api/monitorings/{topic}
1809
+ */
1810
+ getMonitoring: (topic: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Monitoring, void>>;
1811
+ /**
1812
+ * @description Stops sampling and releases the monitoring's SDO parameters from the shared refresher — an object no remaining monitoring needs stops being polled.
1813
+ *
1814
+ * @name DeleteMonitoring
1815
+ * @summary Delete a monitoring
1816
+ * @request DELETE:/api/monitorings/{topic}
1817
+ */
1818
+ deleteMonitoring: (topic: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<void, void>>;
1819
+ /**
1820
+ * @description Returns one entry per cached parameter-definition file on disk, keyed by device identity (vendor, product, revision). The cache stores only the object-dictionary *definitions* (not live values), so a scan of previously-seen hardware can skip the slow SDO enumeration. Independent of the bus — works whether or not a driver is initialised.
1821
+ *
1822
+ * @name ListParameterCacheEntries
1823
+ * @summary List on-disk parameter caches
1824
+ * @request GET:/api/parameter-cache
1825
+ */
1826
+ listParameterCacheEntries: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<ParameterCacheEntry[], any>>;
1827
+ /**
1828
+ * @description Returns the raw JSON cache file for the given id, verbatim, so it can be saved or inspected offline.
1829
+ *
1830
+ * @name GetParameterCache
1831
+ * @summary Download a parameter-cache file
1832
+ * @request GET:/api/parameter-cache/{id}
1833
+ */
1834
+ getParameterCache: (id: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<object, void>>;
1835
+ /**
1836
+ * @description Removes one cached file from disk. The next scan of that hardware re-enumerates it. Useful when a vendor reused a revision across an object-dictionary change.
1837
+ *
1838
+ * @name DeleteParameterCache
1839
+ * @summary Delete a parameter-cache file
1840
+ * @request DELETE:/api/parameter-cache/{id}
1841
+ */
1842
+ deleteParameterCache: (id: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<void, void>>;
1843
+ /**
1844
+ * @description Returns every file in Motion Master's per-user cache directory, flattened: one entry per file with its full path relative to the cache root, whatever the nesting. Directories have no entries of their own. Independent of the bus — works whether or not a driver is initialised. The cache is a plain file store for data that should outlive a restart. The store itself neither validates nor interprets an upload — `PUT` accepts any bytes at any valid path, and putting a file here does not, on its own, make Motion Master do anything with it; the client chooses the paths. That is separate from whether a *feature* reads a given file, and several do: `parameters/` (the on-disk object-dictionary cache) and `dumps/` (`.mmpd` recorder dumps) are written and consumed by those features, with more to follow. Their files appear in this listing alongside everything else, so a client must not assume every entry was uploaded through this API, nor that deleting one is inconsequential.
1845
+ *
1846
+ * @name ListUserCacheFiles
1847
+ * @summary List the files in the user cache
1848
+ * @request GET:/api/user-cache
1849
+ */
1850
+ listUserCacheFiles: (params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<UserCacheListing, void>>;
1851
+ /**
1852
+ * @description Returns the file verbatim, always as `application/octet-stream` and always with `Content-Disposition: attachment`, `X-Content-Type-Options: nosniff` and a `default-src 'none'; sandbox` CSP. The bytes are whatever a user uploaded, served from the API's own origin, so a browser must never *render* them — a rendered upload would be stored XSS against the origin that controls the drives, which CORS cannot help with. No extension is trusted to name a content type, and the attachment carries no `filename` (the path is user-controlled and must not reach a response header). Clients read the bytes and name the saved file themselves.
1853
+ *
1854
+ * @name GetUserCacheFile
1855
+ * @summary Download a user-cache file
1856
+ * @request GET:/api/user-cache/{path}
1857
+ */
1858
+ getUserCacheFile: (path: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<Blob, void>>;
1859
+ /**
1860
+ * @description Writes the request body to the given path, creating parent directories as needed and replacing any existing file. The write is atomic — a concurrent reader sees either the old contents or the new one, never a partial file. The body is taken as raw bytes whatever its content type.
1861
+ *
1862
+ * @name PutUserCacheFile
1863
+ * @summary Upload a user-cache file
1864
+ * @request PUT:/api/user-cache/{path}
1865
+ */
1866
+ putUserCacheFile: (path: string, data: File, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
1867
+ /**
1868
+ * The path written, relative to the cache root.
1869
+ * @example "configs/machine-a.json"
1870
+ */
1871
+ path: string;
1872
+ /**
1873
+ * Bytes written.
1874
+ * @example 20480
1875
+ */
1876
+ size: number;
1877
+ }, void>>;
1878
+ /**
1879
+ * @description Removes a file, or a directory and everything under it. Directories left empty between the removed path and the cache root are pruned, so no husks remain. A file the running server holds open is refused — see `deletable` on `UserCacheFile`.
1880
+ *
1881
+ * @name DeleteUserCacheFile
1882
+ * @summary Delete a user-cache file or directory
1883
+ * @request DELETE:/api/user-cache/{path}
1884
+ */
1885
+ deleteUserCacheFile: (path: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<void, void>>;
1886
+ }