motion-master-client 0.0.76 → 0.0.85

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 (85) hide show
  1. package/README.md +227 -138
  2. package/package.json +1 -1
  3. package/src/cli.d.ts +1 -1
  4. package/src/cli.js +160 -160
  5. package/src/index.d.ts +30 -28
  6. package/src/index.js +33 -31
  7. package/src/index.js.map +1 -1
  8. package/src/lib/cia402.d.ts +184 -182
  9. package/src/lib/cia402.js +393 -391
  10. package/src/lib/cia402.js.map +1 -1
  11. package/src/lib/config-file.d.ts +13 -13
  12. package/src/lib/config-file.js +49 -49
  13. package/src/lib/data-monitoring.d.ts +12 -12
  14. package/src/lib/data-monitoring.js +33 -33
  15. package/src/lib/device-log-line.d.ts +5 -5
  16. package/src/lib/device-log-line.js +2 -2
  17. package/src/lib/device-parameter.d.ts +56 -56
  18. package/src/lib/device-parameter.js +38 -38
  19. package/src/lib/device.d.ts +46 -9
  20. package/src/lib/device.js +166 -2
  21. package/src/lib/device.js.map +1 -1
  22. package/src/lib/encoder-register.d.ts +16 -16
  23. package/src/lib/encoder-register.js +116 -116
  24. package/src/lib/hardware-description.d.ts +46 -46
  25. package/src/lib/hardware-description.js +109 -109
  26. package/src/lib/integro-encoder-calibration.d.ts +31 -0
  27. package/src/lib/integro-encoder-calibration.js +196 -0
  28. package/src/lib/integro-encoder-calibration.js.map +1 -0
  29. package/src/lib/logger.d.ts +1 -1
  30. package/src/lib/logger.js +7 -7
  31. package/src/lib/monitoring-config.d.ts +31 -31
  32. package/src/lib/monitoring-config.js +2 -2
  33. package/src/lib/monitoring-entry.d.ts +9 -9
  34. package/src/lib/monitoring-entry.js +2 -2
  35. package/src/lib/motion-master-client.d.ts +77 -77
  36. package/src/lib/motion-master-client.js +196 -196
  37. package/src/lib/motion-master-pub-sub-client.d.ts +17 -17
  38. package/src/lib/motion-master-pub-sub-client.js +72 -72
  39. package/src/lib/motion-master-pub-sub-client.js.map +1 -1
  40. package/src/lib/motion-master-pub-sub-socket.d.ts +42 -42
  41. package/src/lib/motion-master-pub-sub-socket.js +2 -2
  42. package/src/lib/motion-master-pub-sub-web-socket.d.ts +18 -18
  43. package/src/lib/motion-master-pub-sub-web-socket.js +65 -65
  44. package/src/lib/motion-master-pub-sub-worker-socket.d.ts +18 -18
  45. package/src/lib/motion-master-pub-sub-worker-socket.js +47 -47
  46. package/src/lib/motion-master-req-res-client.d.ts +1104 -1062
  47. package/src/lib/motion-master-req-res-client.js +2137 -1992
  48. package/src/lib/motion-master-req-res-client.js.map +1 -1
  49. package/src/lib/motion-master-req-res-socket.d.ts +60 -60
  50. package/src/lib/motion-master-req-res-socket.js +2 -2
  51. package/src/lib/motion-master-req-res-web-socket.d.ts +28 -28
  52. package/src/lib/motion-master-req-res-web-socket.js +97 -97
  53. package/src/lib/motion-master-req-res-worker-socket.d.ts +24 -24
  54. package/src/lib/motion-master-req-res-worker-socket.js +71 -71
  55. package/src/lib/motion-master.proto.d.ts +5183 -5183
  56. package/src/lib/motion-master.proto.js +53218 -53218
  57. package/src/lib/operators.d.ts +20 -20
  58. package/src/lib/operators.js +82 -83
  59. package/src/lib/operators.js.map +1 -1
  60. package/src/lib/options.d.ts +10 -10
  61. package/src/lib/options.js +13 -13
  62. package/src/lib/os-command.d.ts +387 -173
  63. package/src/lib/os-command.js +555 -269
  64. package/src/lib/os-command.js.map +1 -1
  65. package/src/lib/parameter.d.ts +156 -138
  66. package/src/lib/parameter.js +377 -152
  67. package/src/lib/parameter.js.map +1 -1
  68. package/src/lib/product-id-range.d.ts +7 -7
  69. package/src/lib/product-id-range.js +11 -11
  70. package/src/lib/request-status-resolver.d.ts +4 -4
  71. package/src/lib/request-status-resolver.js +344 -344
  72. package/src/lib/somanet-product.d.ts +37 -0
  73. package/src/lib/somanet-product.js +126 -0
  74. package/src/lib/somanet-product.js.map +1 -0
  75. package/src/lib/system-log-line.d.ts +9 -9
  76. package/src/lib/system-log-line.js +2 -2
  77. package/src/lib/types.d.ts +141 -141
  78. package/src/lib/types.js +28 -28
  79. package/src/lib/urls.d.ts +3 -3
  80. package/src/lib/urls.js +9 -9
  81. package/src/lib/util.d.ts +21 -45
  82. package/src/lib/util.js +113 -379
  83. package/src/lib/util.js.map +1 -1
  84. package/src/lib/web-socket-connection-close-codes.d.ts +8 -8
  85. package/src/lib/web-socket-connection-close-codes.js +88 -88
