motion-master-client 0.0.21 → 0.0.22

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 (126) hide show
  1. package/.babelrc +3 -0
  2. package/.eslintrc.json +18 -0
  3. package/jest.config.ts +16 -0
  4. package/motion-master.proto +1822 -0
  5. package/package.json +2 -17
  6. package/project.json +45 -0
  7. package/src/lib/cia402.spec.ts +77 -0
  8. package/src/lib/cia402.ts +414 -0
  9. package/src/lib/config-file.spec.ts +114 -0
  10. package/src/lib/config-file.ts +63 -0
  11. package/src/lib/device-log-line.ts +5 -0
  12. package/src/lib/device-parameter.spec.ts +85 -0
  13. package/src/lib/device-parameter.ts +79 -0
  14. package/src/lib/device.ts +10 -0
  15. package/src/lib/hardware-description.spec.ts +253 -0
  16. package/src/lib/hardware-description.ts +129 -0
  17. package/src/lib/logger.ts +5 -0
  18. package/src/lib/monitoring-config.ts +6 -0
  19. package/src/lib/{monitoring-entry.d.ts → monitoring-entry.ts} +5 -4
  20. package/src/lib/motion-master-client.ts +221 -0
  21. package/src/lib/motion-master-pub-sub-client.ts +95 -0
  22. package/src/lib/motion-master-pub-sub-socket.ts +40 -0
  23. package/src/lib/motion-master-pub-sub-web-socket.ts +78 -0
  24. package/src/lib/motion-master-pub-sub-worker-socket.ts +51 -0
  25. package/src/lib/motion-master-req-res-client.spec.ts +740 -0
  26. package/src/lib/motion-master-req-res-client.ts +2120 -0
  27. package/src/lib/motion-master-req-res-socket.ts +62 -0
  28. package/src/lib/motion-master-req-res-web-socket.ts +124 -0
  29. package/src/lib/motion-master-req-res-worker-socket.ts +87 -0
  30. package/src/lib/motion-master.proto.js +2 -2
  31. package/src/lib/operators.ts +90 -0
  32. package/src/lib/options.ts +12 -0
  33. package/src/lib/parameter.spec.ts +160 -0
  34. package/src/lib/parameter.ts +170 -0
  35. package/src/lib/product-id-range.ts +8 -0
  36. package/src/lib/request-status-resolver.ts +403 -0
  37. package/src/lib/system-log-line.ts +9 -0
  38. package/src/lib/{types.d.ts → types.ts} +74 -143
  39. package/src/lib/urls.ts +6 -0
  40. package/src/lib/util.ts +305 -0
  41. package/tsconfig.json +23 -0
  42. package/tsconfig.lib.json +10 -0
  43. package/tsconfig.spec.json +20 -0
  44. package/typedoc.json +10 -0
  45. package/src/index.js +0 -29
  46. package/src/index.js.map +0 -1
  47. package/src/lib/cia402.d.ts +0 -182
  48. package/src/lib/cia402.js +0 -392
  49. package/src/lib/cia402.js.map +0 -1
  50. package/src/lib/config-file.d.ts +0 -13
  51. package/src/lib/config-file.js +0 -50
  52. package/src/lib/config-file.js.map +0 -1
  53. package/src/lib/device-log-line.d.ts +0 -5
  54. package/src/lib/device-log-line.js +0 -3
  55. package/src/lib/device-log-line.js.map +0 -1
  56. package/src/lib/device-parameter.d.ts +0 -56
  57. package/src/lib/device-parameter.js +0 -39
  58. package/src/lib/device-parameter.js.map +0 -1
  59. package/src/lib/device.d.ts +0 -9
  60. package/src/lib/device.js +0 -3
  61. package/src/lib/device.js.map +0 -1
  62. package/src/lib/hardware-description.d.ts +0 -41
  63. package/src/lib/hardware-description.js +0 -94
  64. package/src/lib/hardware-description.js.map +0 -1
  65. package/src/lib/logger.d.ts +0 -1
  66. package/src/lib/logger.js +0 -8
  67. package/src/lib/logger.js.map +0 -1
  68. package/src/lib/monitoring-config.d.ts +0 -6
  69. package/src/lib/monitoring-config.js +0 -3
  70. package/src/lib/monitoring-config.js.map +0 -1
  71. package/src/lib/monitoring-entry.js +0 -3
  72. package/src/lib/monitoring-entry.js.map +0 -1
  73. package/src/lib/motion-master-client.d.ts +0 -52
  74. package/src/lib/motion-master-client.js +0 -151
  75. package/src/lib/motion-master-client.js.map +0 -1
  76. package/src/lib/motion-master-pub-sub-client.d.ts +0 -16
  77. package/src/lib/motion-master-pub-sub-client.js +0 -68
  78. package/src/lib/motion-master-pub-sub-client.js.map +0 -1
  79. package/src/lib/motion-master-pub-sub-socket.d.ts +0 -34
  80. package/src/lib/motion-master-pub-sub-socket.js +0 -3
  81. package/src/lib/motion-master-pub-sub-socket.js.map +0 -1
  82. package/src/lib/motion-master-pub-sub-web-socket.d.ts +0 -14
  83. package/src/lib/motion-master-pub-sub-web-socket.js +0 -67
  84. package/src/lib/motion-master-pub-sub-web-socket.js.map +0 -1
  85. package/src/lib/motion-master-pub-sub-worker-socket.d.ts +0 -14
  86. package/src/lib/motion-master-pub-sub-worker-socket.js +0 -42
  87. package/src/lib/motion-master-pub-sub-worker-socket.js.map +0 -1
  88. package/src/lib/motion-master-req-res-client.d.ts +0 -920
  89. package/src/lib/motion-master-req-res-client.js +0 -1680
  90. package/src/lib/motion-master-req-res-client.js.map +0 -1
  91. package/src/lib/motion-master-req-res-socket.d.ts +0 -52
  92. package/src/lib/motion-master-req-res-socket.js +0 -3
  93. package/src/lib/motion-master-req-res-socket.js.map +0 -1
  94. package/src/lib/motion-master-req-res-web-socket.d.ts +0 -24
  95. package/src/lib/motion-master-req-res-web-socket.js +0 -99
  96. package/src/lib/motion-master-req-res-web-socket.js.map +0 -1
  97. package/src/lib/motion-master-req-res-worker-socket.d.ts +0 -20
  98. package/src/lib/motion-master-req-res-worker-socket.js +0 -69
  99. package/src/lib/motion-master-req-res-worker-socket.js.map +0 -1
  100. package/src/lib/operators.d.ts +0 -18
  101. package/src/lib/operators.js +0 -76
  102. package/src/lib/operators.js.map +0 -1
  103. package/src/lib/options.d.ts +0 -10
  104. package/src/lib/options.js +0 -14
  105. package/src/lib/options.js.map +0 -1
  106. package/src/lib/parameter.d.ts +0 -72
  107. package/src/lib/parameter.js +0 -119
  108. package/src/lib/parameter.js.map +0 -1
  109. package/src/lib/product-id-range.d.ts +0 -7
  110. package/src/lib/product-id-range.js +0 -12
  111. package/src/lib/product-id-range.js.map +0 -1
  112. package/src/lib/request-status-resolver.d.ts +0 -4
  113. package/src/lib/request-status-resolver.js +0 -345
  114. package/src/lib/request-status-resolver.js.map +0 -1
  115. package/src/lib/system-log-line.d.ts +0 -9
  116. package/src/lib/system-log-line.js +0 -3
  117. package/src/lib/system-log-line.js.map +0 -1
  118. package/src/lib/types.js +0 -28
  119. package/src/lib/types.js.map +0 -1
  120. package/src/lib/urls.d.ts +0 -3
  121. package/src/lib/urls.js +0 -10
  122. package/src/lib/urls.js.map +0 -1
  123. package/src/lib/util.d.ts +0 -40
  124. package/src/lib/util.js +0 -316
  125. package/src/lib/util.js.map +0 -1
  126. /package/src/{index.d.ts → index.ts} +0 -0
