@synapticon/motion-master-client 2.3.0-beta.0 → 6.0.0-alpha.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/api-error.d.ts +25 -0
- package/dist/api-error.js +52 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.js +37 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +8 -0
- package/dist/eni.d.ts +197 -0
- package/dist/eni.js +61 -0
- package/dist/generated/Api.d.ts +1886 -0
- package/dist/generated/Api.js +1293 -0
- package/dist/generated/data-contracts.d.ts +2282 -0
- package/dist/generated/data-contracts.js +12 -0
- package/dist/generated/http-client.d.ts +60 -0
- package/dist/generated/http-client.js +171 -0
- package/dist/hex.d.ts +2 -0
- package/dist/hex.js +20 -0
- package/dist/index.d.ts +13 -7
- package/dist/index.js +20 -22
- package/dist/lan.d.ts +4 -0
- package/dist/lan.js +59 -0
- package/dist/mmpd.d.ts +53 -0
- package/dist/mmpd.js +322 -0
- package/dist/sdo.d.ts +17 -0
- package/dist/sdo.js +219 -0
- package/dist/web-socket-connection.d.ts +70 -0
- package/dist/web-socket-connection.js +237 -0
- package/dist/wire-time.d.ts +2 -0
- package/dist/wire-time.js +18 -0
- package/package.json +29 -35
- package/.vscode/launch.json +0 -23
- package/README.md +0 -118
- package/box.config.json +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/motion-master-client-web-socket-connection.d.ts +0 -43
- package/dist/motion-master-client-web-socket-connection.d.ts.map +0 -1
- package/dist/motion-master-client-web-socket-connection.js +0 -91
- package/dist/motion-master-client-web-socket-connection.js.map +0 -1
- package/dist/motion-master-client.d.ts +0 -105
- package/dist/motion-master-client.d.ts.map +0 -1
- package/dist/motion-master-client.js +0 -348
- package/dist/motion-master-client.js.map +0 -1
- package/dist/motion-master-notification-subscribe-data.d.ts +0 -8
- package/dist/motion-master-notification-subscribe-data.d.ts.map +0 -1
- package/dist/motion-master-notification-subscribe-data.js +0 -3
- package/dist/motion-master-notification-subscribe-data.js.map +0 -1
- package/dist/motion-master-notification-web-socket-connection.d.ts +0 -56
- package/dist/motion-master-notification-web-socket-connection.d.ts.map +0 -1
- package/dist/motion-master-notification-web-socket-connection.js +0 -115
- package/dist/motion-master-notification-web-socket-connection.js.map +0 -1
- package/dist/motion-master-notification.d.ts +0 -31
- package/dist/motion-master-notification.d.ts.map +0 -1
- package/dist/motion-master-notification.js +0 -44
- package/dist/motion-master-notification.js.map +0 -1
- package/dist/util.d.ts +0 -16
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js +0 -24
- package/dist/util.js.map +0 -1
- package/licenses.format.json +0 -4
- package/motion-master-client.config.json +0 -7
- package/smm_data_dic.json +0 -1213
- package/src/index.ts +0 -7
- package/src/motion-master-client-web-socket-connection.ts +0 -104
- package/src/motion-master-client.ts +0 -468
- package/src/motion-master-notification-subscribe-data.ts +0 -7
- package/src/motion-master-notification-web-socket-connection.ts +0 -143
- package/src/motion-master-notification.ts +0 -51
- package/src/util.ts +0 -22
- package/test.sh +0 -122
- package/tsconfig.json +0 -63
- package/tslint.json +0 -118
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// Framework-agnostic connection to Motion Master's single WebSocket — the one bidirectional
|
|
2
|
+
// socket that carries server->client monitoring batches, notifications, and (planned) procedure
|
|
3
|
+
// progress, and client->server topic subscribe/unsubscribe. It owns reconnection, multiplexes
|
|
4
|
+
// per-topic subscriptions over the one socket (ref-counted: subscribe on the first listener,
|
|
5
|
+
// unsubscribe on the last, re-subscribe everything on reconnect), and routes inbound frames by
|
|
6
|
+
// type. Nothing arrives until something is subscribed: `subscribe(topic, cb)` for one monitoring's
|
|
7
|
+
// batches, `onNotification(cb)` for every server notification — the latter is one shared topic, so
|
|
8
|
+
// a single subscription covers events added in a later server version. It is isomorphic: the
|
|
9
|
+
// browser global `WebSocket` is used by default, and any compatible implementation (e.g. the Node
|
|
10
|
+
// `ws` package) can be injected — there is no hard dependency on either, so the package stays
|
|
11
|
+
// usable in both environments.
|
|
12
|
+
/// The numeric `readyState` value a WebSocket reports when it is open. Hard-coded (rather than read
|
|
13
|
+
/// off a global) so the client never depends on a particular `WebSocket` implementation's statics.
|
|
14
|
+
const WS_OPEN = 1;
|
|
15
|
+
/// The one topic every server notification is published to. One topic rather than one per event, so
|
|
16
|
+
/// a client subscribes once and keeps receiving events added in a later server version — uWebSockets
|
|
17
|
+
/// matches topic names exactly, with no wildcard, so there is no way to ask for "all of them".
|
|
18
|
+
/// Events are told apart by `data.event`, which is kebab-case.
|
|
19
|
+
export const NOTIFICATION_TOPIC = 'notifications';
|
|
20
|
+
export class WebSocketConnection {
|
|
21
|
+
url;
|
|
22
|
+
WebSocketImpl;
|
|
23
|
+
protocolsOrOptions;
|
|
24
|
+
reconnectDelayMs;
|
|
25
|
+
maxReconnectDelayMs;
|
|
26
|
+
socket = null;
|
|
27
|
+
state = 'closed';
|
|
28
|
+
closedByUser = false;
|
|
29
|
+
reconnectAttempts = 0;
|
|
30
|
+
reconnectTimer = null;
|
|
31
|
+
topicListeners = new Map();
|
|
32
|
+
notificationListeners = new Set();
|
|
33
|
+
progressListeners = new Set();
|
|
34
|
+
stateListeners = new Set();
|
|
35
|
+
constructor(options) {
|
|
36
|
+
this.url = options.url;
|
|
37
|
+
this.WebSocketImpl = options.WebSocket;
|
|
38
|
+
this.protocolsOrOptions = options.protocolsOrOptions;
|
|
39
|
+
this.reconnectDelayMs = options.reconnectDelayMs ?? 1000;
|
|
40
|
+
this.maxReconnectDelayMs = options.maxReconnectDelayMs ?? 15000;
|
|
41
|
+
}
|
|
42
|
+
get readyState() {
|
|
43
|
+
return this.state;
|
|
44
|
+
}
|
|
45
|
+
/// Opens the socket if it is not already open or connecting. Idempotent — safe to call from every
|
|
46
|
+
/// subscribe path. Connection is lazy: an HTTP-only consumer that never subscribes never opens a
|
|
47
|
+
/// socket.
|
|
48
|
+
connect() {
|
|
49
|
+
if (this.socket || this.state === 'connecting') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const Impl = this.WebSocketImpl ?? globalThis.WebSocket;
|
|
53
|
+
if (!Impl) {
|
|
54
|
+
throw new Error('No WebSocket implementation available. Inject one via the `WebSocket` option (e.g. the ' +
|
|
55
|
+
'`ws` package on Node < 22).');
|
|
56
|
+
}
|
|
57
|
+
this.closedByUser = false;
|
|
58
|
+
this.setState('connecting');
|
|
59
|
+
let socket;
|
|
60
|
+
try {
|
|
61
|
+
socket = new Impl(this.url, this.protocolsOrOptions);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
// A malformed URL (e.g. a bad host/port from stale saved settings) makes the WebSocket
|
|
65
|
+
// constructor throw synchronously. Report it as a failed connection and stay closed rather
|
|
66
|
+
// than letting it propagate and crash the caller; a bad URL won't fix itself, so there is no
|
|
67
|
+
// point scheduling a reconnect. The consumer observes 'closed' and can correct the endpoint.
|
|
68
|
+
this.setState('closed');
|
|
69
|
+
console.error(`WebSocketConnection: failed to open ${this.url}`, err);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.socket = socket;
|
|
73
|
+
socket.onopen = () => {
|
|
74
|
+
this.reconnectAttempts = 0;
|
|
75
|
+
this.setState('open');
|
|
76
|
+
// (Re)subscribe to every topic that currently has listeners — also covers reconnects.
|
|
77
|
+
for (const topic of this.topicListeners.keys()) {
|
|
78
|
+
this.send({ subscribe: topic });
|
|
79
|
+
}
|
|
80
|
+
if (this.notificationListeners.size > 0) {
|
|
81
|
+
this.send({ subscribe: NOTIFICATION_TOPIC });
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
socket.onmessage = (event) => this.route(event.data);
|
|
85
|
+
socket.onclose = () => this.handleDisconnect();
|
|
86
|
+
socket.onerror = () => this.handleDisconnect();
|
|
87
|
+
}
|
|
88
|
+
/// Permanently closes the socket and cancels any pending reconnect. Registered listeners are
|
|
89
|
+
/// kept, so a later `connect()` resumes them.
|
|
90
|
+
close() {
|
|
91
|
+
this.closedByUser = true;
|
|
92
|
+
if (this.reconnectTimer !== null) {
|
|
93
|
+
clearTimeout(this.reconnectTimer);
|
|
94
|
+
this.reconnectTimer = null;
|
|
95
|
+
}
|
|
96
|
+
const socket = this.socket;
|
|
97
|
+
this.socket = null;
|
|
98
|
+
if (socket) {
|
|
99
|
+
socket.onopen = null;
|
|
100
|
+
socket.onmessage = null;
|
|
101
|
+
socket.onclose = null;
|
|
102
|
+
socket.onerror = null;
|
|
103
|
+
socket.close();
|
|
104
|
+
}
|
|
105
|
+
this.setState('closed');
|
|
106
|
+
}
|
|
107
|
+
/// Subscribes `listener` to a topic's monitoring batches. The first subscriber to a topic sends a
|
|
108
|
+
/// `subscribe` frame; the last to leave sends `unsubscribe`. Connects lazily. Returns an
|
|
109
|
+
/// unsubscribe function.
|
|
110
|
+
subscribe(topic, listener) {
|
|
111
|
+
let listeners = this.topicListeners.get(topic);
|
|
112
|
+
if (!listeners) {
|
|
113
|
+
listeners = new Set();
|
|
114
|
+
this.topicListeners.set(topic, listeners);
|
|
115
|
+
this.send({ subscribe: topic });
|
|
116
|
+
}
|
|
117
|
+
listeners.add(listener);
|
|
118
|
+
this.connect();
|
|
119
|
+
return () => {
|
|
120
|
+
const current = this.topicListeners.get(topic);
|
|
121
|
+
if (!current) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
current.delete(listener);
|
|
125
|
+
if (current.size === 0) {
|
|
126
|
+
this.topicListeners.delete(topic);
|
|
127
|
+
this.send({ unsubscribe: topic });
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/// Registers a listener for server notifications (e.g. `{ event: 'short-working-counter' }`). Every
|
|
132
|
+
/// notification arrives on one topic, so the first listener subscribes and the last to leave
|
|
133
|
+
/// unsubscribes — the same ref-counting `subscribe` uses. Connects lazily. Returns a removal
|
|
134
|
+
/// function.
|
|
135
|
+
onNotification(listener) {
|
|
136
|
+
if (this.notificationListeners.size === 0) {
|
|
137
|
+
this.send({ subscribe: NOTIFICATION_TOPIC });
|
|
138
|
+
}
|
|
139
|
+
this.notificationListeners.add(listener);
|
|
140
|
+
this.connect();
|
|
141
|
+
return () => {
|
|
142
|
+
this.notificationListeners.delete(listener);
|
|
143
|
+
if (this.notificationListeners.size === 0) {
|
|
144
|
+
this.send({ unsubscribe: NOTIFICATION_TOPIC });
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/// Registers a listener for procedure progress messages (reserved; fires once the backend ships
|
|
149
|
+
/// them). Connects lazily. Returns a removal function.
|
|
150
|
+
onProgress(listener) {
|
|
151
|
+
this.progressListeners.add(listener);
|
|
152
|
+
this.connect();
|
|
153
|
+
return () => {
|
|
154
|
+
this.progressListeners.delete(listener);
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/// Observes connection-state changes. Returns a removal function.
|
|
158
|
+
onStateChange(listener) {
|
|
159
|
+
this.stateListeners.add(listener);
|
|
160
|
+
return () => {
|
|
161
|
+
this.stateListeners.delete(listener);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
setState(state) {
|
|
165
|
+
if (this.state === state) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.state = state;
|
|
169
|
+
for (const listener of this.stateListeners) {
|
|
170
|
+
listener(state);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
send(payload) {
|
|
174
|
+
const socket = this.socket;
|
|
175
|
+
if (socket && socket.readyState === WS_OPEN) {
|
|
176
|
+
socket.send(JSON.stringify(payload));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
handleDisconnect() {
|
|
180
|
+
if (this.socket) {
|
|
181
|
+
this.socket.onopen = null;
|
|
182
|
+
this.socket.onmessage = null;
|
|
183
|
+
this.socket.onclose = null;
|
|
184
|
+
this.socket.onerror = null;
|
|
185
|
+
this.socket = null;
|
|
186
|
+
}
|
|
187
|
+
this.setState('closed');
|
|
188
|
+
if (this.closedByUser || this.reconnectDelayMs <= 0) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const delay = Math.min(this.reconnectDelayMs * 2 ** this.reconnectAttempts, this.maxReconnectDelayMs);
|
|
192
|
+
this.reconnectAttempts += 1;
|
|
193
|
+
this.reconnectTimer = setTimeout(() => {
|
|
194
|
+
this.reconnectTimer = null;
|
|
195
|
+
this.connect();
|
|
196
|
+
}, delay);
|
|
197
|
+
}
|
|
198
|
+
route(raw) {
|
|
199
|
+
if (typeof raw !== 'string') {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
let msg;
|
|
203
|
+
try {
|
|
204
|
+
msg = JSON.parse(raw);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (!msg || typeof msg !== 'object') {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const { type } = msg;
|
|
213
|
+
if (type === 'monitoring') {
|
|
214
|
+
const { topic, data } = msg;
|
|
215
|
+
if (typeof topic === 'string' && Array.isArray(data)) {
|
|
216
|
+
const listeners = this.topicListeners.get(topic);
|
|
217
|
+
if (listeners) {
|
|
218
|
+
for (const listener of listeners) {
|
|
219
|
+
listener(data);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else if (type === 'notification') {
|
|
225
|
+
const { data } = msg;
|
|
226
|
+
for (const listener of this.notificationListeners) {
|
|
227
|
+
listener(data);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (type === 'progress') {
|
|
231
|
+
const { data } = msg;
|
|
232
|
+
for (const listener of this.progressListeners) {
|
|
233
|
+
listener(data);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Helper for the server-measured wire-time channel.
|
|
2
|
+
//
|
|
3
|
+
// Endpoints that perform a fieldbus transaction (SDO, FoE, ...) report the on-device wire cost —
|
|
4
|
+
// control-plane lock acquire + the mailbox/ESC round-trip — via the `X-Wire-Us` response header
|
|
5
|
+
// (microseconds), independent of the response body shape. A cross-origin client subtracts this
|
|
6
|
+
// from its own observed HTTP round-trip to separate the device cost from browser/transport
|
|
7
|
+
// overhead. The header is CORS-exposed by the server so it is readable cross-origin.
|
|
8
|
+
// Name of the wire-time response header (microseconds, integer).
|
|
9
|
+
export const WIRE_TIME_HEADER = 'X-Wire-Us';
|
|
10
|
+
// Reads the server-measured wire time from a response, in milliseconds, or null if the header is
|
|
11
|
+
// absent or unparseable. Accepts any `Response` (the generated client's `HttpResponse` extends it).
|
|
12
|
+
export function wireTimeMs(res) {
|
|
13
|
+
const raw = res.headers.get(WIRE_TIME_HEADER);
|
|
14
|
+
if (raw === null)
|
|
15
|
+
return null;
|
|
16
|
+
const us = Number(raw);
|
|
17
|
+
return Number.isFinite(us) ? us / 1000 : null;
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,44 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapticon/motion-master-client",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
3
|
+
"version": "6.0.0-alpha.110",
|
|
4
|
+
"description": "Isomorphic TypeScript client for Motion Master: the generated HTTP API client, the WebSocket connection, and helpers.",
|
|
5
|
+
"license": "MIT",
|
|
8
6
|
"repository": {
|
|
9
7
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/synapticon/motion-master
|
|
8
|
+
"url": "git+https://github.com/synapticon/motion-master.git",
|
|
9
|
+
"directory": "web/packages/motion-master-client"
|
|
11
10
|
},
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
11
|
+
"homepage": "https://github.com/synapticon/motion-master#readme",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
18
22
|
},
|
|
19
|
-
"
|
|
20
|
-
"
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"swagger-typescript-api": "^13.7.2",
|
|
25
|
+
"typescript": "^5.6.0"
|
|
21
26
|
},
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"@synapticon/motion-master-proto": "^5.2.2",
|
|
26
|
-
"commander": "^6.1.0",
|
|
27
|
-
"debug": "^4.1.1",
|
|
28
|
-
"lodash": "^4.17.20",
|
|
29
|
-
"long": "^4.0.0",
|
|
30
|
-
"rxjs": "^6.6.3",
|
|
31
|
-
"uuid": "^8.3.0",
|
|
32
|
-
"yaml": "^1.10.0"
|
|
27
|
+
"scripts": {
|
|
28
|
+
"generate": "swagger-typescript-api generate -p ../../../apps/motion_master/swagger.yml -o ./src/generated -n api.ts --modular",
|
|
29
|
+
"build": "tsc -p tsconfig.build.json && node scripts/fix-esm-imports.mjs"
|
|
33
30
|
},
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"license-checker": "^25.0.1",
|
|
41
|
-
"tslint": "^6.1.3",
|
|
42
|
-
"typescript": "^3.9.7"
|
|
31
|
+
"module": "./dist/index.js",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js"
|
|
36
|
+
}
|
|
43
37
|
}
|
|
44
|
-
}
|
|
38
|
+
}
|
package/.vscode/launch.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Use IntelliSense to learn about possible attributes.
|
|
3
|
-
// Hover to view descriptions of existing attributes.
|
|
4
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
-
"version": "0.2.0",
|
|
6
|
-
"configurations": [
|
|
7
|
-
{
|
|
8
|
-
"type": "node",
|
|
9
|
-
"request": "launch",
|
|
10
|
-
"name": "Upload 0x1000:0 for device at position 0",
|
|
11
|
-
"program": "${workspaceFolder}/dist/cli.js",
|
|
12
|
-
"args": [
|
|
13
|
-
"-p",
|
|
14
|
-
"0",
|
|
15
|
-
"upload",
|
|
16
|
-
"0x1000:0",
|
|
17
|
-
],
|
|
18
|
-
"outFiles": [
|
|
19
|
-
"${workspaceFolder}/**/*.js"
|
|
20
|
-
]
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
}
|
package/README.md
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# Motion Master Client
|
|
2
|
-
|
|
3
|
-
Library and CLI tool for interacting with [Motion Master](https://github.com/synapticon/motion-master).
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
sudo npm --unsafe-perm=true install -g @synapticon/motion-master-client
|
|
8
|
-
|
|
9
|
-
## Command line usage
|
|
10
|
-
|
|
11
|
-
See the examples in [test.sh](test.sh).
|
|
12
|
-
|
|
13
|
-
Usage: cli [options] [command]
|
|
14
|
-
|
|
15
|
-
Options:
|
|
16
|
-
-V, --version output the version number
|
|
17
|
-
-c, --config <path> path to JSON config file to read and replace the default values with
|
|
18
|
-
-d, --device-address <address> device address (uint32) generated by Motion Master - takes precedence over
|
|
19
|
-
device position
|
|
20
|
-
-f, --output-format <json|yaml> if left unspecified the output format is the default colored message
|
|
21
|
-
inspect
|
|
22
|
-
-p, --device-position <position> used when device address is not specified (default: 0)
|
|
23
|
-
-h, --help display help for command
|
|
24
|
-
|
|
25
|
-
Commands:
|
|
26
|
-
request [options] <type> [args...]
|
|
27
|
-
upload [options] [params...]
|
|
28
|
-
download [paramValues...]
|
|
29
|
-
getDeviceFileContent <filename>
|
|
30
|
-
getDeviceLogContent
|
|
31
|
-
getCoggingTorqueDataContent
|
|
32
|
-
startCoggingTorqueRecording [options]
|
|
33
|
-
startOffsetDetection
|
|
34
|
-
startPlantIdentification <durationSeconds> <torqueAmplitude> <startFrequency> <endFrequency> <cutoffFrequency>
|
|
35
|
-
startSystemIdentification <durationSeconds> <torqueAmplitude> <startFrequency> <endFrequency>
|
|
36
|
-
startCirculoEncoderNarrowAngleCalibrationProcedure <encoderOrdinal>
|
|
37
|
-
monitor [options] <topic> [params...]
|
|
38
|
-
help [command] display help for command
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
### request
|
|
42
|
-
|
|
43
|
-
Usage: cli request [options] <type> [args...]
|
|
44
|
-
|
|
45
|
-
Options:
|
|
46
|
-
-i, --interval <value> sending interval in microseconds (default: 1000000)
|
|
47
|
-
-h, --help display help for command
|
|
48
|
-
|
|
49
|
-
Request <type>s:
|
|
50
|
-
pingSystem
|
|
51
|
-
getSystemVersion
|
|
52
|
-
getDeviceInfo
|
|
53
|
-
getDeviceParameterInfo
|
|
54
|
-
getDeviceParameterValues
|
|
55
|
-
getMultiDeviceParameterValues
|
|
56
|
-
setDeviceParameterValues
|
|
57
|
-
setMultiDeviceParameterValues
|
|
58
|
-
getDeviceFileList
|
|
59
|
-
getDeviceFile
|
|
60
|
-
setDeviceFile
|
|
61
|
-
deleteDeviceFile
|
|
62
|
-
resetDeviceFault
|
|
63
|
-
stopDevice
|
|
64
|
-
startDeviceFirmwareInstallation
|
|
65
|
-
getDeviceLog
|
|
66
|
-
startCoggingTorqueRecording
|
|
67
|
-
getCoggingTorqueData
|
|
68
|
-
startOffsetDetection
|
|
69
|
-
startPlantIdentification
|
|
70
|
-
startSystemIdentification
|
|
71
|
-
computeAutoTuningGains
|
|
72
|
-
setMotionControllerParameters
|
|
73
|
-
enableMotionController
|
|
74
|
-
disableMotionController
|
|
75
|
-
setSignalGeneratorParameters
|
|
76
|
-
startSignalGenerator
|
|
77
|
-
stopSignalGenerator
|
|
78
|
-
startMonitoringDeviceParameterValues
|
|
79
|
-
stopMonitoringDeviceParameterValues
|
|
80
|
-
getEthercatNetworkState
|
|
81
|
-
setEthercatNetworkState
|
|
82
|
-
startNarrowAngleCalibration
|
|
83
|
-
setSystemClientTimeout
|
|
84
|
-
getCirculoEncoderMagnetDistance
|
|
85
|
-
startCirculoEncoderNarrowAngleCalibrationProcedure
|
|
86
|
-
getDeviceCiA402State
|
|
87
|
-
setDeviceCiA402State
|
|
88
|
-
getSystemLog
|
|
89
|
-
startDeviceSiiRestore
|
|
90
|
-
startOpenLoopFieldControl
|
|
91
|
-
computeFullAutoTuningGains
|
|
92
|
-
startFullAutoTuning
|
|
93
|
-
stopFullAutoTuning
|
|
94
|
-
startCirculoEncoderConfiguration
|
|
95
|
-
stopCirculoEncoderNarrowAngleCalibrationProcedure
|
|
96
|
-
startOsCommand
|
|
97
|
-
|
|
98
|
-
### monitor
|
|
99
|
-
|
|
100
|
-
Usage: monitor [options] <topic> [params...]
|
|
101
|
-
|
|
102
|
-
Options:
|
|
103
|
-
-i, --interval <value> sending interval in microseconds (default: 1000000)
|
|
104
|
-
-h, --help output usage information
|
|
105
|
-
|
|
106
|
-
## Library usage
|
|
107
|
-
|
|
108
|
-
const input = new rxjs.Subject<Buffer>();
|
|
109
|
-
const output = new rxjs.Subject<Buffer>();
|
|
110
|
-
const motionMasterClient = new MotionMasterClient(input, output);
|
|
111
|
-
const messageId = v4(); // '4e4d938e-1021-4b68-ad01-38c7ed2c5ee4'
|
|
112
|
-
const getSystemVersion: motionmaster.MotionMasterMessage.Request.IGetSystemVersion = {};
|
|
113
|
-
motionMasterClient.sendRequest({ getSystemVersion }, messageId);
|
|
114
|
-
motionMasterClient.systemVersion$.subscribe(console.log);
|
|
115
|
-
|
|
116
|
-
## Publish
|
|
117
|
-
|
|
118
|
-
npm publish --access=public
|
package/box.config.json
DELETED
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qCAAqC,EAAE,MAAM,8CAA8C,CAAC;AACrG,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,sCAAsC,EAAE,MAAM,6CAA6C,CAAC;AACrG,OAAO,EAAE,2CAA2C,EAAE,MAAM,oDAAoD,CAAC;AACjH,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,cAAc,QAAQ,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2GAAqG;AAA5F,mKAAA,qCAAqC,OAAA;AAC9C,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA;AAE3B,uHAAiH;AAAxG,+KAAA,2CAA2C,OAAA;AACpD,2EAAwE;AAA/D,sIAAA,wBAAwB,OAAA;AAEjC,yCAAuB"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { BehaviorSubject, Observable } from 'rxjs';
|
|
2
|
-
import { WebSocketSubject } from 'rxjs/webSocket';
|
|
3
|
-
import { MotionMasterClient } from './motion-master-client';
|
|
4
|
-
import { MotionMasterMessage } from './util';
|
|
5
|
-
export declare class MotionMasterClientWebSocketConnection {
|
|
6
|
-
wssUrl: string;
|
|
7
|
-
pingSystemPeriod: number;
|
|
8
|
-
aliveTimeout: number;
|
|
9
|
-
/**
|
|
10
|
-
* An instance of MotionMasterClient bound to this WebSocket connection.
|
|
11
|
-
*/
|
|
12
|
-
readonly client: MotionMasterClient;
|
|
13
|
-
/**
|
|
14
|
-
* Emits a boolean value when connection gets opened or closed.
|
|
15
|
-
*/
|
|
16
|
-
readonly connected$: BehaviorSubject<boolean>;
|
|
17
|
-
/**
|
|
18
|
-
* Emits a boolean value when Motion Master is considered alive. True when messages are received
|
|
19
|
-
* in regular interval, or false when alive timeout expires.
|
|
20
|
-
*/
|
|
21
|
-
readonly alive$: BehaviorSubject<boolean>;
|
|
22
|
-
private pingSystemIntervalObserver;
|
|
23
|
-
private pingSystemIntervalSubscription;
|
|
24
|
-
private aliveTimeoutId;
|
|
25
|
-
private closeObserver;
|
|
26
|
-
private openObserver;
|
|
27
|
-
private wssConfig;
|
|
28
|
-
readonly wss$: WebSocketSubject<Uint8Array>;
|
|
29
|
-
readonly message$: Observable<MotionMasterMessage>;
|
|
30
|
-
private messageSubscription;
|
|
31
|
-
private clientOutputSubscription;
|
|
32
|
-
/**
|
|
33
|
-
* MotionMasterClientWebSocketConnection constructor.
|
|
34
|
-
* @param wssUrl Motion Master Bridge WebSocket client URL.
|
|
35
|
-
* @param pingSystemPeriod timeframe in which to send ping system message to Motion Master.
|
|
36
|
-
* @param aliveTimeout how long to wait for Motion Master message before emitting it's not alive.
|
|
37
|
-
*/
|
|
38
|
-
constructor(wssUrl?: string, pingSystemPeriod?: number, aliveTimeout?: number);
|
|
39
|
-
close(): void;
|
|
40
|
-
open(): void;
|
|
41
|
-
private keepalive;
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=motion-master-client-web-socket-connection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"motion-master-client-web-socket-connection.d.ts","sourceRoot":"","sources":["../src/motion-master-client-web-socket-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAY,UAAU,EAAgB,MAAM,MAAM,CAAC;AAE3E,OAAO,EAAa,gBAAgB,EAA0B,MAAM,gBAAgB,CAAC;AAErF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAE7C,qBAAa,qCAAqC;IAiEvC,MAAM;IACN,gBAAgB;IAChB,YAAY;IAjErB;;OAEG;IACH,QAAQ,CAAC,MAAM,qBAA4B;IAE3C;;OAEG;IACH,QAAQ,CAAC,UAAU,2BAAuC;IAE1D;;;OAGG;IACH,QAAQ,CAAC,MAAM,2BAAuC;IAEtD,OAAO,CAAC,0BAA0B,CAAmD;IAErF,OAAO,CAAC,8BAA8B,CAAsB;IAE5D,OAAO,CAAC,cAAc,CAAK;IAE3B,OAAO,CAAC,aAAa,CAOnB;IAEF,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,SAAS,CAOf;IAEF,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAA6B;IAExE,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAEhD;IAEF,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,wBAAwB,CAAsB;IAEtD;;;;;OAKG;gBAEM,MAAM,SAAoC,EAC1C,gBAAgB,SAAM,EACtB,YAAY,SAAO;IAG5B,KAAK;IAKL,IAAI;IAaJ,OAAO,CAAC,SAAS;CAQlB"}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MotionMasterClientWebSocketConnection = void 0;
|
|
4
|
-
var rxjs_1 = require("rxjs");
|
|
5
|
-
var operators_1 = require("rxjs/operators");
|
|
6
|
-
var webSocket_1 = require("rxjs/webSocket");
|
|
7
|
-
var motion_master_client_1 = require("./motion-master-client");
|
|
8
|
-
var util_1 = require("./util");
|
|
9
|
-
var MotionMasterClientWebSocketConnection = /** @class */ (function () {
|
|
10
|
-
/**
|
|
11
|
-
* MotionMasterClientWebSocketConnection constructor.
|
|
12
|
-
* @param wssUrl Motion Master Bridge WebSocket client URL.
|
|
13
|
-
* @param pingSystemPeriod timeframe in which to send ping system message to Motion Master.
|
|
14
|
-
* @param aliveTimeout how long to wait for Motion Master message before emitting it's not alive.
|
|
15
|
-
*/
|
|
16
|
-
function MotionMasterClientWebSocketConnection(wssUrl, pingSystemPeriod, aliveTimeout) {
|
|
17
|
-
var _this = this;
|
|
18
|
-
if (wssUrl === void 0) { wssUrl = "ws://" + location.hostname + ":63524"; }
|
|
19
|
-
if (pingSystemPeriod === void 0) { pingSystemPeriod = 150; }
|
|
20
|
-
if (aliveTimeout === void 0) { aliveTimeout = 1000; }
|
|
21
|
-
this.wssUrl = wssUrl;
|
|
22
|
-
this.pingSystemPeriod = pingSystemPeriod;
|
|
23
|
-
this.aliveTimeout = aliveTimeout;
|
|
24
|
-
/**
|
|
25
|
-
* An instance of MotionMasterClient bound to this WebSocket connection.
|
|
26
|
-
*/
|
|
27
|
-
this.client = new motion_master_client_1.MotionMasterClient();
|
|
28
|
-
/**
|
|
29
|
-
* Emits a boolean value when connection gets opened or closed.
|
|
30
|
-
*/
|
|
31
|
-
this.connected$ = new rxjs_1.BehaviorSubject(false);
|
|
32
|
-
/**
|
|
33
|
-
* Emits a boolean value when Motion Master is considered alive. True when messages are received
|
|
34
|
-
* in regular interval, or false when alive timeout expires.
|
|
35
|
-
*/
|
|
36
|
-
this.alive$ = new rxjs_1.BehaviorSubject(false);
|
|
37
|
-
this.pingSystemIntervalObserver = { next: function () { return _this.client.requestPingSystem(); } };
|
|
38
|
-
this.pingSystemIntervalSubscription = new rxjs_1.Subscription();
|
|
39
|
-
this.aliveTimeoutId = 0;
|
|
40
|
-
this.closeObserver = {
|
|
41
|
-
next: function () {
|
|
42
|
-
_this.pingSystemIntervalSubscription.unsubscribe();
|
|
43
|
-
_this.connected$.next(false);
|
|
44
|
-
self.clearTimeout(_this.aliveTimeoutId);
|
|
45
|
-
_this.alive$.next(false);
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
this.openObserver = {
|
|
49
|
-
next: function () {
|
|
50
|
-
_this.pingSystemIntervalSubscription = rxjs_1.interval(_this.pingSystemPeriod).subscribe(_this.pingSystemIntervalObserver);
|
|
51
|
-
_this.connected$.next(true);
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
this.wssConfig = {
|
|
55
|
-
binaryType: 'arraybuffer',
|
|
56
|
-
closeObserver: this.closeObserver,
|
|
57
|
-
deserializer: function (e) { return new Uint8Array(e.data); },
|
|
58
|
-
openObserver: this.openObserver,
|
|
59
|
-
serializer: function (value) { return value; },
|
|
60
|
-
url: this.wssUrl,
|
|
61
|
-
};
|
|
62
|
-
this.wss$ = webSocket_1.webSocket(this.wssConfig);
|
|
63
|
-
this.message$ = this.wss$.pipe(operators_1.map(function (data) { return util_1.MotionMasterMessage.decode(data); }));
|
|
64
|
-
this.messageSubscription = new rxjs_1.Subscription();
|
|
65
|
-
this.clientOutputSubscription = new rxjs_1.Subscription();
|
|
66
|
-
}
|
|
67
|
-
MotionMasterClientWebSocketConnection.prototype.close = function () {
|
|
68
|
-
this.messageSubscription.unsubscribe();
|
|
69
|
-
this.clientOutputSubscription.unsubscribe();
|
|
70
|
-
};
|
|
71
|
-
MotionMasterClientWebSocketConnection.prototype.open = function () {
|
|
72
|
-
var _this = this;
|
|
73
|
-
this.messageSubscription = this.message$.pipe(operators_1.tap(function () { return _this.keepalive(); }), operators_1.filter(function (message) { return message && message.status ? !message.status.systemPong : false; })).subscribe(function (message) {
|
|
74
|
-
_this.client.input$.next(message);
|
|
75
|
-
});
|
|
76
|
-
this.clientOutputSubscription = this.client.output$.subscribe(function (message) {
|
|
77
|
-
_this.wss$.next(util_1.MotionMasterMessage.encode(message).finish());
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
|
-
MotionMasterClientWebSocketConnection.prototype.keepalive = function () {
|
|
81
|
-
var _this = this;
|
|
82
|
-
if (this.alive$.getValue() === false) {
|
|
83
|
-
this.alive$.next(true);
|
|
84
|
-
}
|
|
85
|
-
self.clearTimeout(this.aliveTimeoutId);
|
|
86
|
-
this.aliveTimeoutId = self.setTimeout(function () { return _this.alive$.next(false); }, this.aliveTimeout);
|
|
87
|
-
};
|
|
88
|
-
return MotionMasterClientWebSocketConnection;
|
|
89
|
-
}());
|
|
90
|
-
exports.MotionMasterClientWebSocketConnection = MotionMasterClientWebSocketConnection;
|
|
91
|
-
//# sourceMappingURL=motion-master-client-web-socket-connection.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"motion-master-client-web-socket-connection.js","sourceRoot":"","sources":["../src/motion-master-client-web-socket-connection.ts"],"names":[],"mappings":"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"}
|