@@ -1,77 +1,77 @@
1
- import { Observable } from "rxjs";
2
- import { MonitoringConfig } from "./monitoring-config";
3
- import { MotionMasterPubSubClient } from "./motion-master-pub-sub-client";
4
- import { MotionMasterPubSubSocket } from "./motion-master-pub-sub-socket";
5
- import { MotionMasterReqResClient } from "./motion-master-req-res-client";
6
- import { MotionMasterReqResSocket } from "./motion-master-req-res-socket";
7
- import { DeviceParameterIds, DeviceRef, ParameterValueType } from "./types";
8
- import { DeviceParameter } from "./device-parameter";
9
- export declare function createMotionMasterClient(hostname: string): MotionMasterClient;
10
- export declare class MotionMasterClient {
11
- readonly reqResSocket: MotionMasterReqResSocket;
12
- readonly pubSubSocket: MotionMasterPubSubSocket;
13
- readonly request: MotionMasterReqResClient;
14
- readonly monitor: MotionMasterPubSubClient;
15
- private systemEventSubscription?;
16
- constructor(reqResSocket: MotionMasterReqResSocket, pubSubSocket: MotionMasterPubSubSocket);
17
- /**
18
- * This observable will emit true when both req/res and pub/sub sockets are opened.
19
- * If any socket gets closed, this observable will emit false.
20
- * This is a hot observable that will on subscription emit the last value of sockets opened.
21
- */
22
- socketsOpened$: Observable<boolean>;
23
- /**
24
- * Client is ready when both req/res and pub/sub sockets are opened.
25
- * This observable will emit whenever the sockets opened property changes to true.
26
- */
27
- ready$: Observable<true>;
28
- /**
29
- * This observable will emit only once when both req/res and pub/sub sockets are opened.
30
- * NOTE: This observable might never emit and it doesn't timeout.
31
- */
32
- onceReady$: Observable<true>;
33
- /**
34
- * Client is ready when both req/res and pub/sub sockets are opened.
35
- * If both sockets are already opened, this function will immediately resolve to true.
36
- * Otherwise, it will wait up to requestTimeout for both sockets to open, or throw an error.
37
- */
38
- whenReady(requestTimeout?: number): Promise<true>;
39
- /**
40
- * Start monitoring.
41
- *
42
- * Note that the returned observable will never complete on its own.
43
- *
44
- * If you unsubscribe from it, the teardown code will send a request to the master to stop the monitoring.
45
- * That means you will end up with an observable that is not complete, but it won't emit any values.
46
- * This is fine when you want to use the monitoring observable directly in the template with async pipe,
47
- * which will unsubscribe automatically and stop the monitoring when you leave the component.
48
- *
49
- * If you need to complete the observable so that, for example, the toArray() operator works as expected, then use the {@link DataMonitoring} class,
50
- * which has a stop method. It can optionally buffer data for exporting as CSV or performing statistics on it.
51
- *
52
- * @param ids Device parameter IDs to monitor.
53
- * @param monitoringInterval At what interval should the master application send values.
54
- * @param config Configure the topic, buffer size, distinct.
55
- * @param requestTimeout How long will the client wait for the master to confirm that monitoring has started.
56
- * @returns An observable of an array of parameter values.
57
- */
58
- startMonitoring(ids: DeviceParameterIds, monitoringInterval: number, config?: MonitoringConfig, requestTimeout?: number): Observable<ParameterValueType[]>;
59
- /**
60
- * TODO: return device parameters instead of just parameters
61
- * get parameters from ESI uprfront, and then when parameters are received
62
- * from motion master just concatenate (spread operator) props from ESI and props from parameter
63
- * assign device parameter id like 0x1018:00.12345
64
- * when assembling device parameter, get parameter from device in ESI based on product code, see ESI service
65
- * this should probably done for other get parameters functions, get ESI file from device or prepared, get data from it
66
- */
67
- startMonitoringDeviceParameters(ids: DeviceParameterIds, monitoringInterval: number, config?: MonitoringConfig, requestTimeout?: number): Observable<DeviceParameter[]>;
68
- startMonitoringValue<T extends ParameterValueType = number>(id: string | [DeviceRef, number, number], monitoringInterval: number, config?: MonitoringConfig, requestTimeout?: number): Observable<T>;
69
- trackTargetReached(deviceRef: DeviceRef, monitoringInterval?: number): Observable<boolean>;
70
- waitUntilTargetReached(deviceRef: DeviceRef, monitoringInterval?: number): Observable<true>;
71
- whenTargetReached(deviceRef: DeviceRef, monitoringInterval?: number): Promise<true>;
72
- subscribeToSystemEvent(): void;
73
- stopMonitoring(messageId: string): void;
74
- stopMonitoringAll(): void;
75
- closeSockets(): void;
76
- reopenSockets(): void;
77
- }
1
+ import { Observable } from "rxjs";
2
+ import { MonitoringConfig } from "./monitoring-config";
3
+ import { MotionMasterPubSubClient } from "./motion-master-pub-sub-client";
4
+ import { MotionMasterPubSubSocket } from "./motion-master-pub-sub-socket";
5
+ import { MotionMasterReqResClient } from "./motion-master-req-res-client";
6
+ import { MotionMasterReqResSocket } from "./motion-master-req-res-socket";
7
+ import { DeviceParameterIds, DeviceRef, ParameterValueType } from "./types";
8
+ import { DeviceParameter } from "./device-parameter";
9
+ export declare function createMotionMasterClient(hostname: string): MotionMasterClient;
10
+ export declare class MotionMasterClient {
11
+ readonly reqResSocket: MotionMasterReqResSocket;
12
+ readonly pubSubSocket: MotionMasterPubSubSocket;
13
+ readonly request: MotionMasterReqResClient;
14
+ readonly monitor: MotionMasterPubSubClient;
15
+ private systemEventSubscription?;
16
+ constructor(reqResSocket: MotionMasterReqResSocket, pubSubSocket: MotionMasterPubSubSocket);
17
+ /**
18
+ * This observable will emit true when both req/res and pub/sub sockets are opened.
19
+ * If any socket gets closed, this observable will emit false.
20
+ * This is a hot observable that will on subscription emit the last value of sockets opened.
21
+ */
22
+ socketsOpened$: Observable<boolean>;
23
+ /**
24
+ * Client is ready when both req/res and pub/sub sockets are opened.
25
+ * This observable will emit whenever the sockets opened property changes to true.
26
+ */
27
+ ready$: Observable<true>;
28
+ /**
29
+ * This observable will emit only once when both req/res and pub/sub sockets are opened.
30
+ * NOTE: This observable might never emit and it doesn't timeout.
31
+ */
32
+ onceReady$: Observable<true>;
33
+ /**
34
+ * Client is ready when both req/res and pub/sub sockets are opened.
35
+ * If both sockets are already opened, this function will immediately resolve to true.
36
+ * Otherwise, it will wait up to requestTimeout for both sockets to open, or throw an error.
37
+ */
38
+ whenReady(requestTimeout?: number): Promise<true>;
39
+ /**
40
+ * Start monitoring.
41
+ *
42
+ * Note that the returned observable will never complete on its own.
43
+ *
44
+ * If you unsubscribe from it, the teardown code will send a request to the master to stop the monitoring.
45
+ * That means you will end up with an observable that is not complete, but it won't emit any values.
46
+ * This is fine when you want to use the monitoring observable directly in the template with async pipe,
47
+ * which will unsubscribe automatically and stop the monitoring when you leave the component.
48
+ *
49
+ * If you need to complete the observable so that, for example, the toArray() operator works as expected, then use the {@link DataMonitoring} class,
50
+ * which has a stop method. It can optionally buffer data for exporting as CSV or performing statistics on it.
51
+ *
52
+ * @param ids Device parameter IDs to monitor.
53
+ * @param monitoringInterval At what interval should the master application send values.
54
+ * @param config Configure the topic, buffer size, distinct.
55
+ * @param requestTimeout How long will the client wait for the master to confirm that monitoring has started.
56
+ * @returns An observable of an array of parameter values.
57
+ */
58
+ startMonitoring(ids: DeviceParameterIds, monitoringInterval: number, config?: MonitoringConfig, requestTimeout?: number): Observable<ParameterValueType[]>;
59
+ /**
60
+ * TODO: return device parameters instead of just parameters
61
+ * get parameters from ESI uprfront, and then when parameters are received
62
+ * from motion master just concatenate (spread operator) props from ESI and props from parameter
63
+ * assign device parameter id like 0x1018:00.12345
64
+ * when assembling device parameter, get parameter from device in ESI based on product code, see ESI service
65
+ * this should probably done for other get parameters functions, get ESI file from device or prepared, get data from it
66
+ */
67
+ startMonitoringDeviceParameters(ids: DeviceParameterIds, monitoringInterval: number, config?: MonitoringConfig, requestTimeout?: number): Observable<DeviceParameter[]>;
68
+ startMonitoringValue<T extends ParameterValueType = number>(id: string | [DeviceRef, number, number], monitoringInterval: number, config?: MonitoringConfig, requestTimeout?: number): Observable<T>;
69
+ trackTargetReached(deviceRef: DeviceRef, monitoringInterval?: number): Observable<boolean>;
70
+ waitUntilTargetReached(deviceRef: DeviceRef, monitoringInterval?: number): Observable<true>;
71
+ whenTargetReached(deviceRef: DeviceRef, monitoringInterval?: number): Promise<true>;
72
+ subscribeToSystemEvent(): void;
73
+ stopMonitoring(messageId: string): void;
74
+ stopMonitoringAll(): void;
75
+ closeSockets(): void;
76
+ reopenSockets(): void;
77
+ }
@@ -1,197 +1,197 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MotionMasterClient = exports.createMotionMasterClient = void 0;
4
- const rxjs_1 = require("rxjs");
5
- const uuid_1 = require("uuid");
6
- const motion_master_pub_sub_client_1 = require("./motion-master-pub-sub-client");
7
- const motion_master_pub_sub_web_socket_1 = require("./motion-master-pub-sub-web-socket");
8
- const motion_master_req_res_client_1 = require("./motion-master-req-res-client");
9
- const motion_master_req_res_web_socket_1 = require("./motion-master-req-res-web-socket");
10
- const operators_1 = require("./operators");
11
- const types_1 = require("./types");
12
- function createMotionMasterClient(hostname) {
13
- const reqResSocket = new motion_master_req_res_web_socket_1.MotionMasterReqResWebSocket();
14
- const pubSubSocket = new motion_master_pub_sub_web_socket_1.MotionMasterPubSubWebSocket();
15
- const client = new MotionMasterClient(reqResSocket, pubSubSocket);
16
- const clientId = (0, uuid_1.v4)();
17
- reqResSocket.open(`ws://${hostname}:63524?clientId=${clientId}`);
18
- pubSubSocket.open(`ws://${hostname}:63525?clientId=${clientId}`);
19
- return client;
20
- }
21
- exports.createMotionMasterClient = createMotionMasterClient;
22
- class MotionMasterClient {
23
- constructor(reqResSocket, pubSubSocket) {
24
- this.reqResSocket = reqResSocket;
25
- this.pubSubSocket = pubSubSocket;
26
- /**
27
- * This observable will emit true when both req/res and pub/sub sockets are opened.
28
- * If any socket gets closed, this observable will emit false.
29
- * This is a hot observable that will on subscription emit the last value of sockets opened.
30
- */
31
- this.socketsOpened$ = (0, rxjs_1.combineLatest)([this.reqResSocket.opened$, this.pubSubSocket.opened$]).pipe((0, rxjs_1.map)(([reqResSocketOpened, pubSubSocketOpened]) => reqResSocketOpened && pubSubSocketOpened));
32
- /**
33
- * Client is ready when both req/res and pub/sub sockets are opened.
34
- * This observable will emit whenever the sockets opened property changes to true.
35
- */
36
- this.ready$ = this.socketsOpened$.pipe((0, rxjs_1.filter)(Boolean));
37
- /**
38
- * This observable will emit only once when both req/res and pub/sub sockets are opened.
39
- * NOTE: This observable might never emit and it doesn't timeout.
40
- */
41
- this.onceReady$ = this.ready$.pipe((0, rxjs_1.first)());
42
- this.request = new motion_master_req_res_client_1.MotionMasterReqResClient(this.reqResSocket);
43
- this.monitor = new motion_master_pub_sub_client_1.MotionMasterPubSubClient(this.pubSubSocket);
44
- this.subscribeToSystemEvent();
45
- }
46
- /**
47
- * Client is ready when both req/res and pub/sub sockets are opened.
48
- * If both sockets are already opened, this function will immediately resolve to true.
49
- * Otherwise, it will wait up to requestTimeout for both sockets to open, or throw an error.
50
- */
51
- whenReady(requestTimeout = 5000) {
52
- return (0, rxjs_1.firstValueFrom)(this.ready$.pipe((0, rxjs_1.timeout)(requestTimeout)));
53
- }
54
- /**
55
- * Start monitoring.
56
- *
57
- * Note that the returned observable will never complete on its own.
58
- *
59
- * If you unsubscribe from it, the teardown code will send a request to the master to stop the monitoring.
60
- * That means you will end up with an observable that is not complete, but it won't emit any values.
61
- * This is fine when you want to use the monitoring observable directly in the template with async pipe,
62
- * which will unsubscribe automatically and stop the monitoring when you leave the component.
63
- *
64
- * If you need to complete the observable so that, for example, the toArray() operator works as expected, then use the {@link DataMonitoring} class,
65
- * which has a stop method. It can optionally buffer data for exporting as CSV or performing statistics on it.
66
- *
67
- * @param ids Device parameter IDs to monitor.
68
- * @param monitoringInterval At what interval should the master application send values.
69
- * @param config Configure the topic, buffer size, distinct.
70
- * @param requestTimeout How long will the client wait for the master to confirm that monitoring has started.
71
- * @returns An observable of an array of parameter values.
72
- */
73
- startMonitoring(ids, monitoringInterval, config, requestTimeout = 5000) {
74
- return (0, rxjs_1.defer)(() => {
75
- var _a, _b;
76
- const topic = (_a = config === null || config === void 0 ? void 0 : config.topic) !== null && _a !== void 0 ? _a : (0, uuid_1.v4)();
77
- const messageId = (_b = config === null || config === void 0 ? void 0 : config.messageId) !== null && _b !== void 0 ? _b : (0, uuid_1.v4)();
78
- if (!config) {
79
- config = { messageId, topic, bufferSize: 1, distinct: false };
80
- }
81
- this.request.resolveGetParameterValuesIds(ids).pipe((0, rxjs_1.mergeMap)((refs) => {
82
- if ((new Set(refs.map(([deviceAddress]) => deviceAddress))).size !== 1) {
83
- throw new Error('Start monitoring only supports a single device');
84
- }
85
- // Skipping write-only (wo) parameters is necessary because Motion Master does not initiate monitoring when the requested list contains such parameters.
86
- // For now, this serves as a temporary solution until Motion Master is fixed.
87
- refs = refs.filter(([, index]) => index !== 0x1024);
88
- const deviceAddress = refs[0][0];
89
- const props = {
90
- getDeviceParameterValues: {
91
- deviceAddress,
92
- parameters: refs.map(([, index, subindex]) => ({ index, subindex, loadFromCache: false })),
93
- sendProgress: false,
94
- },
95
- interval: monitoringInterval,
96
- topic,
97
- };
98
- return this.request.startMonitoringDeviceParameterValues(props, requestTimeout, messageId);
99
- })).subscribe();
100
- this.monitor.subscribe(config);
101
- const values$ = this.monitor.socket.data$.pipe((0, operators_1.selectMotionMasterMessageByTopic)(config.topic), (0, operators_1.mapMonitoringParameterValuesStatusMessageToParameterValues)());
102
- return new rxjs_1.Observable((observer) => {
103
- const subscription = values$.subscribe(observer).add(() => {
104
- this.stopMonitoring(messageId);
105
- });
106
- return subscription;
107
- });
108
- });
109
- }
110
- /**
111
- * TODO: return device parameters instead of just parameters
112
- * get parameters from ESI uprfront, and then when parameters are received
113
- * from motion master just concatenate (spread operator) props from ESI and props from parameter
114
- * assign device parameter id like 0x1018:00.12345
115
- * when assembling device parameter, get parameter from device in ESI based on product code, see ESI service
116
- * this should probably done for other get parameters functions, get ESI file from device or prepared, get data from it
117
- */
118
- startMonitoringDeviceParameters(ids, monitoringInterval, config, requestTimeout = 5000) {
119
- return (0, rxjs_1.defer)(() => {
120
- var _a, _b;
121
- const topic = (_a = config === null || config === void 0 ? void 0 : config.topic) !== null && _a !== void 0 ? _a : (0, uuid_1.v4)();
122
- const messageId = (_b = config === null || config === void 0 ? void 0 : config.messageId) !== null && _b !== void 0 ? _b : (0, uuid_1.v4)();
123
- if (!config) {
124
- config = { messageId, topic, bufferSize: 1, distinct: false };
125
- }
126
- this.request.resolveGetParameterValuesIds(ids).pipe((0, rxjs_1.mergeMap)((refs) => {
127
- if ((new Set(refs.map(([deviceAddress]) => deviceAddress))).size !== 1) {
128
- throw new Error('Start monitoring only supports a single device');
129
- }
130
- // Skipping write-only (wo) parameters is necessary because Motion Master does not initiate monitoring when the requested list contains such parameters.
131
- // For now, this serves as a temporary solution until Motion Master is fixed.
132
- refs = refs.filter(([, index]) => index !== 0x1024);
133
- const deviceAddress = refs[0][0];
134
- const props = {
135
- getDeviceParameterValues: {
136
- deviceAddress,
137
- parameters: refs.map(([, index, subindex]) => ({ index, subindex, loadFromCache: false })),
138
- sendProgress: false,
139
- },
140
- interval: monitoringInterval,
141
- topic,
142
- };
143
- return this.request.startMonitoringDeviceParameterValues(props, requestTimeout, messageId);
144
- })).subscribe();
145
- this.monitor.subscribe(config);
146
- const values$ = this.monitor.socket.data$.pipe((0, operators_1.selectMotionMasterMessageByTopic)(config.topic), (0, operators_1.mapMonitoringParameterValuesStatusMessageToDeviceParameters)(this.request));
147
- return new rxjs_1.Observable((observer) => {
148
- const subscription = values$.subscribe(observer).add(() => {
149
- this.stopMonitoring(messageId);
150
- });
151
- return subscription;
152
- });
153
- });
154
- }
155
- startMonitoringValue(id, monitoringInterval, config, requestTimeout = 5000) {
156
- const ids = typeof id === 'string' ? [id] : [id];
157
- return this.startMonitoring(ids, monitoringInterval, config, requestTimeout).pipe((0, rxjs_1.map)((parameters) => { var _a; return ((_a = parameters[0]) !== null && _a !== void 0 ? _a : 0); }));
158
- }
159
- trackTargetReached(deviceRef, monitoringInterval = 20) {
160
- return this.startMonitoringValue([deviceRef, 0x6041, 0], monitoringInterval).pipe((0, rxjs_1.map)((value) => (value & 0x0400) > 0), // tr = target reached bit
161
- (0, rxjs_1.distinctUntilChanged)());
162
- }
163
- waitUntilTargetReached(deviceRef, monitoringInterval = 20) {
164
- return this.trackTargetReached(deviceRef, monitoringInterval).pipe((0, rxjs_1.filter)(Boolean), (0, rxjs_1.first)());
165
- }
166
- whenTargetReached(deviceRef, monitoringInterval = 20) {
167
- return (0, rxjs_1.firstValueFrom)(this.waitUntilTargetReached(deviceRef, monitoringInterval));
168
- }
169
- subscribeToSystemEvent() {
170
- this.systemEventSubscription = this.monitor.systemEvent$.subscribe(systemEvent => {
171
- if (systemEvent.state === types_1.MotionMasterMessage.Status.SystemEvent.State.DEINITIALIZING) {
172
- this.request.clearDevicesInformation();
173
- }
174
- });
175
- }
176
- stopMonitoring(messageId) {
177
- this.request.stopMonitoringDeviceParameterValues({ startMonitoringRequestId: messageId });
178
- this.monitor.unsubscribe(messageId);
179
- }
180
- stopMonitoringAll() {
181
- this.monitor.messageIds.forEach(this.stopMonitoring);
182
- }
183
- closeSockets() {
184
- var _a;
185
- (_a = this.systemEventSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
186
- this.request.clearDevicesInformation();
187
- this.reqResSocket.close();
188
- this.pubSubSocket.close();
189
- }
190
- reopenSockets() {
191
- this.reqResSocket.reopen();
192
- this.pubSubSocket.reopen();
193
- this.subscribeToSystemEvent();
194
- }
195
- }
196
- exports.MotionMasterClient = MotionMasterClient;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MotionMasterClient = exports.createMotionMasterClient = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const uuid_1 = require("uuid");
6
+ const motion_master_pub_sub_client_1 = require("./motion-master-pub-sub-client");
7
+ const motion_master_pub_sub_web_socket_1 = require("./motion-master-pub-sub-web-socket");
8
+ const motion_master_req_res_client_1 = require("./motion-master-req-res-client");
9
+ const motion_master_req_res_web_socket_1 = require("./motion-master-req-res-web-socket");
10
+ const operators_1 = require("./operators");
11
+ const types_1 = require("./types");
12
+ function createMotionMasterClient(hostname) {
13
+ const reqResSocket = new motion_master_req_res_web_socket_1.MotionMasterReqResWebSocket();
14
+ const pubSubSocket = new motion_master_pub_sub_web_socket_1.MotionMasterPubSubWebSocket();
15
+ const client = new MotionMasterClient(reqResSocket, pubSubSocket);
16
+ const clientId = (0, uuid_1.v4)();
17
+ reqResSocket.open(`ws://${hostname}:63524?clientId=${clientId}`);
18
+ pubSubSocket.open(`ws://${hostname}:63525?clientId=${clientId}`);
19
+ return client;
20
+ }
21
+ exports.createMotionMasterClient = createMotionMasterClient;
22
+ class MotionMasterClient {
23
+ constructor(reqResSocket, pubSubSocket) {
24
+ this.reqResSocket = reqResSocket;
25
+ this.pubSubSocket = pubSubSocket;
26
+ /**
27
+ * This observable will emit true when both req/res and pub/sub sockets are opened.
28
+ * If any socket gets closed, this observable will emit false.
29
+ * This is a hot observable that will on subscription emit the last value of sockets opened.
30
+ */
31
+ this.socketsOpened$ = (0, rxjs_1.combineLatest)([this.reqResSocket.opened$, this.pubSubSocket.opened$]).pipe((0, rxjs_1.map)(([reqResSocketOpened, pubSubSocketOpened]) => reqResSocketOpened && pubSubSocketOpened));
32
+ /**
33
+ * Client is ready when both req/res and pub/sub sockets are opened.
34
+ * This observable will emit whenever the sockets opened property changes to true.
35
+ */
36
+ this.ready$ = this.socketsOpened$.pipe((0, rxjs_1.filter)(Boolean));
37
+ /**
38
+ * This observable will emit only once when both req/res and pub/sub sockets are opened.
39
+ * NOTE: This observable might never emit and it doesn't timeout.
40
+ */
41
+ this.onceReady$ = this.ready$.pipe((0, rxjs_1.first)());
42
+ this.request = new motion_master_req_res_client_1.MotionMasterReqResClient(this.reqResSocket);
43
+ this.monitor = new motion_master_pub_sub_client_1.MotionMasterPubSubClient(this.pubSubSocket);
44
+ this.subscribeToSystemEvent();
45
+ }
46
+ /**
47
+ * Client is ready when both req/res and pub/sub sockets are opened.
48
+ * If both sockets are already opened, this function will immediately resolve to true.
49
+ * Otherwise, it will wait up to requestTimeout for both sockets to open, or throw an error.
50
+ */
51
+ whenReady(requestTimeout = 5000) {
52
+ return (0, rxjs_1.firstValueFrom)(this.ready$.pipe((0, rxjs_1.timeout)(requestTimeout)));
53
+ }
54
+ /**
55
+ * Start monitoring.
56
+ *
57
+ * Note that the returned observable will never complete on its own.
58
+ *
59
+ * If you unsubscribe from it, the teardown code will send a request to the master to stop the monitoring.
60
+ * That means you will end up with an observable that is not complete, but it won't emit any values.
61
+ * This is fine when you want to use the monitoring observable directly in the template with async pipe,
62
+ * which will unsubscribe automatically and stop the monitoring when you leave the component.
63
+ *
64
+ * If you need to complete the observable so that, for example, the toArray() operator works as expected, then use the {@link DataMonitoring} class,
65
+ * which has a stop method. It can optionally buffer data for exporting as CSV or performing statistics on it.
66
+ *
67
+ * @param ids Device parameter IDs to monitor.
68
+ * @param monitoringInterval At what interval should the master application send values.
69
+ * @param config Configure the topic, buffer size, distinct.
70
+ * @param requestTimeout How long will the client wait for the master to confirm that monitoring has started.
71
+ * @returns An observable of an array of parameter values.
72
+ */
73
+ startMonitoring(ids, monitoringInterval, config, requestTimeout = 5000) {
74
+ return (0, rxjs_1.defer)(() => {
75
+ var _a, _b;
76
+ const topic = (_a = config === null || config === void 0 ? void 0 : config.topic) !== null && _a !== void 0 ? _a : (0, uuid_1.v4)();
77
+ const messageId = (_b = config === null || config === void 0 ? void 0 : config.messageId) !== null && _b !== void 0 ? _b : (0, uuid_1.v4)();
78
+ if (!config) {
79
+ config = { messageId, topic, bufferSize: 1, distinct: false };
80
+ }
81
+ this.request.resolveGetParameterValuesIds(ids).pipe((0, rxjs_1.mergeMap)((refs) => {
82
+ if ((new Set(refs.map(([deviceAddress]) => deviceAddress))).size !== 1) {
83
+ throw new Error('Start monitoring only supports a single device');
84
+ }
85
+ // Skipping write-only (wo) parameters is necessary because Motion Master does not initiate monitoring when the requested list contains such parameters.
86
+ // For now, this serves as a temporary solution until Motion Master is fixed.
87
+ refs = refs.filter(([, index]) => index !== 0x1024);
88
+ const deviceAddress = refs[0][0];
89
+ const props = {
90
+ getDeviceParameterValues: {
91
+ deviceAddress,
92
+ parameters: refs.map(([, index, subindex]) => ({ index, subindex, loadFromCache: false })),
93
+ sendProgress: false,
94
+ },
95
+ interval: monitoringInterval,
96
+ topic,
97
+ };
98
+ return this.request.startMonitoringDeviceParameterValues(props, requestTimeout, messageId);
99
+ })).subscribe();
100
+ this.monitor.subscribe(config);
101
+ const values$ = this.monitor.socket.data$.pipe((0, operators_1.selectMotionMasterMessageByTopic)(config.topic), (0, operators_1.mapMonitoringParameterValuesStatusMessageToParameterValues)());
102
+ return new rxjs_1.Observable((observer) => {
103
+ const subscription = values$.subscribe(observer).add(() => {
104
+ this.stopMonitoring(messageId);
105
+ });
106
+ return subscription;
107
+ });
108
+ });
109
+ }
110
+ /**
111
+ * TODO: return device parameters instead of just parameters
112
+ * get parameters from ESI uprfront, and then when parameters are received
113
+ * from motion master just concatenate (spread operator) props from ESI and props from parameter
114
+ * assign device parameter id like 0x1018:00.12345
115
+ * when assembling device parameter, get parameter from device in ESI based on product code, see ESI service
116
+ * this should probably done for other get parameters functions, get ESI file from device or prepared, get data from it
117
+ */
118
+ startMonitoringDeviceParameters(ids, monitoringInterval, config, requestTimeout = 5000) {
119
+ return (0, rxjs_1.defer)(() => {
120
+ var _a, _b;
121
+ const topic = (_a = config === null || config === void 0 ? void 0 : config.topic) !== null && _a !== void 0 ? _a : (0, uuid_1.v4)();
122
+ const messageId = (_b = config === null || config === void 0 ? void 0 : config.messageId) !== null && _b !== void 0 ? _b : (0, uuid_1.v4)();
123
+ if (!config) {
124
+ config = { messageId, topic, bufferSize: 1, distinct: false };
125
+ }
126
+ this.request.resolveGetParameterValuesIds(ids).pipe((0, rxjs_1.mergeMap)((refs) => {
127
+ if ((new Set(refs.map(([deviceAddress]) => deviceAddress))).size !== 1) {
128
+ throw new Error('Start monitoring only supports a single device');
129
+ }
130
+ // Skipping write-only (wo) parameters is necessary because Motion Master does not initiate monitoring when the requested list contains such parameters.
131
+ // For now, this serves as a temporary solution until Motion Master is fixed.
132
+ refs = refs.filter(([, index]) => index !== 0x1024);
133
+ const deviceAddress = refs[0][0];
134
+ const props = {
135
+ getDeviceParameterValues: {
136
+ deviceAddress,
137
+ parameters: refs.map(([, index, subindex]) => ({ index, subindex, loadFromCache: false })),
138
+ sendProgress: false,
139
+ },
140
+ interval: monitoringInterval,
141
+ topic,
142
+ };
143
+ return this.request.startMonitoringDeviceParameterValues(props, requestTimeout, messageId);
144
+ })).subscribe();
145
+ this.monitor.subscribe(config);
146
+ const values$ = this.monitor.socket.data$.pipe((0, operators_1.selectMotionMasterMessageByTopic)(config.topic), (0, operators_1.mapMonitoringParameterValuesStatusMessageToDeviceParameters)(this.request));
147
+ return new rxjs_1.Observable((observer) => {
148
+ const subscription = values$.subscribe(observer).add(() => {
149
+ this.stopMonitoring(messageId);
150
+ });
151
+ return subscription;
152
+ });
153
+ });
154
+ }
155
+ startMonitoringValue(id, monitoringInterval, config, requestTimeout = 5000) {
156
+ const ids = typeof id === 'string' ? [id] : [id];
157
+ return this.startMonitoring(ids, monitoringInterval, config, requestTimeout).pipe((0, rxjs_1.map)((parameters) => { var _a; return ((_a = parameters[0]) !== null && _a !== void 0 ? _a : 0); }));
158
+ }
159
+ trackTargetReached(deviceRef, monitoringInterval = 20) {
160
+ return this.startMonitoringValue([deviceRef, 0x6041, 0], monitoringInterval).pipe((0, rxjs_1.map)((value) => (value & 0x0400) > 0), // tr = target reached bit
161
+ (0, rxjs_1.distinctUntilChanged)());
162
+ }
163
+ waitUntilTargetReached(deviceRef, monitoringInterval = 20) {
164
+ return this.trackTargetReached(deviceRef, monitoringInterval).pipe((0, rxjs_1.filter)(Boolean), (0, rxjs_1.first)());
165
+ }
166
+ whenTargetReached(deviceRef, monitoringInterval = 20) {
167
+ return (0, rxjs_1.firstValueFrom)(this.waitUntilTargetReached(deviceRef, monitoringInterval));
168
+ }
169
+ subscribeToSystemEvent() {
170
+ this.systemEventSubscription = this.monitor.systemEvent$.subscribe(systemEvent => {
171
+ if (systemEvent.state === types_1.MotionMasterMessage.Status.SystemEvent.State.DEINITIALIZING) {
172
+ this.request.clearDevicesInformation();
173
+ }
174
+ });
175
+ }
176
+ stopMonitoring(messageId) {
177
+ this.request.stopMonitoringDeviceParameterValues({ startMonitoringRequestId: messageId });
178
+ this.monitor.unsubscribe(messageId);
179
+ }
180
+ stopMonitoringAll() {
181
+ this.monitor.messageIds.forEach(this.stopMonitoring);
182
+ }
183
+ closeSockets() {
184
+ var _a;
185
+ (_a = this.systemEventSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
186
+ this.request.clearDevicesInformation();
187
+ this.reqResSocket.close();
188
+ this.pubSubSocket.close();
189
+ }
190
+ reopenSockets() {
191
+ this.reqResSocket.reopen();
192
+ this.pubSubSocket.reopen();
193
+ this.subscribeToSystemEvent();
194
+ }
195
+ }
196
+ exports.MotionMasterClient = MotionMasterClient;
197
197
  //# sourceMappingURL=motion-master-client.js.map
@@ -1,17 +1,17 @@
1
- import { Observable, Subject } from "rxjs";
2
- import { MonitoringConfig } from "./monitoring-config";
3
- import { MotionMasterPubSubSocket } from "./motion-master-pub-sub-socket";
4
- import { IMotionMasterMessage, MotionMasterMessage } from "./types";
5
- export declare class MotionMasterPubSubClient {
6
- readonly socket: MotionMasterPubSubSocket;
7
- readonly data$: Subject<[string, IMotionMasterMessage[]]>;
8
- private subscriptions;
9
- readonly notification$: Observable<IMotionMasterMessage>;
10
- readonly systemEvent$: Observable<MotionMasterMessage.Status.ISystemEvent>;
11
- readonly deviceEvent$: Observable<MotionMasterMessage.Status.IDeviceEvent>;
12
- constructor(socket: MotionMasterPubSubSocket);
13
- get messageIds(): string[];
14
- subscribe(config: MonitoringConfig): string;
15
- unsubscribe(messageId: string): void;
16
- unsubscribeAll(): void;
17
- }
1
+ import { Observable, Subject } from "rxjs";
2
+ import { MonitoringConfig } from "./monitoring-config";
3
+ import { MotionMasterPubSubSocket } from "./motion-master-pub-sub-socket";
4
+ import { IMotionMasterMessage, MotionMasterMessage } from "./types";
5
+ export declare class MotionMasterPubSubClient {
6
+ readonly socket: MotionMasterPubSubSocket;
7
+ readonly data$: Subject<[string, IMotionMasterMessage[]]>;
8
+ private subscriptions;
9
+ readonly notification$: Observable<IMotionMasterMessage>;
10
+ readonly systemEvent$: Observable<MotionMasterMessage.Status.ISystemEvent>;
11
+ readonly deviceEvent$: Observable<MotionMasterMessage.Status.IDeviceEvent>;
12
+ constructor(socket: MotionMasterPubSubSocket);
13
+ get messageIds(): string[];
14
+ subscribe(config: MonitoringConfig): string;
15
+ unsubscribe(messageId: string): void;
16
+ unsubscribeAll(): void;
17
+ }