@@ -1,1680 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MotionMasterReqResClient = void 0;
4
- const tslib_1 = require("tslib");
5
- const rxjs_1 = require("rxjs");
6
- const operators_1 = require("rxjs/operators");
7
- const uuid_1 = require("uuid");
8
- const device_parameter_1 = require("./device-parameter");
9
- const hardware_description_1 = require("./hardware-description");
10
- const operators_2 = require("./operators");
11
- const parameter_1 = require("./parameter");
12
- const types_1 = require("./types");
13
- const util_1 = require("./util");
14
- const cia402_1 = require("./cia402");
15
- const cia402_2 = require("./cia402");
16
- const cia402_3 = require("./cia402");
17
- /**
18
- * This class contains methods for making requests to Motion Master using the injected request/response socket.
19
- *
20
- * Each request message defined in the proto file has a corresponding request method in this class.
21
- * For some requests like firmware installation, Motion Master will send progress messages until the firmware installation is done.
22
- *
23
- * Call to a request method will return an Observable of: (1) corresponding status message, for example call to `getDeviceInfo`
24
- * will return an instance of `MotionMasterMessage.Status.DeviceInfo`, (2) request status - one of "succeeded", "failed", or "running", and
25
- * (3) request message id.
26
- *
27
- * If the request fails on Motion Master the function will throw an error. It can also throw an error if the request times out.
28
- *
29
- * Request methods have optional `messageId` input parameter.
30
- * If `messageId` is not provided, one will be generated before sending the request message to Motion Master.
31
- * Status messages (responses) received from Motion Master that correspond to the previous request will have the same `messageId` as the one in the request.
32
- * This is how we match request with response messages in the full-duplex asynchronous communication (WebSockets, ZeroMQ).
33
- * Matching request/response by message id is inspired by [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification).
34
- *
35
- * Almost all request methods have mandatory `requestTimeout` input parameter.
36
- * This parameter specifies how long (in milliseconds) will the client wait for the status (response) messages corresponding to the previous request.
37
- * If status message is not received in due time the request method will throw a timeout error.
38
- * The error doesn't mean the request has failed on Motion Master, but rather that client has given up waiting for the response(s).
39
- * It's possible to stop some on-going procedures on Motion Master with the corresponding stop messages, for example `StopFullAutoTuning`.
40
- *
41
- * @example
42
- * How to handle request method timeout error:
43
- * ```ts
44
- * req.getDeviceInfo(10).subscribe({
45
- * next: (status) => console.log(status),
46
- * error: (err: unknown) => {
47
- * if (err instanceof TimeoutError) {
48
- * alert('Request has timed out');
49
- * }
50
- * }
51
- * });
52
- * ```
53
- *
54
- * Request methods for a particular device, like `getDeviceParameterInfo`, as the first input parameter accept the type of request message as defined in the proto file.
55
- * For `getDeviceParameterInfo` that's `MotionMasterMessage.Request.IGetDeviceParameterInfo`. This type is extended (via type intersection) by `DeviceRefObj`.
56
- * This is done in order to support multiple ways to reference a device. Motion Master only supports device address which it re-generates for each device on power-cycle.
57
- * Because device address can change, for scripts and applications it's preferred to use a device reference that won't change.
58
- * Device serial number in the hardware description file uniquely identifies device and doesn't change. This is what each request message is extended with.
59
- * Before sending the request message to Motion Master, device address gets resolved and is set on the request message.
60
- * Beside device address and device serial number, devices can be referenced by position (sequence number in the network).
61
- *
62
- * It is ensured that Observable returned from a call to request method will eventually complete, so a call to unsubscribe is not required.
63
- * Observable will complete when request status is either "succeeded" or "failed", or it will complete (error) due to timeout.
64
- * Finding out if a request has completed, failed or is it still on-going is different for each request - it depends on the status messages, see {@link requestStatusResolver}.
65
- * Request methods handle this and for each request they will emit status messages with one of "succeeded", "failed", or "running" request status.
66
- *
67
- * Beside the request methods this class contains many helper methods such as the ones for getting and setting device parameter values and
68
- * saving all parameters which involves complex logic like multiple repeating requests in order to determine if saving all parameters has completed successfully.
69
- */
70
- class MotionMasterReqResClient {
71
- constructor(socket) {
72
- this.socket = socket;
73
- /**
74
- * Map device address to a map of parameter id to type value key.
75
- *
76
- * @example
77
- * ```ts
78
- * new Map([
79
- * [2045285448, new Map([
80
- * ["0x1018:02", "uintValue"]
81
- * ])]
82
- * ]);
83
- * ```
84
- *
85
- * When setting a parameter value only one of int, uint, float, string, or raw type value fields must be set.
86
- * This is defined in the proto file SetDeviceParameterValues request message.
87
- *
88
- * Device parameters have richer set of base types defined in ESI and they're provided by DeviceParameterInfo status message.
89
- * When device parameter info is fetched this map gets updated by mapping device parameters type to "oneof" proto type, e.g. `INTEGER32 -> intValue`.
90
- *
91
- * This map helps in simplifying the API by allowing users to set parameter values without specifying the type value field.
92
- * One can simply call `setParameterValue(2045285448, 0x2004, 0x03, 2500)` and the correct type value field on the proto message will be set, `uintValue` in this example.
93
- */
94
- this.typeValueKeyMap = new Map();
95
- /**
96
- * Map device serial number to device address.
97
- *
98
- * @example
99
- * ```ts
100
- * new Map([
101
- * ["8502-03-0001353-2115", 2045285448]
102
- * ]);
103
- * ```
104
- *
105
- * When making requests related to a device, device address is used as an identifier.
106
- * Device address is not permanent. The number is re-generated by Motion Master when devices are power-cycled.
107
- * For scripts and applications that use this library, having a permanent device identifier is a better option.
108
- * Device serial number read from the hardware description file (.hardware_description) stored on a device is a permanent identifier.
109
- *
110
- * This map helps in making all request methods related to a device accept device reference instead of just device address as an identifier.
111
- * Device reference {@link DeviceRefObj} can be one of: device address, device serial number, or device position.
112
- * Prior to sending a request message to Motion Master, device address is resolved from device reference and this map is used for that.
113
- */
114
- this.deviceMap = new Map();
115
- }
116
- //
117
- // Requests
118
- //
119
- /**
120
- * Ping system.
121
- *
122
- * The client must send messages to Motion Master in regular intervals in order for Motion Master to consider it alive.
123
- * When the client is considered "not alive", Motion Master will stop the ongoing procedures and monitorings started by that client.
124
- * Each client on the Motion Master side has its own default timeout which can be changed by {@link setSystemClientTimeout}.
125
- */
126
- pingSystem(messageId) {
127
- const pingSystem = types_1.MotionMasterMessage.Request.PingSystem.create();
128
- this.sendRequest({ pingSystem }, messageId);
129
- return rxjs_1.EMPTY;
130
- }
131
- /**
132
- * Get system version.
133
- *
134
- * Get the version of Motion Master. The version follows [Semantic Versioning 2.0.0](https://semver.org/).
135
- */
136
- getSystemVersion(requestTimeout, messageId) {
137
- const getSystemVersion = types_1.MotionMasterMessage.Request.GetSystemVersion.create();
138
- const id = this.sendRequest({ getSystemVersion }, messageId);
139
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('systemVersion', requestTimeout, id));
140
- }
141
- /**
142
- * Get device info.
143
- *
144
- * Device info includes a list of devices on the network. Each device has a type, position in the network, and device address.
145
- * At the time of writing, the device alias is not yet supported.
146
- *
147
- * Motion Master will assign a unique device address to each device in the list.
148
- * Device address is what the client libraries use to make requests like `getDeviceParameter` for a particular device.
149
- * Device address is only valid for the duration of the session, that is, until Motion Master re-initializes the devices, for example
150
- * when devices are power cycled or Motion Master process is restarted.
151
- */
152
- getDeviceInfo(requestTimeout, messageId) {
153
- const getDeviceInfo = types_1.MotionMasterMessage.Request.GetDeviceInfo.create();
154
- const id = this.sendRequest({ getDeviceInfo }, messageId);
155
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceInfo', requestTimeout, id));
156
- }
157
- /**
158
- * Get device parameter info.
159
- *
160
- * Device parameter info includes a list of all parameters for the requested device, but without the parameter values.
161
- * Getting device parameter values can take more than 20ms per parameter using the IgH EtherCAT Master library.
162
- * Not all clients require all the parameter values at once, like OBLAC Drives, so this method is good for getting
163
- * the list of available parameters and then separately getting the values of some required parameters.
164
- *
165
- * The returned list of device parameters will include some basic data for each parameter: index, subindex,
166
- * name, unit, group (ARRAY or RECORD name for subitems), read and write access, min and max, and value type.
167
- * Min and max values are not yet fully supported - they contain the min/max values for the used base type.
168
- * The same info and more can be read from the "SOMANET_CiA_402.xml" file, but getting info from ESI file is more complicated.
169
- * It requires an XML parsing library and knowing how to read objects info from a dictionary and assigned modules.
170
- *
171
- * In addition to fetching device parameter info, this method will map parameter base data type (ETG.1020) to proto3 types.
172
- * The map removes the need to specify proto3 type field when setting a parameter value {@link typeValueKeyMap}.
173
- */
174
- getDeviceParameterInfo(props, requestTimeout, messageId) {
175
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
176
- const getDeviceParameterInfo = types_1.MotionMasterMessage.Request.GetDeviceParameterInfo.create(Object.assign(Object.assign({}, props), { deviceAddress }));
177
- const id = this.sendRequest({ getDeviceParameterInfo }, messageId);
178
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceParameterInfo', requestTimeout, id));
179
- }));
180
- }
181
- /**
182
- * Get device parameter values.
183
- *
184
- * As already mentioned above, the fetching of parameter values can take 20ms and more, but it can also fail completely or timeout on the master side, which registers as a "cannot refresh value" error.
185
- */
186
- getDeviceParameterValues(props, requestTimeout, messageId) {
187
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
188
- const getDeviceParameterValues = types_1.MotionMasterMessage.Request.GetDeviceParameterValues.create(Object.assign(Object.assign({}, props), { deviceAddress }));
189
- const id = this.sendRequest({ getDeviceParameterValues }, messageId);
190
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceParameterValues', requestTimeout, id));
191
- }));
192
- }
193
- /**
194
- * Get multi device parameter values.
195
- *
196
- * Allows requesting parameter values from multiple devices at the same time.
197
- */
198
- getMultiDeviceParameterValues(props, requestTimeout, messageId) {
199
- const getMultiDeviceParameterValues = types_1.MotionMasterMessage.Request.GetMultiDeviceParameterValues.create(props);
200
- const id = this.sendRequest({ getMultiDeviceParameterValues }, messageId);
201
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('multiDeviceParameterValues', requestTimeout, id));
202
- }
203
- /**
204
- * Set device parameter values.
205
- */
206
- setDeviceParameterValues(props, requestTimeout, messageId) {
207
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
208
- const setDeviceParameterValues = types_1.MotionMasterMessage.Request.SetDeviceParameterValues.create(Object.assign(Object.assign({}, props), { deviceAddress }));
209
- const id = this.sendRequest({ setDeviceParameterValues }, messageId);
210
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceParameterValues', requestTimeout, id));
211
- }));
212
- }
213
- /**
214
- * Set multi device parameter values.
215
- *
216
- * Allows setting parameter values from multiple devices at the same time.
217
- */
218
- setMultiDeviceParameterValues(props, requestTimeout, messageId) {
219
- const setMultiDeviceParameterValues = types_1.MotionMasterMessage.Request.SetMultiDeviceParameterValues.create(props);
220
- const id = this.sendRequest({ setMultiDeviceParameterValues }, messageId);
221
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('multiDeviceParameterValues', requestTimeout, id));
222
- }
223
- /**
224
- * Get device file list.
225
- *
226
- * Motion Master will use Filetransfer over EtherCAT (FoE) to get the list of files from a device.
227
- * There isn't an actual command for getting the list, but rather the content of a specially named file "fs-getlist" is the file list.
228
- * The list can be read like any other file from a device using the IgH EtherCAT Master for Linux CLI program:
229
- *
230
- * ```
231
- * $ ethercat foe_read fs-getlist
232
- * ```
233
- *
234
- * At the time of writing this document "fs-getlist" can return a maximum of 32 files (subject to change) in the list. This is a firmware limitation.
235
- * However, more than 32 files can be stored on device flash memory, but they won't appear in the list.
236
- * Also note that FoE can behave differently in the bootstrap firmware which runs in the BOOT EtherCAT state and
237
- * SOMANET firmware which runs in other EtherCAT states like PREOP/OP. Bootstrap tends to be buggier since it cannot be updated easily, so
238
- * Motion Master has certain workarounds to overcome these FoE differences and bugs.
239
- */
240
- getDeviceFileList(props, requestTimeout, messageId) {
241
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
242
- const getDeviceFileList = types_1.MotionMasterMessage.Request.GetDeviceFileList.create(Object.assign(Object.assign({}, props), { deviceAddress }));
243
- const id = this.sendRequest({ getDeviceFileList }, messageId);
244
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceFileList', requestTimeout, id));
245
- }));
246
- }
247
- /**
248
- * Get device file.
249
- *
250
- * Motion Master uses the Filetransfer over EtherCAT (FoE) to read and send back the content of a file from the device flash memory.
251
- *
252
- * The IgH EtherCAT Master library used by Motion Master limits the file read buffer to 9KB, so any file written to flash that is larger than 9KB
253
- * needs to be split into parts of max 9KB. Motion Master does this automatically on request to {@link setDeviceFile}.
254
- *
255
- * Upon receiving this request Motion Master will first read the list of files on a device, see {@link getDeviceFileList}.
256
- * It does that in order to determine if the requested file, for example "SOMANET_CiA_402.xml", has been stored in multiple parts.
257
- * The parts are named like "SOMANET_CiA_402.xml.zip.part000", "SOMANET_CiA_402.xml.zip.part001" and so on.
258
- * Motion Master will read all parts of the requested file, unzip it and send the content back to a client.
259
- * Since the number of items in the list of files is limited to 32 (based on the firmware version) Motion Master might not see the file,
260
- * but in any case it will try to read the content of it.
261
- * If the file exists it will return its content, otherwise it will return the file not found error.
262
- *
263
- * Zipped files will be automatically unzipped and their content returned, for example: stack_image.svg.zip can be stored
264
- * in one or multiple files depending on the size. No matter how its stored it will be unzipped and its content returned as
265
- * text (SVG) instead of zipped content (binary).
266
- *
267
- * In BOOT EtherCAT state it's only allowed to read the .hardware_description file. This was done because
268
- * the bootloader firmware would hang when trying to read a corrupted or missing file.
269
- *
270
- * If the requested file content is empty, Motion Master will return a not found error. This is subject to change now that Motion Master reads the file error codes.
271
- */
272
- getDeviceFile(props, requestTimeout, messageId) {
273
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
274
- const getDeviceFile = types_1.MotionMasterMessage.Request.GetDeviceFile.create(Object.assign(Object.assign({}, props), { deviceAddress }));
275
- const id = this.sendRequest({ getDeviceFile }, messageId);
276
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceFile', requestTimeout, id));
277
- }));
278
- }
279
- /**
280
- * Set device file.
281
- *
282
- * Motion Master uses the Filetransfer over EtherCAT (FoE) to write files to the device flash memory.
283
- *
284
- * The IgH EtherCAT Master library used by Motion Master limits the file read buffer to 9KB, so any file written to flash that is larger than 9KB
285
- * needs to be split into parts of max 9KB. Motion Master does this automatically by first zipping the content and then writing the parts.
286
- * The parts are named in the following manner: "SOMANET_CiA_402.xml.zip.part000", "SOMANET_CiA_402.xml.zip.part001" and so on.
287
- */
288
- setDeviceFile(props, requestTimeout, messageId) {
289
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
290
- const setDeviceFile = types_1.MotionMasterMessage.Request.SetDeviceFile.create(Object.assign(Object.assign({}, props), { deviceAddress }));
291
- const id = this.sendRequest({ setDeviceFile }, messageId);
292
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceFile', requestTimeout, id));
293
- }));
294
- }
295
- /**
296
- * Delete device file.
297
- *
298
- * Motion Master uses the Filetransfer over EtherCAT (FoE) to delete files from the device flash memory.
299
- *
300
- * If the file to delete is written in parts, Motion Master will ensure that all parts are deleted.
301
- * It does that by reading the list of files on a device, see {@link getDeviceFileList}, removing all parts from that list and then
302
- * it re-reading the list again to ensure that there are no leftovers if there were more than 32 files in the list. If there are still
303
- * more than 32 files in the list, Motion Master will blindly try to make sure there are no file parts left in the memory (may, or may not work).
304
- */
305
- deleteDeviceFile(props, requestTimeout, messageId) {
306
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
307
- const deleteDeviceFile = types_1.MotionMasterMessage.Request.DeleteDeviceFile.create(Object.assign(Object.assign({}, props), { deviceAddress }));
308
- const id = this.sendRequest({ deleteDeviceFile }, messageId);
309
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceFile', requestTimeout, id));
310
- }));
311
- }
312
- /**
313
- * Reset device fault.
314
- *
315
- * When an error occurs on a device, the device will go into Fault reaction active state (transition 13) and then automatically to Fault state (transition 14).
316
- * The CiA402 state of a device can be derived from the value of Statusword object (0x6041:00).
317
- * In order to go out of Fault and into Switch on disabled state (transition 15) master must send Fault reset command via Controlword object (0x6040:00).
318
- *
319
- * When this request is sent to Motion Master, it will try to reset the fault. Resetting the fault can succeed or fail.
320
- * While resetting the fault, Motion Master will use the current Controlword value and set the Reset fault bit to 1,
321
- * but when it completes (either success or error), it will set it back to 0.
322
- *
323
- * Motion Master will return "No Fault" warning when this request is sent and device is not in Fault or Fault reaction active state.
324
- * If this request is sent when device is in Fault reaction active state, then Motion Master will
325
- * wait for the automatic transition (14) to Fault state before trying to reset fault.
326
- * When Motion Master sets the Controlword Fault bit to 1, it will also occasionally check if the device is no longer in Fault state.
327
- * After a couple of seconds, if the device is still in Fault state, it will give up and return the timeout error.
328
- */
329
- resetDeviceFault(props, requestTimeout, messageId) {
330
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
331
- const resetDeviceFault = types_1.MotionMasterMessage.Request.ResetDeviceFault.create(Object.assign(Object.assign({}, props), { deviceAddress }));
332
- const id = this.sendRequest({ resetDeviceFault }, messageId);
333
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceFaultReset', requestTimeout, id));
334
- }));
335
- }
336
- /**
337
- * Stop device.
338
- *
339
- * Motion Master will use the current value of the Controlword object and set the command on it to Quick stop.
340
- * It will then wait for up to 2 seconds for a device to get into one of the following CiA402 states: Switch on disabled, Operation enabled, Fault.
341
- * It does that by periodically checking the value of the Statusword object. If the device doesn't go into one of those states,
342
- * Motion Master will return a timeout or a quick stop failed error.
343
- */
344
- stopDevice(props, requestTimeout, messageId) {
345
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
346
- const stopDevice = types_1.MotionMasterMessage.Request.StopDevice.create(Object.assign(Object.assign({}, props), { deviceAddress }));
347
- const id = this.sendRequest({ stopDevice }, messageId);
348
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceStop', requestTimeout, id));
349
- }));
350
- }
351
- /**
352
- * Start device firmware installation.
353
- *
354
- * When Motion Master receives this request for a device, it will do the following:
355
- * - switch the device to the BOOT EtherCAT state - the device will then run the bootloader instead of the firmware
356
- * - validate the firmware package
357
- * - delete files the files found in the package from the device flash memory (SOMANET_CiA_402.xml and stack_image.svg)
358
- * - write files other than the firmware binaries and SII from package to the device (SOMANET_CiA_402.xml and stack_image.svg)
359
- * - (optional) install the SII file using the IgH EtherCAT Master library write SII function
360
- * - write the firmware binaries to the device using predefined names like app_firmware.bin and com_firmware.bin
361
- *
362
- * During the firmware installation, Motion Master will send progress messages back to clients.
363
- * If Motion Master fails in any step other than SII write, it will send an error. If SII write fails, only a warning will be sent.
364
- */
365
- startDeviceFirmwareInstallation(props, requestTimeout, messageId) {
366
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
367
- const startDeviceFirmwareInstallation = types_1.MotionMasterMessage.Request.StartDeviceFirmwareInstallation.create(Object.assign(Object.assign({}, props), { deviceAddress }));
368
- const id = this.sendRequest({ startDeviceFirmwareInstallation }, messageId);
369
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceFirmwareInstallation', requestTimeout, id));
370
- }));
371
- }
372
- /**
373
- * Get device log.
374
- *
375
- * The device log is stored in two files due to IgH EtherCAT Master library 9KB file size limitation, see {@link getDeviceFile}.
376
- * A device automatically writes the log to logging_curr.log and copies that file to logging_prev.log once it reaches 9KB.
377
- * When Motion Master receives this request, it will read both of these files and return their combined contents.
378
- */
379
- getDeviceLog(props, requestTimeout, messageId) {
380
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
381
- const getDeviceLog = types_1.MotionMasterMessage.Request.GetDeviceLog.create(Object.assign(Object.assign({}, props), { deviceAddress }));
382
- const id = this.sendRequest({ getDeviceLog }, messageId);
383
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceLog', requestTimeout, id));
384
- }));
385
- }
386
- /**
387
- * Start cogging torque recording.
388
- *
389
- * Cogging torque compensation (CTC) recording can be started with or without auto-config.
390
- * In the proto file skipping the auto-config is currently named skip_auto_tuning. The field name is deprecated and will be renamed.
391
- *
392
- * If CTC recording is started without auto-config, the users must ensure that the encoder on the motor shaft is used for all functions: commutation, position, and velocity.
393
- * If this is not the case, then Motion Master will return an invalid encoder configuration error.
394
- * Recording can also fail if the position controller is not tuned.
395
- *
396
- * If CTC recording is started with auto-config then Motion Master will:
397
- * - change the encoder configuration to have all encoder functions on the motor shaft
398
- * - disable CTC
399
- * - change the velocity feed forward value
400
- * - change the position and velocity filter types and cutoff frequencies
401
- * - run iterative sharpening position controller auto-tuning in order to compute the optimal PID values (gains) for CTC recording
402
- *
403
- * All parameter values that Motion Master changes as part of the auto-config are first stored in memory and once the CTC recording is done are reverted back.
404
- *
405
- * CTC recording is started by changing the Modes of operation (0x6060) parameter value to -1 (Cogging compensation recording mode).
406
- * During the operation Motion Master will monitor the Cogging torque compensation state parameter (0x2008:01) to know when the recording is in progress and when it's done.
407
- *
408
- * The result of CTC recording is the cogging_torque.bin file written to device flash memory. The size of this file is 2048 bytes.
409
- * Each pair of bytes represents a 16-bit signed integer value in mNm (millinewton meter).
410
- *
411
- * This request will turn the motor.
412
- */
413
- startCoggingTorqueRecording(props, requestTimeout, messageId) {
414
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
415
- const startCoggingTorqueRecording = types_1.MotionMasterMessage.Request.StartCoggingTorqueRecording.create(Object.assign(Object.assign({}, props), { deviceAddress }));
416
- const id = this.sendRequest({ startCoggingTorqueRecording }, messageId);
417
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('coggingTorqueRecording', requestTimeout, id));
418
- }));
419
- }
420
- /**
421
- * Get cogging torque data.
422
- *
423
- * The cogging_torque.bin file is the result of cogging torque compensation recording, see {@link startCoggingTorqueRecording}.
424
- * The size of this file is 2048 bytes where each pair of bytes represents a 16-bit signed integer value in mNm (millinewton meter).
425
- *
426
- * Motion Master will read the cogging_torque.bin file, convert bytes to 16-bit signed integer values and return that as an array of values.
427
- */
428
- getCoggingTorqueData(props, requestTimeout, messageId) {
429
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
430
- const getCoggingTorqueData = types_1.MotionMasterMessage.Request.GetCoggingTorqueData.create(Object.assign(Object.assign({}, props), { deviceAddress }));
431
- const id = this.sendRequest({ getCoggingTorqueData }, messageId);
432
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('coggingTorqueData', requestTimeout, id));
433
- }));
434
- }
435
- /**
436
- * Start offset detection.
437
- *
438
- * Running offset detection is different for firmwares <v5 and >=v5.
439
- *
440
- * For devices that run firmware >=v5, Motion Master will run multiple OS commands.
441
- * Before starting any command, device is switched to Modes of operation -2 (Diagnostics mode) and
442
- * it's put into operation enabled CiA402 state. The OS commands are then run in the following order:
443
- * - open phase detection
444
- * - phase resistance measurement
445
- * - phase inductance measurement
446
- * - pole pair detection
447
- * - motor phase order detection
448
- * - commutation offset measurement
449
- *
450
- * Motion Master will return an error if any of the following OS commands fail: open phase detection,
451
- * phase order detection, commutation offset measurement.
452
- * If other OS commands fail, Motion Master will continue with the procedure and only return a warning.
453
- *
454
- * Once the commutation offset measurement command completes, it will update the following parameter values:
455
- * - 0x2001:00 Commutation angle offset to the computed offset value
456
- * - 0x2009:01 Commutation offset State to 2 (OFFSET_VALID)
457
- *
458
- * For devices that run firmware <5 the same Modes of operation -2 is used, but it's named Commutation offset detection mode
459
- * and it will run as a single procedure as soon as the device is switched to CiA402 operation enabled state.
460
- * The end result is the same, the procedure will update 0x2001:00 and 0x2009:01 parameter values.
461
- *
462
- * This request will turn the motor.
463
- */
464
- startOffsetDetection(props, requestTimeout, messageId) {
465
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
466
- const startOffsetDetection = types_1.MotionMasterMessage.Request.StartOffsetDetection.create(Object.assign(Object.assign({}, props), { deviceAddress }));
467
- const id = this.sendRequest({ startOffsetDetection }, messageId);
468
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('offsetDetection', requestTimeout, id));
469
- }));
470
- }
471
- /**
472
- * @deprecated use {@link startSystemIdentification} instead
473
- */
474
- startPlantIdentification(props, requestTimeout, messageId) {
475
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
476
- const startPlantIdentification = types_1.MotionMasterMessage.Request.StartPlantIdentification.create(Object.assign(Object.assign({}, props), { deviceAddress }));
477
- const id = this.sendRequest({ startPlantIdentification }, messageId);
478
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('plantIdentification', requestTimeout, id));
479
- }));
480
- }
481
- /**
482
- * Compute auto tuning gains.
483
- *
484
- * Auto tuning gains can be computed for the position or the velocity controller.
485
- *
486
- * The prerequisites for running this procedure are a configured motor and the existence of
487
- * plant_model.csv file created by previously running the system identification {@link startSystemIdentification}.
488
- * Motion Master will return error if the plant_model.csv file is not found.
489
- *
490
- * In OBLAC Drives, this request is called when the tuning sliders (damping ratio, bandwidth) are moved and
491
- * during the CTC recording {@link startCoggingTorqueRecording} when auto-config is not skipped.
492
- *
493
- * Motion Master will compute the PID gains using a proprietary algorithm and update the Kp, Ki, Kd values of the 0x2011 and 0x2012 parameters.
494
- */
495
- computeAutoTuningGains(props, requestTimeout, messageId) {
496
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
497
- const computeAutoTuningGains = types_1.MotionMasterMessage.Request.ComputeAutoTuningGains.create(Object.assign(Object.assign({}, props), { deviceAddress }));
498
- const id = this.sendRequest({ computeAutoTuningGains }, messageId);
499
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('autoTuning', requestTimeout, id));
500
- }));
501
- }
502
- /**
503
- * Set motion controller parameters.
504
- *
505
- * This request sets the target value for a device on Motion Master.
506
- *
507
- * A previous call to {@link enableMotionController} will set the mode of operation to CSP, CSV, or CST and optionally enable filtering.
508
- */
509
- setMotionControllerParameters(props, messageId) {
510
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
511
- const setMotionControllerParameters = types_1.MotionMasterMessage.Request.SetMotionControllerParameters.create(Object.assign(Object.assign({}, props), { deviceAddress }));
512
- this.sendRequest({ setMotionControllerParameters }, messageId);
513
- return rxjs_1.EMPTY;
514
- }));
515
- }
516
- /**
517
- * Enable motion controller.
518
- *
519
- * This request will set the mode of operation to CSP, CSV, or CST and optionally enable filtering.
520
- *
521
- * If filtering is enabled Motion Master will compute an intermediate target value in each cycle and, depending on the active mode of operation,
522
- * set the value of one of 0x607A Target position, 0x60FF Target velocity, 0x6071 Target torque to that value.
523
- *
524
- * The target value can be updated with {@link setMotionControllerParameters}.
525
- */
526
- enableMotionController(props, requestTimeout, messageId) {
527
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
528
- const enableMotionController = types_1.MotionMasterMessage.Request.EnableMotionController.create(Object.assign(Object.assign({}, props), { deviceAddress }));
529
- const id = this.sendRequest({ enableMotionController }, messageId);
530
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('motionController', requestTimeout, id));
531
- }));
532
- }
533
- /**
534
- * Disable motion controller.
535
- *
536
- * Depending on the current CiA402 state this request will do the following:
537
- * - if device is in Quick stop active it will transition to Switch on disabled state
538
- * - if device is in Operation enabled it will transition to Switched on state
539
- */
540
- disableMotionController(props, requestTimeout, messageId) {
541
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
542
- const disableMotionController = types_1.MotionMasterMessage.Request.DisableMotionController.create(Object.assign(Object.assign({}, props), { deviceAddress }));
543
- const id = this.sendRequest({ disableMotionController }, messageId);
544
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('motionController', requestTimeout, id));
545
- }));
546
- }
547
- /**
548
- * Set signal generator parameters.
549
- *
550
- * This request will update the signal generator parameter values for a device on Motion Master.
551
- * The selected signal generator is then started by {@link startSignalGenerator}.
552
- * Signal generator must be started within the next 60 seconds before Motion Master invalidates the previously set parameters.
553
- */
554
- setSignalGeneratorParameters(props, requestTimeout, messageId) {
555
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
556
- const setSignalGeneratorParameters = types_1.MotionMasterMessage.Request.SetSignalGeneratorParameters.create(Object.assign(Object.assign({}, props), { deviceAddress }));
557
- const id = this.sendRequest({ setSignalGeneratorParameters }, messageId);
558
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('signalGenerator', requestTimeout, id));
559
- }));
560
- }
561
- /**
562
- * Start signal generator.
563
- *
564
- * This request will start one of the signal generators based on the
565
- * previously set parameters with {@link setSignalGeneratorParameters}.
566
- *
567
- * Signal generators are started by changing the mode of operation, putting the device into Operation enabled CiA402 state,
568
- * and setting the target value. What mode of operation is set depends on the type of signal generator and the selected controller:
569
- * - For the simple & advanced step response and the sine wave, one of CSP, CSV, or CST is set.
570
- * - For the ramp, trapezoidal, and bidirectional signal generators, also called profiles, one of the PP, PV, TQ is set.
571
- *
572
- * Currently, the only profile type that the firmware supports is the ramp profile.
573
- * Motion Master uses this profile type to construct and run the following signals: ramp, trapezoidal, and bidirectional.
574
- * Sine wave is also a profile, but it is currently being generated on Motion Master alone.
575
- * Firmwares >=5.2 will support generating and running sine wave profiles on devices themselves. This will enable lossless profile
576
- * execution on possibly higher frequencies. Future Motion Master versions will switch to this method.
577
- *
578
- * For the simple step response, Motion Master will only set the target value,
579
- * wait for the specified holding duration, and then send a Quick Stop command.
580
- *
581
- * The advanced step response is similar to the simple one, but, after the holding duration, it will set the new target
582
- * multiple times depending on the shape, and then send a Quick Stop if the repeat option is set to NO. If repeat is set to YES,
583
- * then the signal generator will run indefinitely and the users must stop it manually.
584
- *
585
- * Before running a profile, Motion Master will check if device supports the profile modes by looking at 0x6502 Supported drives modes.
586
- * If profile modes are not supported, then the profiles will be generated on Motion Master. This means the targets will be computed up-front.
587
- * If profiles are supported, then ramp, trapezoidal, and bidirectional signal generators are run in profile mode of operation.
588
- * To prepare the signal generator foe execution, Motion Master will set the following parameters:
589
- * - 0x6081:00 Profile velocity (only for position controller)
590
- * - 0x6083:00 Profile acceleration
591
- * - 0x6084:00 Profile deceleration
592
- * Motion Master knows when the profile has completed by comparing the demand with the actual value, taking into account the
593
- * holding duration and the shape of the profile. Once the profile is considered complete, Motion Master will send a Quick Stop, but
594
- * only if repeat is set to NO.
595
- *
596
- * The sine wave profile is generated up-front on Motion Master. Targets are computed for each master cycle (millisecond).
597
- * Once the last computed target has been set, Motion Master will send a Quick Stop if repeat is set to NO.
598
- *
599
- * For all signal generators, Motion Master will check the requested target against the currently set software position limits
600
- * and, if necessary, alter it whilst returning a warning.
601
- *
602
- * This request will turn the motor.
603
- */
604
- startSignalGenerator(props, requestTimeout, messageId) {
605
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
606
- const startSignalGenerator = types_1.MotionMasterMessage.Request.StartSignalGenerator.create(Object.assign(Object.assign({}, props), { deviceAddress }));
607
- const id = this.sendRequest({ startSignalGenerator }, messageId);
608
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('signalGenerator', requestTimeout, id));
609
- }));
610
- }
611
- /**
612
- * Stop signal generator.
613
- *
614
- * This request will send a Quick Stop to the device.
615
- */
616
- stopSignalGenerator(props, requestTimeout, messageId) {
617
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
618
- const stopSignalGenerator = types_1.MotionMasterMessage.Request.StopSignalGenerator.create(Object.assign(Object.assign({}, props), { deviceAddress }));
619
- const id = this.sendRequest({ stopSignalGenerator }, messageId);
620
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('signalGenerator', requestTimeout, id));
621
- }));
622
- }
623
- /**
624
- * Start monitoring device parameter values.
625
- *
626
- * When monitoring is started, Motion Master will begin and continue reading values from the device
627
- * and send them back to a client in the specified interval on the given topic.
628
- *
629
- * The request is made through the req/res socket {@link MotionMasterReqResSocket},
630
- * but the status messages will arrive on the pub/sub socket {@link MotionMasterPubSubSocket}.
631
- *
632
- * The same monitoring can read both PDO and SDO values. PDO values will be updated on every Motion Master cycle (1ms).
633
- * How fast will SDO values update depends on the number of SDOs being monitored. Motion Master reads the SDO values in a sequence
634
- * so, for example, if there are 10 SDOs and it takes 20ms to read a single SDO it will take approximately 200ms for each SDO to get updated.
635
- * IgH EtherCAT Master supports non-blocking SDO reading with a request to read and check the state of the request (one of not used, busy, failed, succeeded).
636
- * Future version of Motion Master will likely leverage this and update SDO values out of order as each of the requests to update SDO succeeds.
637
- * This should decrease the time it takes to read multiple SDOs.
638
- * If a parameter is required to be updated more frequently, it should be mapped as a PDO.
639
- *
640
- * Firmware versions >=5.2 supports SDO complete access, but it is currently not being supported in Motion Master.
641
- * With SDO complete access RECORD and ARRAY subitems can be read with a single request.
642
- *
643
- * Interval is given in microseconds.
644
- *
645
- * The topic should be unique. The previous monitoring will stop if the given topic is reused.
646
- * Clients can easily stop one another's monitoring by using the same topic.
647
- * Prefixing topics with the client id or some other unique identifier is suggested.
648
- *
649
- * When the monitoring request is received, Motion Master will mark all requested parameters as stale.
650
- * The first time a parameter gets refreshed from a device, it'll be marked as not stale.
651
- * Motion Master won't start publishing parameter values until all parameters are marked as not stale.
652
- * This was done in order to satisfy the firmware test client applications.
653
- *
654
- * Stopping the ongoing monitoring is done through the req/res socket using
655
- * the request message ID of the initial start monitoring message {@link stopMonitoringDeviceParameterValues}.
656
- */
657
- startMonitoringDeviceParameterValues(props, requestTimeout, messageId) {
658
- const startMonitoringDeviceParameterValues = types_1.MotionMasterMessage.Request.StartMonitoringDeviceParameterValues.create(props);
659
- const id = this.sendRequest({ startMonitoringDeviceParameterValues }, messageId);
660
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('monitoringParameterValues', requestTimeout, id));
661
- }
662
- /**
663
- * Stop monitoring device parameter values.
664
- *
665
- * Message ID used for {@link startMonitoringDeviceParameterValues} uniquely identifies a monitoring and is used for stopping it.
666
- */
667
- stopMonitoringDeviceParameterValues(props, messageId) {
668
- const stopMonitoringDeviceParameterValues = types_1.MotionMasterMessage.Request.StopMonitoringDeviceParameterValues.create(props);
669
- this.sendRequest({ stopMonitoringDeviceParameterValues }, messageId);
670
- return rxjs_1.EMPTY;
671
- }
672
- /**
673
- * Get the EtherCAT network state.
674
- *
675
- * Returns one of the EtherCAT network states: BOOT, INIT, PRE-OP, SAFE-OP, OP.
676
- * The state is returned as an enum value: INIT: 1, PREOP: 2, BOOT: 3, SAFEOP: 4, OP: 5.
677
- */
678
- getEthercatNetworkState(props, requestTimeout, messageId) {
679
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
680
- const getEthercatNetworkState = types_1.MotionMasterMessage.Request.GetEthercatNetworkState.create(Object.assign(Object.assign({}, props), { deviceAddress }));
681
- const id = this.sendRequest({ getEthercatNetworkState }, messageId);
682
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('ethercatNetworkState', requestTimeout, id));
683
- }));
684
- }
685
- /**
686
- * Set the EtherCAT network state.
687
- *
688
- * Set the EtherCAT network state to one of: BOOT, INIT, PRE-OP, SAFE-OP, OP.
689
- * The state is set by an enum value: INIT: 1, PREOP: 2, BOOT: 3, SAFEOP: 4, OP: 5.
690
- *
691
- * When switching from PRE-OP to OP, MM will reinitialize slaves in order to update the PDO mapping.
692
- */
693
- setEthercatNetworkState(props, requestTimeout, messageId) {
694
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
695
- const setEthercatNetworkState = types_1.MotionMasterMessage.Request.SetEthercatNetworkState.create(Object.assign(Object.assign({}, props), { deviceAddress }));
696
- const id = this.sendRequest({ setEthercatNetworkState }, messageId);
697
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('ethercatNetworkState', requestTimeout, id));
698
- }));
699
- }
700
- /**
701
- * @deprecated use {@link startCirculoEncoderNarrowAngleCalibrationProcedure} instead
702
- */
703
- startNarrowAngleCalibration(props, requestTimeout, messageId) {
704
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
705
- const startNarrowAngleCalibration = types_1.MotionMasterMessage.Request.StartNarrowAngleCalibration.create(Object.assign(Object.assign({}, props), { deviceAddress }));
706
- const id = this.sendRequest({ startNarrowAngleCalibration }, messageId);
707
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('narrowAngleCalibration', requestTimeout, id));
708
- }));
709
- }
710
- /**
711
- * Set system client timeout.
712
- *
713
- * This request will update the client timeout.
714
- *
715
- * Client timeout specifies how long Motion Master will wait for the client to send a ping or any other message before
716
- * considering it gone and clearing the resources (stopping procedures and monitorings) related to that client.
717
- *
718
- * Default client timeout is 1000ms.
719
- *
720
- * Client will typically change this once the socket connection is established.
721
- */
722
- setSystemClientTimeout(props, messageId) {
723
- const setSystemClientTimeout = types_1.MotionMasterMessage.Request.SetSystemClientTimeout.create(props);
724
- this.sendRequest({ setSystemClientTimeout }, messageId);
725
- return rxjs_1.EMPTY;
726
- }
727
- /**
728
- * Start system identification.
729
- *
730
- * This request will run the system identification procedure which identifies the plant model.
731
- *
732
- * Pre-conditions: a configured motor and configured encoders.
733
- *
734
- * The chirp signal that the procedure does only uses the torque controller.
735
- * The chirp signal is generated on Motion Master and then, on every master cycle (1ms), the target torque value is set on a device.
736
- * Motion Master will send a Quick Stop to a device after the last target value is set.
737
- *
738
- * The request can fail for multiple reasons: device is in the fault state, cannot set the op mode state,
739
- * or the system identification fails because not enough data points have been collected.
740
- * While running the chirp signal, the data points are collected, but due to potential communication lag it can happen
741
- * that master doesn't collect enough data points. If more than 80% of data points are missing, the procedure will fail.
742
- * If between 20%-80% of data points are missing, only a warning will be returned.
743
- *
744
- * Before computing the plant model data based on the collected data points, Motion Master will interpolate the missing data points.
745
- * Plant model data is then computed and written to plant_model.csv file on the device flash memory.
746
- * The plant model file is later used to compute the PID values using {@link computeAutoTuningGains} and {@link startFullAutoTuning}.
747
- * It's also used indirectly in {@link startCoggingTorqueRecording} when auto-config is turned on.
748
- * Motion Master will also update the integral limit values in 0x2011: Velocity controller and 0x2012: Position controller during this procedure.
749
- *
750
- * In future versions of firmware, the chirp signal would be executed on the devices themselves, so no data points will be missing
751
- * and the system identification will be able to run at higher frequencies and with higher precision.
752
- *
753
- * This request will turn the motor.
754
- */
755
- startSystemIdentification(props, requestTimeout, messageId) {
756
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
757
- const startSystemIdentification = types_1.MotionMasterMessage.Request.StartSystemIdentification.create(Object.assign(Object.assign({}, props), { deviceAddress }));
758
- const id = this.sendRequest({ startSystemIdentification }, messageId);
759
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('systemIdentification', requestTimeout, id));
760
- }));
761
- }
762
- /**
763
- * Get Circulo encoder magnet distance.
764
- *
765
- * This feature is only available for firmwares >=v5. For older firmwares, Motion Master will return an error.
766
- *
767
- * Motion Master will read registers 0x2B and 0x2F on the specified encoder (by encoder ordinal) and then it will compute the magnet distance.
768
- * The computation depends on the Circulo type, encoder port and ring revision.
769
- */
770
- getCirculoEncoderMagnetDistance(props, requestTimeout, messageId) {
771
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
772
- const getCirculoEncoderMagnetDistance = types_1.MotionMasterMessage.Request.GetCirculoEncoderMagnetDistance.create(Object.assign(Object.assign({}, props), { deviceAddress }));
773
- const id = this.sendRequest({ getCirculoEncoderMagnetDistance }, messageId);
774
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('circuloEncoderMagnetDistance', requestTimeout, id));
775
- }));
776
- }
777
- /**
778
- * Start the Circulo encoder narrow angle calibration procedure.
779
- *
780
- * This feature is only available on firmwares >=v5.
781
- *
782
- * Before starting the procedure, Motion Master will check and return an error if:
783
- * - the firmware version is not >=v5
784
- * - software position limits are set so that the required motor rotation is not possible
785
- * - for SMM devices, the encoder source type is not set to None
786
- * - the velocity resolution determined by the gear ratio, SI unit velocity and feed constant is not high enough
787
- *
788
- * Before starting the procedure, Motion Master will do the following:
789
- * - send OS command 14 (Ignore BiSS status bits) so that no firmware warnings or errors are raised during the procedure.
790
- * - set certain encoder registers to their default values.
791
- * - set the BiSS encoder to raw mode.
792
- * - change the values of some device parameters: profile acceleration, deceleration, max motor speed, etc.
793
- *
794
- * The parameter values Motion Master sets depend on the type of the device (fetched from the hardware description file).
795
- * Once the operation has completed, Motion Master will rollback all of the above parameters to their initial values.
796
- *
797
- * Procedure:
798
- * - The procedure is run in velocity profile mode of operation.
799
- * - The procedure will do multiple iterations until the encoder data is satisfactory.
800
- * - The procedure can fail for various reasons: data out of range, motor too slow, bad data, internal error, etc.
801
- * - The procedure will run a maximum of 13 calibration iterations, up to 2 mins in total.
802
- * - One iteration turns the motor in one direction and then the next one reverses the direction.
803
- * - Each iteration will record encoder data into HRD files (4kHz) that contain the raw data from the specified encoder.
804
- * - Motion Master will remove previous high resolution data (HRD) files after each iteration. HRD streaming is configured/started using OS commands.
805
- * - After each iteration, which lasts ~6 seconds, the recorded data in HRD files is read and passed to the iC House library.
806
- * - The recorded data is sliced into 32-bit pair of values of master and nonius track data. Motion Master creates two arrays out of this data and
807
- * passes that to the iC House library which computes the new calibration parameters depending on encoder type sine and cosine offset, gain, etc.
808
- * - The iterations are being repeated until the encoder (raw) data satisfies a certain threshold.
809
- *
810
- * The result of a successful calibration is setting multiple parameters into registers of the specified encoder.
811
- *
812
- * At the end of the procedure Motion Master will rotate the motor back to the starting position and run commutation offset detection.
813
- * There will also be a final iteration which only measures the values of a (now) calibrated encoder for display.
814
- *
815
- * This request will turn the motor.
816
- *
817
- * @todo improve documentation
818
- */
819
- startCirculoEncoderNarrowAngleCalibrationProcedure(props, requestTimeout, messageId) {
820
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
821
- const startCirculoEncoderNarrowAngleCalibrationProcedure = types_1.MotionMasterMessage.Request.StartCirculoEncoderNarrowAngleCalibrationProcedure.create(Object.assign(Object.assign({}, props), { deviceAddress }));
822
- const id = this.sendRequest({ startCirculoEncoderNarrowAngleCalibrationProcedure }, messageId);
823
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('circuloEncoderNarrowAngleCalibrationProcedure', requestTimeout, id));
824
- }));
825
- }
826
- /**
827
- * Get device cia402 state.
828
- */
829
- getDeviceCia402State(props, requestTimeout, messageId) {
830
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
831
- const getDeviceCia402State = types_1.MotionMasterMessage.Request.GetDeviceCiA402State.create(Object.assign(Object.assign({}, props), { deviceAddress }));
832
- const id = this.sendRequest({ getDeviceCia402State }, messageId);
833
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceCia402State', requestTimeout, id));
834
- }));
835
- }
836
- /**
837
- * Set device cia402 state.
838
- */
839
- setDeviceCia402State(props, requestTimeout, messageId) {
840
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
841
- const setDeviceCia402State = types_1.MotionMasterMessage.Request.SetDeviceCiA402State.create(Object.assign(Object.assign({}, props), { deviceAddress }));
842
- const id = this.sendRequest({ setDeviceCia402State }, messageId);
843
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceCia402State', requestTimeout, id));
844
- }));
845
- }
846
- /**
847
- * Get system log.
848
- *
849
- * The system log represents the collected standard output from Motion Master process.
850
- *
851
- * This request will return the whole system log which can be max ~2MB.
852
- *
853
- * The log level can be set as an environmental variable when the Motion Master process is started.
854
- * The log level can be selected in the OBLAC Drives Update Service expert mode before installing a release.
855
- * The supported log levels are:
856
- * - 6: Request content
857
- * - 5: Request type
858
- * - 4: Parameter value
859
- * - 3: Monitoring
860
- * - 2: Verbose 2
861
- * - 1: Verbose 1
862
- * - 0: Info
863
- * - 1: Warnings
864
- * - 2: Errors
865
- * - 3: Fatal errors
866
- */
867
- getSystemLog(requestTimeout, messageId) {
868
- const getSystemLog = types_1.MotionMasterMessage.Request.GetSystemVersion.create();
869
- const id = this.sendRequest({ getSystemLog }, messageId);
870
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('systemLog', requestTimeout, id));
871
- }
872
- /**
873
- * Start device SII restore.
874
- *
875
- * This request uses the EEPROM tool from SOEM to overwrite the SII portion of EEPROM on a device.
876
- *
877
- * Motion Master will verify the provided SII file before writing it to EEPROM. It will:
878
- * - check the file content length,
879
- * - compute CRC from a part of the SII file content and compare it to the CRC inside the file,
880
- * - check the SII category types in the category header.
881
- *
882
- * Unlike IgH EtherCAT Master which identifies interfaces by MAC address, the SOEM tool requires an adapter name.
883
- * Before calling SOEM tool Motion Master will find the adapter name by looking into /sys/class/net.
884
- *
885
- * The SOEM tool binary is being delivered as a part of the Motion Master Docker image.
886
- */
887
- startDeviceSiiRestore(props, requestTimeout, messageId) {
888
- const startDeviceSiiRestore = types_1.MotionMasterMessage.Request.StartDeviceSiiRestore.create(props);
889
- const id = this.sendRequest({ startDeviceSiiRestore }, messageId);
890
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('deviceSiiRestore', requestTimeout, id));
891
- }
892
- /**
893
- * Start open loop field control.
894
- *
895
- * The precondition for running the open loop field control is to have a configured motor.
896
- * No encoder configuration or offset detection is required.
897
- *
898
- * Open loop field control is started by changing the Modes of operation (0x6060) parameter value to -3 (Open loop field mode) and
899
- * setting the CiA402 state to Ready to switch on.
900
- * After that, Motion Master will run several OS commands that configure the open loop field control parameters:
901
- * - start angle [milliradian]
902
- * - end angle [milliradian]
903
- * - max rotational speed [radian/s]
904
- * - rotational acceleration [radian/s^2]
905
- * - start length [permille of rated torque]
906
- * - end length [permille of rated torque]
907
- * - length speed [permille of rated torque]
908
- *
909
- * After the configuration Motion Master will switch device to Operation enabled CiA402 state and the profile will start.
910
- *
911
- * While the open loop field control is running Motion Master will monitor the target reached bit in the statusword.
912
- * When the target reached bit becomes 1, Motion Master will stop the procedure by changing the CiA402 state to Switched on.
913
- *
914
- * Motion Master will return an error if the device goes out of Operation enabled state before target reached bit becomes 1.
915
- * There is no timeout on the Motion Master side.
916
- *
917
- * This request will turn the motor.
918
- */
919
- startOpenLoopFieldControl(props, requestTimeout, messageId) {
920
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
921
- const startOpenLoopFieldControl = types_1.MotionMasterMessage.Request.StartOpenLoopFieldControl.create(Object.assign(Object.assign({}, props), { deviceAddress }));
922
- const id = this.sendRequest({ startOpenLoopFieldControl }, messageId);
923
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('openLoopFieldControl', requestTimeout, id));
924
- }));
925
- }
926
- /**
927
- * @deprecated use {@link startFullAutoTuning} instead
928
- */
929
- computeFullAutoTuningGains(props, requestTimeout, messageId) {
930
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
931
- const computeFullAutoTuningGains = types_1.MotionMasterMessage.Request.ComputeFullAutoTuningGains.create(Object.assign(Object.assign({}, props), { deviceAddress }));
932
- const id = this.sendRequest({ computeFullAutoTuningGains }, messageId);
933
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('fullAutoTuning', requestTimeout, id));
934
- }));
935
- }
936
- /**
937
- * Start full auto tuning.
938
- *
939
- * The preconditions for running the full auto tuning are properly configured motor, brake and encoders,
940
- * and to have executed the offset detection and the system identification procedures.
941
- *
942
- * In order to successfully run the full auto tuning procedure, the motor must not rotate and the device must not be in CiA402 Operation enabled.
943
- *
944
- * Motion Master will try to read the plant_model.csv file and if doesn't exist it will return an error.
945
- *
946
- * Before the operation starts, Motion Master will measure the actual velocity for 500ms at a standstill in order to determine the encoder noise.
947
- * The noise is then sent, along with some other parameters (velocity feedback filter, feed forward, dc link voltage, firmware version and similar)
948
- * and data to a proprietary computation algorithm.
949
- * ADC current ratio which is used in the computation script is determined by the firmware version and the device hardware) ID (e.g. 9500, 9501, 8501...).
950
- *
951
- * Full auto tuning will compute the PID gains and Motion Master will update the parameter values in the velocity or position controller depending on the request.
952
- *
953
- * Motion Master will return the damping ratio, settling time, and bandwidth values when the procedure completes. UI will use these values to update the sliders in the Tuning screen.
954
- *
955
- * This procedure can be stopped with {@link stopFullAutoTuning}.
956
- */
957
- startFullAutoTuning(props, requestTimeout, messageId) {
958
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
959
- const startFullAutoTuning = types_1.MotionMasterMessage.Request.StartFullAutoTuning.create(Object.assign(Object.assign({}, props), { deviceAddress }));
960
- const id = this.sendRequest({ startFullAutoTuning }, messageId);
961
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('fullAutoTuning', requestTimeout, id));
962
- }));
963
- }
964
- /**
965
- * Stop full auto tuning.
966
- *
967
- * Motion Master has only one exit point for this procedure, which is after the computation algorithm ends.
968
- * This means that, once stopped, the procedure will compute the gains, but Motion Master will not update the controller parameters.
969
- * Previously started full auto tuning request will complete with an aborted error.
970
- */
971
- stopFullAutoTuning(props, requestTimeout, messageId) {
972
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
973
- const stopFullAutoTuning = types_1.MotionMasterMessage.Request.StopFullAutoTuning.create(Object.assign(Object.assign({}, props), { deviceAddress }));
974
- const id = this.sendRequest({ stopFullAutoTuning }, messageId);
975
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('fullAutoTuning', requestTimeout, id), (0, operators_1.map)((status) => {
976
- var _a, _b;
977
- if (((_a = status.success) === null || _a === void 0 ? void 0 : _a.code) === types_1.MotionMasterMessage.Status.FullAutoTuning.Success.Code.POSITION_STOPPED ||
978
- ((_b = status.success) === null || _b === void 0 ? void 0 : _b.code) === types_1.MotionMasterMessage.Status.FullAutoTuning.Success.Code.VELOCITY_STOPPED) {
979
- // Full auto tuning status is shared between start and stop.
980
- // When full auto tuning has stopped this request is considered successful.
981
- status.request = 'succeeded';
982
- }
983
- return status;
984
- }));
985
- }));
986
- }
987
- /**
988
- * Start Circulo encoder configuration.
989
- *
990
- * The preconditions for this procedure are to have Circulo device with internal encoders and a firmware >=v5.
991
- *
992
- * This procedure will set various internal encoder registers based on the hardware description, Circulo device type and the encoder ordinal.
993
- *
994
- * Before updating the registers, Motion Master will send an OS command to ignore the BiSS status bits. Once the procedure is done the value of this register will be reverted.
995
- *
996
- * Depending on the setup, this procedure can take up to 30 seconds.
997
- *
998
- * This procedure can fail if it's already running, if it's not supported because of the firmware version, or if the hardware description file is missing.
999
- *
1000
- * While this procedure runs, Motion Master will return its progress.
1001
- */
1002
- startCirculoEncoderConfiguration(props, requestTimeout, messageId) {
1003
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
1004
- const startCirculoEncoderConfiguration = types_1.MotionMasterMessage.Request.StartCirculoEncoderConfiguration.create(Object.assign(Object.assign({}, props), { deviceAddress }));
1005
- const id = this.sendRequest({ startCirculoEncoderConfiguration }, messageId);
1006
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('circuloEncoderConfiguration', requestTimeout, id));
1007
- }));
1008
- }
1009
- /**
1010
- * @deprecated use {@link stopDevice} instead
1011
- */
1012
- stopCirculoEncoderNarrowAngleCalibrationProcedure(props, requestTimeout, messageId) {
1013
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
1014
- const stopCirculoEncoderNarrowAngleCalibrationProcedure = types_1.MotionMasterMessage.Request.StopCirculoEncoderNarrowAngleCalibrationProcedure.create(Object.assign(Object.assign({}, props), { deviceAddress }));
1015
- const id = this.sendRequest({ stopCirculoEncoderNarrowAngleCalibrationProcedure }, messageId);
1016
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('circuloEncoderNarrowAngleCalibrationProcedure', requestTimeout, id));
1017
- }));
1018
- }
1019
- /**
1020
- * Start OS command.
1021
- *
1022
- * This request will execute an OS command and return a result as a bytearray.
1023
- *
1024
- * Motion Master will check if an OS command is already running and use a mutex to ensure only one OS command runs at a time.
1025
- *
1026
- * This request can fail if the requested OS command is not supported.
1027
- *
1028
- * Motion Master will check if the OS command has failed and return an error.
1029
- *
1030
- * The OS command can timeout if it takes longer than the provided timeout in milliseconds, in which case Motion Master will return an error.
1031
- */
1032
- startOsCommand(props, requestTimeout, messageId) {
1033
- return this.resolveDeviceAddress(props).pipe((0, operators_1.mergeMap)((deviceAddress) => {
1034
- const startOsCommand = types_1.MotionMasterMessage.Request.StartOsCommand.create(Object.assign(Object.assign({}, props), { deviceAddress }));
1035
- const id = this.sendRequest({ startOsCommand }, messageId);
1036
- return this.socket.message$.pipe((0, operators_2.transformMotionMasterMessageToStatus)('osCommand', requestTimeout, id));
1037
- }));
1038
- }
1039
- sendRequest(request, messageId) {
1040
- const id = messageId !== null && messageId !== void 0 ? messageId : (0, uuid_1.v4)();
1041
- const message = types_1.MotionMasterMessage.create({ request, id });
1042
- this.socket.send(message);
1043
- return id;
1044
- }
1045
- //
1046
- // Helpers
1047
- //
1048
- /**
1049
- * Resolve device.
1050
- */
1051
- resolveDevice(deviceRefObj, requestTimeout = 5000) {
1052
- if (!(0, util_1.isValidDeviceRefObj)(deviceRefObj)) {
1053
- return (0, rxjs_1.throwError)(() => new Error(`Device ref object is not valid ${JSON.stringify(deviceRefObj)}`));
1054
- }
1055
- const device = this.getCachedDeviceByDeviceRefObj(deviceRefObj);
1056
- if (device) {
1057
- return (0, rxjs_1.of)(device);
1058
- }
1059
- else {
1060
- return this.getDevices(requestTimeout).pipe((0, rxjs_1.tap)((devices) => {
1061
- this.deviceMap.clear();
1062
- devices.forEach((device) => {
1063
- if (!device.hardwareDescription) {
1064
- throw new Error(`Device ${device.position} has no hardware description`);
1065
- }
1066
- const deviceSerialNumber = (0, hardware_description_1.getSerialNumberFromHardwareDescription)(device.hardwareDescription);
1067
- this.deviceMap.set(deviceSerialNumber, device);
1068
- });
1069
- }), (0, operators_1.map)(() => {
1070
- const device = this.getCachedDeviceByDeviceRefObj(deviceRefObj);
1071
- if (!device) {
1072
- throw new Error(`Device is not found by deviceRefObj ${JSON.stringify(deviceRefObj)}`);
1073
- }
1074
- return device;
1075
- }));
1076
- }
1077
- }
1078
- /**
1079
- * Resolve device address.
1080
- *
1081
- * This method should return device address by device reference object,
1082
- * or throw an Error if device address cannot be found.
1083
- *
1084
- * Read the description of this class for more info.
1085
- */
1086
- resolveDeviceAddress(deviceRefObj, requestTimeout = 5000) {
1087
- if (!(0, util_1.isValidDeviceRefObj)(deviceRefObj)) {
1088
- return (0, rxjs_1.throwError)(() => new Error(`Device ref object is not valid ${JSON.stringify(deviceRefObj)}`));
1089
- }
1090
- if (deviceRefObj.deviceAddress) {
1091
- return (0, rxjs_1.of)(deviceRefObj.deviceAddress);
1092
- }
1093
- return this.resolveDevice(deviceRefObj, requestTimeout).pipe((0, operators_1.map)((device) => {
1094
- return device.deviceAddress;
1095
- }));
1096
- }
1097
- getCachedDeviceByDeviceRefObj(deviceRefObj) {
1098
- if (deviceRefObj.deviceSerialNumber) {
1099
- return this.deviceMap.get(deviceRefObj.deviceSerialNumber);
1100
- }
1101
- else if (typeof deviceRefObj.devicePosition === 'number') {
1102
- const devices = Array.from(this.deviceMap.values());
1103
- return devices.find((device) => device.position === deviceRefObj.devicePosition);
1104
- }
1105
- else if (typeof deviceRefObj.deviceAddress === 'number') {
1106
- const devices = Array.from(this.deviceMap.values());
1107
- return devices.find((device) => device.deviceAddress === deviceRefObj.deviceAddress);
1108
- }
1109
- return;
1110
- }
1111
- /**
1112
- * Get devices.
1113
- *
1114
- * Get device info from Motion Master and for each device in the list
1115
- * read its .hardware_description file and assign its content to the device.
1116
- */
1117
- getDevices(requestTimeout = 5000) {
1118
- return this.getDeviceInfo(requestTimeout).pipe((0, operators_1.mergeMap)((deviceInfo) => {
1119
- var _a;
1120
- const devices = ((_a = deviceInfo.devices) !== null && _a !== void 0 ? _a : []);
1121
- return (0, rxjs_1.forkJoin)(devices.map((device) => {
1122
- return this.getDeviceFile({ deviceAddress: device.deviceAddress, name: '.hardware_description' }, requestTimeout).pipe((0, operators_1.map)((deviceFile) => {
1123
- if (deviceFile.content) {
1124
- const data = (0, util_1.decodeTextContent)(deviceFile.content);
1125
- const hardwareDescription = JSON.parse(data);
1126
- let id = (0, uuid_1.v4)();
1127
- if (hardwareDescription) {
1128
- id = (0, hardware_description_1.getSerialNumberFromHardwareDescription)(hardwareDescription);
1129
- }
1130
- return Object.assign(Object.assign({}, device), { id, hardwareDescription });
1131
- }
1132
- return Object.assign({}, device);
1133
- }));
1134
- }));
1135
- }));
1136
- }
1137
- getParameterValue(a, b, c, d, e, f) {
1138
- try {
1139
- const { deviceRefObj, index, subindex, loadFromCache, requestTimeout, messageId } = this.resolveGetDeviceParameterValueArguments(a, b, c, d, e, f);
1140
- return this.createGetParameterValueObservable(deviceRefObj, index, subindex, loadFromCache, requestTimeout, messageId);
1141
- }
1142
- catch (err) {
1143
- return (0, rxjs_1.throwError)(() => err);
1144
- }
1145
- }
1146
- upload(a, b, c, d, e, f) {
1147
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1148
- const { deviceRefObj, index, subindex, loadFromCache, requestTimeout, messageId } = this.resolveGetDeviceParameterValueArguments(a, b, c, d, e, f);
1149
- return (0, rxjs_1.lastValueFrom)(this.createGetParameterValueObservable(deviceRefObj, index, subindex, loadFromCache, requestTimeout, messageId));
1150
- });
1151
- }
1152
- createGetParameterValueObservable(deviceRefObj, index, subindex, loadFromCache = false, requestTimeout = 1000, messageId) {
1153
- return (0, rxjs_1.defer)(() => {
1154
- return this.getDeviceParameterValues(Object.assign(Object.assign({}, deviceRefObj), { parameters: [{ index, subindex, loadFromCache }] }), requestTimeout, messageId).pipe((0, operators_1.map)(({ parameterValues }) => {
1155
- var _a, _b, _c;
1156
- const parameterValue = parameterValues === null || parameterValues === void 0 ? void 0 : parameterValues[0];
1157
- if (parameterValue === null || parameterValue === void 0 ? void 0 : parameterValue.success) {
1158
- const typeValue = parameterValue.typeValue;
1159
- if (typeValue) {
1160
- return parameterValues === null || parameterValues === void 0 ? void 0 : parameterValues[0][typeValue];
1161
- }
1162
- }
1163
- const props = Object.assign(Object.assign({}, deviceRefObj), { index, subindex, loadFromCache, requestTimeout, messageId });
1164
- const errorCodeName = types_1.MotionMasterMessage.Status.DeviceParameterValues.ParameterValue.Error.Code[(_c = (_b = (_a = parameterValues === null || parameterValues === void 0 ? void 0 : parameterValues[0]) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.code) !== null && _c !== void 0 ? _c : 0];
1165
- throw new Error(`Failed to get parameter value (${errorCodeName}) for ${JSON.stringify(props)}`);
1166
- }));
1167
- });
1168
- }
1169
- resolveGetDeviceParameterValueArguments(a, b, c, d, e, f) {
1170
- let deviceSerialNumber;
1171
- let index;
1172
- let subindex = 0;
1173
- let loadFromCache = false;
1174
- let requestTimeout = 1000;
1175
- let deviceRefObj;
1176
- let messageId;
1177
- if (typeof b === 'number' && typeof c === 'number') { // index, subindex, e.g. 0x6060, 1
1178
- deviceRefObj = (0, util_1.makeDeviceRefObj)(a);
1179
- index = b;
1180
- subindex = c;
1181
- if (typeof d === 'boolean') {
1182
- loadFromCache = d;
1183
- }
1184
- if (typeof e === 'number') {
1185
- requestTimeout = e;
1186
- }
1187
- if (typeof f === 'string') {
1188
- messageId = f;
1189
- }
1190
- }
1191
- else if (typeof a === 'string') { // device parameter id, e.g. "0x2110:1A.8502-03-0001353-2115"
1192
- [deviceSerialNumber, index, subindex] = (0, device_parameter_1.splitDeviceParameterId)(a);
1193
- deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceSerialNumber);
1194
- if (typeof b === 'boolean') {
1195
- loadFromCache = b;
1196
- }
1197
- if (typeof c === 'number') {
1198
- requestTimeout = c;
1199
- }
1200
- if (typeof d === 'string') {
1201
- messageId = d;
1202
- }
1203
- }
1204
- if (!index) {
1205
- throw new Error('Device parameter index is not provided!');
1206
- }
1207
- if (!deviceRefObj) {
1208
- throw new Error('Device address, position or serial number is not provided!');
1209
- }
1210
- return { deviceRefObj, index, subindex, loadFromCache, requestTimeout, messageId };
1211
- }
1212
- getParameterValues(ids, loadFromCache = false, requestTimeout = 9000, messageId) {
1213
- return this.resolveGetParameterValuesIds(ids).pipe((0, operators_1.mergeMap)((tuples) => {
1214
- var _a;
1215
- const collection = [];
1216
- for (const [deviceAddress, index, subindex] of tuples) {
1217
- let item = collection.find(c => c.deviceAddress === deviceAddress);
1218
- if (!item) {
1219
- item = { deviceAddress, parameters: [], sendProgress: false };
1220
- collection.push(item);
1221
- }
1222
- (_a = item.parameters) === null || _a === void 0 ? void 0 : _a.push({ index, subindex, loadFromCache });
1223
- }
1224
- return this.getMultiDeviceParameterValues({ collection }, requestTimeout, messageId).pipe((0, operators_1.map)((multiDeviceParameterValues) => {
1225
- if (!(multiDeviceParameterValues === null || multiDeviceParameterValues === void 0 ? void 0 : multiDeviceParameterValues.collection)) {
1226
- throw new Error(`Multi device parameter values collection is empty`);
1227
- }
1228
- return multiDeviceParameterValues.collection.map(({ parameterValues, deviceAddress }) => {
1229
- if (!parameterValues) {
1230
- throw new Error(`No parameterValues for device ${deviceAddress}`);
1231
- }
1232
- return parameterValues.map((parameterValue) => {
1233
- const value = parameterValue;
1234
- const typeValue = value === null || value === void 0 ? void 0 : value.typeValue;
1235
- if (typeValue) {
1236
- return parameterValue[typeValue];
1237
- }
1238
- throw new Error(`No type value for parameter ${(0, parameter_1.makeParameterId)(value === null || value === void 0 ? void 0 : value.index, value === null || value === void 0 ? void 0 : value.subindex)}`);
1239
- });
1240
- }).flat();
1241
- }));
1242
- }));
1243
- }
1244
- uploadMany(ids, loadFromCache = false, requestTimeout = 9000, messageId) {
1245
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1246
- return (0, rxjs_1.lastValueFrom)(this.getParameterValues(ids, loadFromCache, requestTimeout, messageId));
1247
- });
1248
- }
1249
- resolveGetParameterValuesIds(ids) {
1250
- if (ids.length === 0) {
1251
- return (0, rxjs_1.throwError)(() => new Error('The provided array of device parameter ids or addresses is empty!'));
1252
- }
1253
- let refs;
1254
- if ((0, types_1.isArrayOfDeviceSerialNumbers)(ids)) {
1255
- refs = ids.map(id => (0, device_parameter_1.splitDeviceParameterId)(id));
1256
- }
1257
- else {
1258
- refs = ids;
1259
- }
1260
- return (0, rxjs_1.defer)(() => {
1261
- return (0, rxjs_1.forkJoin)(refs.map(([deviceRef, index, subindex]) => {
1262
- return this.resolveDeviceAddress((0, util_1.makeDeviceRefObj)(deviceRef)).pipe((0, operators_1.map)((deviceAddress) => ([deviceAddress, index, subindex])));
1263
- }));
1264
- });
1265
- }
1266
- setParameterValue(a, b, c, d, e, f, g) {
1267
- try {
1268
- const { deviceRefObj, index, subindex, value, valueTypeKey, requestTimeout, messageId } = this.resolveSetDeviceParameterValueArguments(a, b, c, d, e, f, g);
1269
- return this.createSetParameterValueObservable(deviceRefObj, index, subindex, value, valueTypeKey, requestTimeout, messageId);
1270
- }
1271
- catch (err) {
1272
- return (0, rxjs_1.throwError)(() => err);
1273
- }
1274
- }
1275
- download(a, b, c, d, e, f, g) {
1276
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1277
- const { deviceRefObj, index, subindex, value, valueTypeKey, requestTimeout, messageId } = this.resolveSetDeviceParameterValueArguments(a, b, c, d, e, f, g);
1278
- return (0, rxjs_1.lastValueFrom)(this.createSetParameterValueObservable(deviceRefObj, index, subindex, value, valueTypeKey, requestTimeout, messageId));
1279
- });
1280
- }
1281
- createSetParameterValueObservable(deviceRefObj, index, subindex, value, valueTypeKey, requestTimeout = 1000, messageId) {
1282
- return (0, rxjs_1.defer)(() => {
1283
- return this.resolveDeviceParameterTypeValueKey(deviceRefObj, index, subindex, valueTypeKey).pipe((0, operators_1.mergeMap)((valueTypeKey) => {
1284
- const parameterValue = { index, subindex, [valueTypeKey]: value };
1285
- return this.setDeviceParameterValues(Object.assign(Object.assign({}, deviceRefObj), { parameterValues: [parameterValue] }), requestTimeout, messageId).pipe((0, operators_1.map)(({ parameterValues }) => {
1286
- var _a, _b, _c;
1287
- const parameterValue = parameterValues === null || parameterValues === void 0 ? void 0 : parameterValues[0];
1288
- if (parameterValue === null || parameterValue === void 0 ? void 0 : parameterValue.success) {
1289
- const typeValue = parameterValue.typeValue;
1290
- if (typeValue) {
1291
- return;
1292
- }
1293
- }
1294
- const props = Object.assign(Object.assign({}, deviceRefObj), { index, subindex, value, valueTypeKey, requestTimeout, messageId });
1295
- const errorCodeName = types_1.MotionMasterMessage.Status.DeviceParameterValues.ParameterValue.Error.Code[(_c = (_b = (_a = parameterValues === null || parameterValues === void 0 ? void 0 : parameterValues[0]) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.code) !== null && _c !== void 0 ? _c : 0];
1296
- throw new Error(`Failed to set parameter value (${errorCodeName}) for ${JSON.stringify(props)}`);
1297
- }));
1298
- }));
1299
- });
1300
- }
1301
- /**
1302
- * Resolve get device parameter value arguments.
1303
- */
1304
- resolveSetDeviceParameterValueArguments(a, b, c, d, e, f, g) {
1305
- let deviceSerialNumber;
1306
- let index;
1307
- let subindex = 0;
1308
- let value = 0;
1309
- let valueTypeKey;
1310
- let requestTimeout = 1000;
1311
- let deviceRefObj;
1312
- let messageId;
1313
- if (typeof b === 'number' && typeof c === 'number') { // index, subindex, e.g. 0x6060, 1
1314
- deviceRefObj = (0, util_1.makeDeviceRefObj)(a);
1315
- index = b;
1316
- subindex = c;
1317
- if (d !== undefined) {
1318
- value = d;
1319
- }
1320
- valueTypeKey = e;
1321
- if (typeof f === 'number') {
1322
- requestTimeout = f;
1323
- }
1324
- messageId = g;
1325
- }
1326
- else if (typeof a === 'string') { // device parameter id, e.g. "0x2110:1A.8502-03-0001353-2115"
1327
- [deviceSerialNumber, index, subindex] = (0, device_parameter_1.splitDeviceParameterId)(a);
1328
- deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceSerialNumber);
1329
- value = b;
1330
- if (typeof c !== 'number') {
1331
- valueTypeKey = c;
1332
- }
1333
- if (typeof d === 'number') {
1334
- requestTimeout = d;
1335
- }
1336
- messageId = e;
1337
- }
1338
- if (!index) {
1339
- throw new Error('Device parameter index is not provided!');
1340
- }
1341
- if (!deviceRefObj) {
1342
- throw new Error('Device address, position or serial number is not provided!');
1343
- }
1344
- return { deviceRefObj, index, subindex, value, valueTypeKey, requestTimeout, messageId };
1345
- }
1346
- setParameterValues(ids, requestTimeout = 9000, messageId) {
1347
- if (ids.length === 0) {
1348
- return (0, rxjs_1.throwError)(() => new Error('The provided array of device parameter ids or addresses is empty!'));
1349
- }
1350
- let refs;
1351
- if ((0, types_1.isObjectOfDeviceSerialNumberToValues)(ids)) {
1352
- refs = Object.entries(ids).map(([id, value]) => ([...(0, device_parameter_1.splitDeviceParameterId)(id), value]));
1353
- }
1354
- else {
1355
- refs = ids;
1356
- }
1357
- return (0, rxjs_1.defer)(() => {
1358
- return (0, rxjs_1.forkJoin)(refs.map(([deviceRef, index, subindex, value, typeValueKey]) => {
1359
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1360
- return this.resolveDeviceAddress(deviceRefObj).pipe((0, operators_1.mergeMap)((deviceAddress) => {
1361
- return this.resolveDeviceParameterTypeValueKey(deviceRefObj, index, subindex, typeValueKey).pipe((0, operators_1.map)((typeValueKey) => ([deviceAddress, index, subindex, value, typeValueKey])));
1362
- }));
1363
- })).pipe((0, operators_1.mergeMap)((tuples) => {
1364
- var _a;
1365
- const collection = [];
1366
- for (const [deviceAddress, index, subindex, value, typeValueKey] of tuples) {
1367
- let item = collection.find(c => c.deviceAddress === deviceAddress);
1368
- if (!item) {
1369
- item = { deviceAddress, parameterValues: [] };
1370
- collection.push(item);
1371
- }
1372
- (_a = item.parameterValues) === null || _a === void 0 ? void 0 : _a.push({ index, subindex, [typeValueKey]: value });
1373
- }
1374
- return this.setMultiDeviceParameterValues({ collection }, requestTimeout, messageId).pipe((0, operators_1.map)((multiDeviceParameterValues) => {
1375
- var _a;
1376
- (_a = multiDeviceParameterValues.collection) === null || _a === void 0 ? void 0 : _a.map(({ parameterValues, deviceAddress }) => {
1377
- if (!parameterValues) {
1378
- throw new Error(`No parameterValues for device ${deviceAddress}`);
1379
- }
1380
- });
1381
- }));
1382
- }));
1383
- });
1384
- }
1385
- downloadMany(ids, requestTimeout = 9000, messageId) {
1386
- return (0, rxjs_1.lastValueFrom)(this.setParameterValues(ids, requestTimeout, messageId));
1387
- }
1388
- resolveDeviceParameterTypeValueKey(deviceRefObj, index, subindex, typeValueKey) {
1389
- if (typeValueKey) {
1390
- return (0, rxjs_1.of)(typeValueKey);
1391
- }
1392
- const parameterId = (0, parameter_1.makeParameterId)(index, subindex);
1393
- return this.resolveDeviceAddress(deviceRefObj).pipe((0, operators_1.mergeMap)((deviceAddress) => {
1394
- const el = this.typeValueKeyMap.get(deviceAddress);
1395
- if (el) {
1396
- typeValueKey = el.get(parameterId);
1397
- if (!typeValueKey) {
1398
- throw new Error(`No type value key is set for device ${deviceAddress} ${parameterId}`);
1399
- }
1400
- return (0, rxjs_1.of)(typeValueKey);
1401
- }
1402
- else {
1403
- return this.getDeviceParameterInfo({ deviceAddress }, 5000).pipe((0, operators_1.map)(({ parameters }) => {
1404
- if (!parameters) {
1405
- throw new Error(`Device parameter info has no parameters ${deviceAddress}`);
1406
- }
1407
- const map = new Map();
1408
- this.typeValueKeyMap.set(deviceAddress, map);
1409
- for (const parameter of parameters) {
1410
- if (parameter.valueType) {
1411
- const typeValueKey = util_1.valueTypeToParameterTypeValueKeyMap.get(parameter.valueType);
1412
- if (typeValueKey) {
1413
- map.set((0, parameter_1.makeParameterId)(parameter), typeValueKey);
1414
- }
1415
- }
1416
- }
1417
- typeValueKey = map.get(parameterId);
1418
- if (!typeValueKey) {
1419
- throw new Error(`No type value key is set for device ${deviceAddress} ${parameterId}`);
1420
- }
1421
- return typeValueKey;
1422
- }));
1423
- }
1424
- }));
1425
- }
1426
- /**
1427
- * Get device parameters.
1428
- */
1429
- getDeviceParameters(props, requestTimeout = 30000) {
1430
- return this.resolveDevice(props).pipe((0, operators_1.mergeMap)((device) => {
1431
- return this.getDeviceParameterInfo({ deviceAddress: device.deviceAddress }, requestTimeout).pipe((0, operators_1.mergeMap)(deviceParameterInfoStatus => {
1432
- var _a;
1433
- const { loadFromCache, sendProgress } = props;
1434
- const parameters = (_a = deviceParameterInfoStatus.parameters) === null || _a === void 0 ? void 0 : _a.map(p => { var _a, _b; return ({ index: (_a = p.index) !== null && _a !== void 0 ? _a : 0, subindex: (_b = p.subindex) !== null && _b !== void 0 ? _b : 0, loadFromCache }); });
1435
- return this.getDeviceParameterValues({ deviceAddress: device.deviceAddress, sendProgress, parameters }, requestTimeout).pipe((0, operators_1.map)(deviceParameterValuesStatus => {
1436
- var _a, _b;
1437
- if (!deviceParameterValuesStatus.parameterValues) {
1438
- throw new Error('Device parameter values is empty');
1439
- }
1440
- const deviceParameters = deviceParameterValuesStatus.parameterValues.map((value, i) => {
1441
- var _a, _b, _c;
1442
- const index = (_a = value.index) !== null && _a !== void 0 ? _a : 0;
1443
- const subindex = (_b = value.subindex) !== null && _b !== void 0 ? _b : 0;
1444
- const id = (0, device_parameter_1.makeDeviceParameterId)(device.id, index, subindex);
1445
- return (Object.assign(Object.assign(Object.assign({ id }, value), (_c = deviceParameterInfoStatus.parameters) === null || _c === void 0 ? void 0 : _c[i]), { index, subindex, value: (0, util_1.getParameterValue)(value) }));
1446
- });
1447
- const progress = sendProgress ? (_b = (_a = deviceParameterValuesStatus === null || deviceParameterValuesStatus === void 0 ? void 0 : deviceParameterValuesStatus.progress) === null || _a === void 0 ? void 0 : _a.percentage) !== null && _b !== void 0 ? _b : 0 : 100;
1448
- return { parameters: deviceParameters, progress };
1449
- }));
1450
- }));
1451
- }));
1452
- }
1453
- /**
1454
- * Get files.
1455
- */
1456
- getFiles(deviceRef, requestTimeout = 30000, messageId) {
1457
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1458
- return this.getDeviceFileList(deviceRefObj, requestTimeout, messageId).pipe((0, operators_1.map)((status) => { var _a, _b; return (_b = (_a = status.fileList) === null || _a === void 0 ? void 0 : _a.files) !== null && _b !== void 0 ? _b : []; }));
1459
- }
1460
- /**
1461
- * Get file.
1462
- */
1463
- getFile(deviceRef, name, requestTimeout = 5000, messageId) {
1464
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1465
- return this.getDeviceFile(Object.assign(Object.assign({}, deviceRefObj), { name }), requestTimeout, messageId).pipe((0, operators_1.map)(({ content }) => content));
1466
- }
1467
- /**
1468
- * Get decoded file.
1469
- *
1470
- * Content of a device file is returned as a binary data buffer.
1471
- * This functions tries to decode the content as a text in utf-8 character encoding.
1472
- */
1473
- getDecodedFile(deviceRef, name, requestTimeout = 2000, messageId) {
1474
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1475
- return this.getDeviceFile(Object.assign(Object.assign({}, deviceRefObj), { name }), requestTimeout, messageId).pipe((0, operators_1.map)(({ content }) => {
1476
- if (content) {
1477
- return (0, util_1.decodeTextContent)(content);
1478
- }
1479
- throw new Error(`Device file ${name} content for device ${deviceRef} is empty!}`);
1480
- }));
1481
- }
1482
- /**
1483
- * Unlock protected files.
1484
- *
1485
- * This will enable the deletion of protected files.
1486
- * Protected files begin with a period, such as '.hardware_description'.
1487
- */
1488
- unlockProtectedFiles(deviceRef, requestTimeout = 3000, messageId) {
1489
- return this.getDecodedFile(deviceRef, 'fs-stackunlock=DD1317', requestTimeout, messageId);
1490
- }
1491
- /**
1492
- * Delete file.
1493
- */
1494
- deleteFile(deviceRef, name, requestTimeout = 3000, messageId) {
1495
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1496
- return this.deleteDeviceFile(Object.assign(Object.assign({}, deviceRefObj), { name }), requestTimeout, messageId);
1497
- }
1498
- /**
1499
- * Get system log lines.
1500
- *
1501
- * Get the system log content and parse it into an array of lines, where each line contains the date, uptime, ID, file, level, and message.
1502
- */
1503
- getSystemLogLines(requestTimeout = 2000, messageId) {
1504
- return this.getSystemLog(requestTimeout, messageId).pipe((0, operators_1.map)((systemLog) => { var _a; return (0, util_1.parseSystemLogContent)((_a = systemLog.content) !== null && _a !== void 0 ? _a : ''); }));
1505
- }
1506
- /**
1507
- * Store parameters.
1508
- *
1509
- * Command the device to store the parameters into config.csv, then delay initially and subsequently check if the value of
1510
- * the Store parameters has changed to 1, indicating the successful completion.
1511
- *
1512
- * {@link https://www.synapticon.com/documentation/circulo/sw5.0/device_info/save_restore_config.html}
1513
- */
1514
- storeParameters(deviceRef) {
1515
- return this.setParameterValue(deviceRef, 0x1010, 1, 0x65766173).pipe(// "evas"
1516
- (0, operators_1.delay)(2000), (0, operators_1.mergeMap)(() => this.matchParameterValue(deviceRef, 0x1010, 1, 1).pipe((0, operators_1.retry)({ count: 10, delay: 500 }))));
1517
- }
1518
- /**
1519
- * Restore default parameters.
1520
- *
1521
- * Command the device to restore the default parameters, then delay initially and subsequently check if the value of
1522
- * the Restore default parameters has changed to 1, indicating the successful completion.
1523
- *
1524
- * {@link https://www.synapticon.com/documentation/circulo/sw5.0/device_info/save_restore_config.html}
1525
- */
1526
- restoreDefaultParameters(deviceRef, type = types_1.RestoreDefaultParametersType.RESTORE_ALL_DEFAULT_PARAMETERS) {
1527
- return this.setParameterValue(deviceRef, 0x1011, type, 0x64616f6c).pipe(// "daol"
1528
- (0, operators_1.delay)(2000), (0, operators_1.mergeMap)(() => this.matchParameterValue(deviceRef, 0x1011, type, 1).pipe((0, operators_1.retry)({ count: 10, delay: 500 }))));
1529
- }
1530
- /**
1531
- * Match parameter value.
1532
- *
1533
- * This function will retrieve a parameter value from a device and compare it with the expected value.
1534
- *
1535
- * @throws Will throw an error if the values do not match.
1536
- */
1537
- matchParameterValue(deviceRef, index, subindex, expectedValue) {
1538
- return this.getParameterValue(deviceRef, index, subindex).pipe((0, operators_1.map)((value) => {
1539
- if (value !== expectedValue) {
1540
- throw new Error(`Device parameter value and the expected value don't match: ${value} ${expectedValue}`);
1541
- }
1542
- }));
1543
- }
1544
- matchCia402States(deviceRef, expectedStates) {
1545
- return this.getParameterValue(deviceRef, 0x6041, 0).pipe((0, operators_1.map)((value) => {
1546
- const state = (0, cia402_1.getCia402State)(value);
1547
- if (!expectedStates.includes(state)) {
1548
- throw new Error(`Device CiA402 state and the expected state don't match: ${state} ${expectedStates}`);
1549
- }
1550
- }));
1551
- }
1552
- /**
1553
- * Helper function to enable motion.
1554
- */
1555
- enableMotion(deviceRef, controllerType, filter = false, requestTimeout = 2000, messageId) {
1556
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1557
- return this.enableMotionController(Object.assign(Object.assign({}, deviceRefObj), { controllerType, filter }), requestTimeout, messageId);
1558
- }
1559
- /**
1560
- * Helper function to disable motion.
1561
- */
1562
- disableMotion(deviceRef, requestTimeout = 3000, messageId) {
1563
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1564
- return this.disableMotionController(deviceRefObj, requestTimeout, messageId);
1565
- }
1566
- /**
1567
- * Helper function to set motion target.
1568
- */
1569
- setMotionTarget(deviceRef, target, messageId) {
1570
- const deviceRefObj = (0, util_1.makeDeviceRefObj)(deviceRef);
1571
- return this.setMotionControllerParameters(Object.assign(Object.assign({}, deviceRefObj), { target }), messageId);
1572
- }
1573
- /**
1574
- * Get CiA402 state.
1575
- */
1576
- getCia402State(deviceRef, requestTimeout = 1000, messageId) {
1577
- return this.getParameterValue(deviceRef, 0x6041, 0, false, requestTimeout, messageId).pipe((0, operators_1.map)((value) => (0, cia402_1.getCia402State)(value)));
1578
- }
1579
- /**
1580
- * Transition to CiA402 state.
1581
- *
1582
- * This function will utilize the current value of the controlword and modify it to transition to the requested CiA402 state.
1583
- *
1584
- * Only one transition will occur, except when the current CiA402 state is SWITCH_ON_DISABLED. In this case,
1585
- * the first transition is from SOD to RTSO, and then from RTSO to the requested CiA402 state.
1586
- *
1587
- * The Statusword will be polled to check if the device has successfully transitioned to the requested CiA402 state.
1588
- * When transitioning to QSA, the Statusword will be checked against both QSA and SOD.
1589
- * This is necessary because the automatic transition from QSA to SOD can occur faster than the client's polling interval.
1590
- */
1591
- transitionToCia402State(deviceRef, targetState) {
1592
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1593
- let currentState = yield (0, rxjs_1.lastValueFrom)(this.getCia402State(deviceRef));
1594
- if (targetState === currentState) {
1595
- return;
1596
- }
1597
- if (currentState === cia402_1.Cia402State.NOT_READY_TO_SWITCH_ON || currentState === cia402_1.Cia402State.FAULT_REACTION_ACTIVE) {
1598
- throw new Error(`It is not possible to transition from state ${currentState} to state ${targetState}. The transition from the current ${currentState} state is automatic.`);
1599
- }
1600
- let controlword = yield this.upload(deviceRef, 0x6040, 0);
1601
- let transition = cia402_2.cia402Transitions.find(t => t.from === currentState && t.to === targetState);
1602
- // From SOD it's only possible to transition to RTSO.
1603
- if (currentState === cia402_1.Cia402State.SWITCH_ON_DISABLED && targetState !== cia402_1.Cia402State.READY_TO_SWITCH_ON) {
1604
- transition = cia402_2.cia402Transitions.find(t => t.from === cia402_1.Cia402State.READY_TO_SWITCH_ON && t.to === targetState);
1605
- }
1606
- if (!transition) {
1607
- throw new Error(`It is not possible to transition from state ${currentState} to state ${targetState}.`);
1608
- }
1609
- if (currentState === cia402_1.Cia402State.SWITCH_ON_DISABLED) {
1610
- const sodToRtsoTransition = cia402_2.cia402Transitions[0];
1611
- const command = (0, cia402_3.createControlwordCommand)(controlword, sodToRtsoTransition.command);
1612
- yield (0, rxjs_1.lastValueFrom)(this.setParameterValue(deviceRef, 0x6040, 0, command).pipe((0, operators_1.mergeMap)(() => this.matchCia402States(deviceRef, [cia402_1.Cia402State.READY_TO_SWITCH_ON]).pipe((0, operators_1.retry)({ count: 5, delay: 1000 })))));
1613
- controlword = yield this.upload(deviceRef, 0x6040, 0);
1614
- currentState = yield (0, rxjs_1.lastValueFrom)(this.getCia402State(deviceRef));
1615
- if (targetState === currentState) {
1616
- return;
1617
- }
1618
- }
1619
- const command = (0, cia402_3.createControlwordCommand)(controlword, transition.command);
1620
- const expectedStates = [targetState];
1621
- if (targetState === cia402_1.Cia402State.QUICK_STOP_ACTIVE) {
1622
- expectedStates.push(cia402_1.Cia402State.SWITCH_ON_DISABLED);
1623
- }
1624
- yield (0, rxjs_1.lastValueFrom)(this.setParameterValue(deviceRef, 0x6040, 0, command).pipe((0, operators_1.mergeMap)(() => this.matchCia402States(deviceRef, expectedStates).pipe((0, operators_1.retry)({ count: 5, delay: 1000 }))), (0, operators_1.catchError)(() => {
1625
- throw new Error(`Timeout occurred while transitioning from ${currentState} state to ${targetState} state.`);
1626
- })));
1627
- });
1628
- }
1629
- resetFault(deviceRef) {
1630
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1631
- const currentState = yield (0, rxjs_1.lastValueFrom)(this.getCia402State(deviceRef));
1632
- if (currentState !== cia402_1.Cia402State.FAULT) {
1633
- throw new Error(`Device ${deviceRef} is not in FAULT CiA402 state.`);
1634
- }
1635
- this.transitionToCia402State(deviceRef, cia402_1.Cia402State.SWITCH_ON_DISABLED);
1636
- });
1637
- }
1638
- quickStop(deviceRef) {
1639
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1640
- const currentState = yield (0, rxjs_1.lastValueFrom)(this.getCia402State(deviceRef));
1641
- if (currentState !== cia402_1.Cia402State.OPERATION_ENABLED) {
1642
- throw new Error(`Device ${deviceRef} is not in OPERATION_ENABLED CiA402 state.`);
1643
- }
1644
- this.transitionToCia402State(deviceRef, cia402_1.Cia402State.QUICK_STOP_ACTIVE);
1645
- });
1646
- }
1647
- /**
1648
- * Reset targets.
1649
- *
1650
- * Set torque and velocity targets to 0, and set the position target to the current position value.
1651
- */
1652
- resetTargets(deviceRef) {
1653
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
1654
- const positionActualValue = yield this.upload(deviceRef, 0x6064, 0);
1655
- return this.downloadMany([
1656
- [deviceRef, 0x6071, 0, 0],
1657
- [deviceRef, 0x607A, 0, positionActualValue],
1658
- [deviceRef, 0x60FF, 0, 0], // target velocity
1659
- ]);
1660
- });
1661
- }
1662
- /**
1663
- * Get modes of operation.
1664
- *
1665
- * Retrieve the value of the 0x6061:00 Modes of operation display.
1666
- */
1667
- getModesOfOperation(deviceRef, requestTimeout = 1000, messageId) {
1668
- return this.getParameterValue(deviceRef, 0x6061, 0, false, requestTimeout, messageId);
1669
- }
1670
- /**
1671
- * Set modes of operation.
1672
- *
1673
- * Set the 0x6060:00 Modes of operation to one of the available options, such as Homing mode (6).
1674
- */
1675
- setModesOfOperation(deviceRef, value, requestTimeout = 1000, messageId) {
1676
- return this.setParameterValue(deviceRef, 0x6060, 0, value, 'uintValue', requestTimeout, messageId);
1677
- }
1678
- }
1679
- exports.MotionMasterReqResClient = MotionMasterReqResClient;
1680
- //# sourceMappingURL=motion-master-req-res-client.js.map