motion-master-client 0.0.1 → 0.0.2
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/.babelrc +3 -0
- package/.eslintrc.json +18 -0
- package/README.md +44 -2
- package/jest.config.ts +15 -0
- package/motion-master.proto +1822 -0
- package/package.json +6 -9
- package/src/{index.d.ts → index.ts} +1 -0
- package/src/lib/device-log-line.ts +5 -0
- package/src/lib/device-parameter.spec.ts +85 -0
- package/src/lib/device-parameter.ts +69 -0
- package/src/lib/hardware-description.spec.ts +223 -0
- package/src/lib/hardware-description.ts +79 -0
- package/src/lib/logger.ts +5 -0
- package/src/lib/monitoring-config.ts +6 -0
- package/src/lib/monitoring-entry.ts +11 -0
- package/src/lib/motion-master-client.ts +94 -0
- package/src/lib/motion-master-pub-sub-client.ts +94 -0
- package/src/lib/motion-master-pub-sub-socket.ts +33 -0
- package/src/lib/motion-master-pub-sub-web-socket.ts +71 -0
- package/src/lib/motion-master-pub-sub-worker-socket.ts +58 -0
- package/src/lib/motion-master-req-res-client.spec.ts +126 -0
- package/src/lib/motion-master-req-res-client.ts +1625 -0
- package/src/lib/motion-master-req-res-socket.ts +45 -0
- package/src/lib/motion-master-req-res-web-socket.ts +119 -0
- package/src/lib/motion-master-req-res-worker-socket.ts +63 -0
- package/src/lib/motion-master.proto.d.ts +5084 -0
- package/src/lib/motion-master.proto.js +52278 -0
- package/src/lib/operators.ts +93 -0
- package/src/lib/{options.js → options.ts} +7 -6
- package/src/lib/parameter.spec.ts +81 -0
- package/src/lib/parameter.ts +119 -0
- package/src/lib/request-status-resolver.ts +380 -0
- package/src/lib/system-log-line.ts +8 -0
- package/src/lib/types.ts +58 -0
- package/src/lib/{urls.js → urls.ts} +3 -3
- package/src/lib/util.ts +261 -0
- package/tsconfig.json +22 -0
- package/tsconfig.lib.json +10 -0
- package/tsconfig.spec.json +20 -0
- package/typedoc.json +10 -0
- package/src/index.js +0 -22
- package/src/index.js.map +0 -1
- package/src/lib/device-log-line.d.ts +0 -5
- package/src/lib/device-log-line.js +0 -2
- package/src/lib/device-log-line.js.map +0 -1
- package/src/lib/hardware-description.d.ts +0 -36
- package/src/lib/hardware-description.js +0 -38
- package/src/lib/hardware-description.js.map +0 -1
- package/src/lib/logger.d.ts +0 -1
- package/src/lib/logger.js +0 -5
- package/src/lib/logger.js.map +0 -1
- package/src/lib/monitoring-config.d.ts +0 -6
- package/src/lib/monitoring-config.js +0 -2
- package/src/lib/monitoring-config.js.map +0 -1
- package/src/lib/monitoring-entry.d.ts +0 -10
- package/src/lib/monitoring-entry.js +0 -2
- package/src/lib/monitoring-entry.js.map +0 -1
- package/src/lib/motion-master-client.d.ts +0 -18
- package/src/lib/motion-master-client.js +0 -48
- package/src/lib/motion-master-client.js.map +0 -1
- package/src/lib/motion-master-pub-sub-client.d.ts +0 -16
- package/src/lib/motion-master-pub-sub-client.js +0 -64
- package/src/lib/motion-master-pub-sub-client.js.map +0 -1
- package/src/lib/motion-master-pub-sub-socket.d.ts +0 -28
- package/src/lib/motion-master-pub-sub-socket.js +0 -2
- package/src/lib/motion-master-pub-sub-socket.js.map +0 -1
- package/src/lib/motion-master-pub-sub-web-socket.d.ts +0 -13
- package/src/lib/motion-master-pub-sub-web-socket.js +0 -57
- package/src/lib/motion-master-pub-sub-web-socket.js.map +0 -1
- package/src/lib/motion-master-pub-sub-worker-socket.d.ts +0 -16
- package/src/lib/motion-master-pub-sub-worker-socket.js +0 -37
- package/src/lib/motion-master-pub-sub-worker-socket.js.map +0 -1
- package/src/lib/motion-master-req-res-client.d.ts +0 -370
- package/src/lib/motion-master-req-res-client.js +0 -1067
- package/src/lib/motion-master-req-res-client.js.map +0 -1
- package/src/lib/motion-master-req-res-socket.d.ts +0 -38
- package/src/lib/motion-master-req-res-socket.js +0 -2
- package/src/lib/motion-master-req-res-socket.js.map +0 -1
- package/src/lib/motion-master-req-res-web-socket.d.ts +0 -20
- package/src/lib/motion-master-req-res-web-socket.js +0 -96
- package/src/lib/motion-master-req-res-web-socket.js.map +0 -1
- package/src/lib/motion-master-req-res-worker-socket.d.ts +0 -15
- package/src/lib/motion-master-req-res-worker-socket.js +0 -49
- package/src/lib/motion-master-req-res-worker-socket.js.map +0 -1
- package/src/lib/operators.d.ts +0 -21
- package/src/lib/operators.js +0 -62
- package/src/lib/operators.js.map +0 -1
- package/src/lib/options.d.ts +0 -10
- package/src/lib/options.js.map +0 -1
- package/src/lib/parameter.d.ts +0 -9
- package/src/lib/parameter.js +0 -2
- package/src/lib/parameter.js.map +0 -1
- package/src/lib/request-status-resolver.d.ts +0 -4
- package/src/lib/request-status-resolver.js +0 -320
- package/src/lib/request-status-resolver.js.map +0 -1
- package/src/lib/system-log-line.d.ts +0 -8
- package/src/lib/system-log-line.js +0 -2
- package/src/lib/system-log-line.js.map +0 -1
- package/src/lib/types.d.ts +0 -41
- package/src/lib/types.js +0 -9
- package/src/lib/types.js.map +0 -1
- package/src/lib/urls.d.ts +0 -3
- package/src/lib/urls.js.map +0 -1
- package/src/lib/util.d.ts +0 -33
- package/src/lib/util.js +0 -247
- package/src/lib/util.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "motion-master-client",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"dependencies": {},
|
|
8
|
-
"peerDependencies": {}
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "motion-master-client",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A library and CLI program used for communicating with Motion Master."
|
|
6
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { makeDeviceParameterId, splitDeviceParameterId } from "./device-parameter";
|
|
2
|
+
|
|
3
|
+
describe('deviceParameter', () => {
|
|
4
|
+
|
|
5
|
+
describe('makeDeviceParameterId', () => {
|
|
6
|
+
|
|
7
|
+
const serialNumber = '8502-03-0001353-2115';
|
|
8
|
+
|
|
9
|
+
test.each<[string, [(number | null | undefined), (number | null | undefined)], string]>([
|
|
10
|
+
[serialNumber, [0x1234, 123], '0x1234:7B.8502-03-0001353-2115'],
|
|
11
|
+
[serialNumber, [23, 23], '0x0017:17.8502-03-0001353-2115'],
|
|
12
|
+
[serialNumber, [0, 0], '0x0000:00.8502-03-0001353-2115'],
|
|
13
|
+
[serialNumber, [0x2000, undefined], '0x2000:00.8502-03-0001353-2115'],
|
|
14
|
+
[serialNumber, [0x2003, null], '0x2003:00.8502-03-0001353-2115'],
|
|
15
|
+
[serialNumber, [0x10000, 3], '0x00010000:03.8502-03-0001353-2115'],
|
|
16
|
+
[serialNumber, [0x100F0, undefined], '0x000100F0:00.8502-03-0001353-2115'],
|
|
17
|
+
])('should for device serial number "%s" and tuple %j return "%s"', (serialNumber, tuple, expected) => {
|
|
18
|
+
const result = makeDeviceParameterId(serialNumber, tuple);
|
|
19
|
+
|
|
20
|
+
expect(result).toBe(expected);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test.each([
|
|
24
|
+
[serialNumber, {}, '0x0000:00.8502-03-0001353-2115'],
|
|
25
|
+
[serialNumber, { index: 0x2004, subindex: 4 }, '0x2004:04.8502-03-0001353-2115'],
|
|
26
|
+
[serialNumber, { index: 0x1024 }, '0x1024:00.8502-03-0001353-2115'],
|
|
27
|
+
])('should for device serial number "%s" and parameter %j return "%s"', (serialNumber, parameter, expected) => {
|
|
28
|
+
const result = makeDeviceParameterId(serialNumber, parameter);
|
|
29
|
+
|
|
30
|
+
expect(result).toBe(expected);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test.each([
|
|
34
|
+
[serialNumber, 0x1234, 123, '0x1234:7B.8502-03-0001353-2115'],
|
|
35
|
+
[serialNumber, 23, 23, '0x0017:17.8502-03-0001353-2115'],
|
|
36
|
+
[serialNumber, 0, 0, '0x0000:00.8502-03-0001353-2115'],
|
|
37
|
+
[serialNumber, 0x2000, undefined, '0x2000:00.8502-03-0001353-2115'],
|
|
38
|
+
[serialNumber, 0x2003, null, '0x2003:00.8502-03-0001353-2115'],
|
|
39
|
+
[serialNumber, 0x10000, 3, '0x00010000:03.8502-03-0001353-2115'],
|
|
40
|
+
[serialNumber, 0x100F0, undefined, '0x000100F0:00.8502-03-0001353-2115'],
|
|
41
|
+
])('should for device serial number "%s" and index %d and subindex %d return "%s"', (serialNumber, index, subindex, expected) => {
|
|
42
|
+
const result = makeDeviceParameterId(serialNumber, index, subindex);
|
|
43
|
+
|
|
44
|
+
expect(result).toBe(expected);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should throw if index is less than 0', () => {
|
|
48
|
+
expect(() => {
|
|
49
|
+
makeDeviceParameterId(serialNumber, -123, 0);
|
|
50
|
+
}).toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should throw if subindex is less than 0', () => {
|
|
54
|
+
expect(() => {
|
|
55
|
+
makeDeviceParameterId(serialNumber, 0x1024, -3);
|
|
56
|
+
}).toThrow();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('splitDeviceParameterId', () => {
|
|
62
|
+
|
|
63
|
+
test.each([
|
|
64
|
+
['0x1234:7B.8502-03-0001353-2115', ['8502-03-0001353-2115', 4660, 123]],
|
|
65
|
+
['0x000100F0:00.8502-03-0001353-2115', ['8502-03-0001353-2115', 65776, 0]],
|
|
66
|
+
])('should for id "%s" return tuple %j', (id, expected) => {
|
|
67
|
+
const result = splitDeviceParameterId(id);
|
|
68
|
+
|
|
69
|
+
expect(result).toEqual(expected);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test.each([
|
|
73
|
+
['0x12:7B.8502-03-0001353-2115'],
|
|
74
|
+
['0x1234:F.8502-03-0001353-2115'],
|
|
75
|
+
['0x1234:FG.8502-03-0001353-2115'],
|
|
76
|
+
['0x1234:7B.8502-03-ABC1353-2115'],
|
|
77
|
+
['0x1234:7B.8502_03_0001353_2115'],
|
|
78
|
+
['0x1H34:7B.8502-03-0001353-2115'],
|
|
79
|
+
])('should throw error for id "%s"', (id) => {
|
|
80
|
+
expect(() => splitDeviceParameterId(id)).toThrow();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { makeParameterId, Parameter } from "./parameter";
|
|
2
|
+
|
|
3
|
+
export interface DeviceParameter extends Parameter {
|
|
4
|
+
id: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Make device parameter id by providing a device serial number and tuple of index and subindex.
|
|
9
|
+
*
|
|
10
|
+
* @param serialNumber - device serial number from the hardware description file
|
|
11
|
+
* @param tuple - an array of index and subindex
|
|
12
|
+
* @throws {Error} if index or subindex are less than 0
|
|
13
|
+
* @returns combined index and subindex in uppercase hexadecimal format, e.g. "0x60FE:02"
|
|
14
|
+
*/
|
|
15
|
+
export function makeDeviceParameterId(serialNumber: string, tuple: [(number | null | undefined), (number | null | undefined)]): string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Make device parameter id by providing a device serial number and object which has index and subindex properties.
|
|
19
|
+
*
|
|
20
|
+
* @param serialNumber - device serial number from the hardware description file
|
|
21
|
+
* @param parameter - an object with optional index and subindex properties
|
|
22
|
+
* @throws {Error} if index or subindex are less than 0
|
|
23
|
+
* @returns combined index and subindex in uppercase hexadecimal format, e.g. "0x60FE:02"
|
|
24
|
+
*/
|
|
25
|
+
export function makeDeviceParameterId(serialNumber: string, parameter: { index?: (number | null), subindex?: (number | null) }): string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Make parameter id by providing a device serial number and index and subindex.
|
|
29
|
+
*
|
|
30
|
+
* @param serialNumber - device serial number from the hardware description file
|
|
31
|
+
* @param index - from 0x0000 to 0xFFFF for objects defined in ESI and >0xFFFF for custom object
|
|
32
|
+
* @param subindex - defaults to 0 if not provided
|
|
33
|
+
* @throws {Error} if index or subindex are less than 0
|
|
34
|
+
* @returns combined index and subindex in uppercase hexadecimal format, e.g. "0x60FE:02"
|
|
35
|
+
*/
|
|
36
|
+
export function makeDeviceParameterId(serialNumber: string, index?: (number | null), subindex?: (number | null)): string;
|
|
37
|
+
|
|
38
|
+
export function makeDeviceParameterId(serialNumber: string, a?: (number | null) | { index?: (number | null), subindex?: (number | null) } | [(number | null | undefined), (number | null | undefined)], b?: (number | null)): string {
|
|
39
|
+
const parameterId = makeParameterId(a, b);
|
|
40
|
+
return `${parameterId}.${serialNumber}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Example of device parameter id is "0x2110:1A.8502-03-0001353-2115" where:
|
|
45
|
+
* - 0x2110 is object index in hexadecimal format
|
|
46
|
+
* - 1A is subindex in hexadecimal format
|
|
47
|
+
* - 8502-03-0001353-2115 is device serial number from hardware description file
|
|
48
|
+
*/
|
|
49
|
+
export const deviceParameterIdRegExp = /^0x([0-9a-fA-F]{4,}):([0-9a-fA-F]{2})\.([\d-]+)$/;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Split device parameter id into parts.
|
|
53
|
+
*
|
|
54
|
+
* @param id - device parameter id like "0x2110:1A.8502-03-0001353-2115"
|
|
55
|
+
* @returns tuple of device serial number, index, and subindex
|
|
56
|
+
*/
|
|
57
|
+
export function splitDeviceParameterId(id: string): [string, number, number] {
|
|
58
|
+
const match = id.match(deviceParameterIdRegExp);
|
|
59
|
+
|
|
60
|
+
if (!match) {
|
|
61
|
+
throw new Error(`Device parameter id "${id}" doesn't match the regular expression: ${deviceParameterIdRegExp}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return [
|
|
65
|
+
match[3], // device serial number
|
|
66
|
+
parseInt(match[1], 16), // index
|
|
67
|
+
parseInt(match[2], 16), // subindex
|
|
68
|
+
];
|
|
69
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAllComponentsFromHardwareDescription,
|
|
3
|
+
getApiIdentifierFromHardwareDescription,
|
|
4
|
+
getNameFromHardwareDescription,
|
|
5
|
+
getSerialNumberFromHardwareDescription,
|
|
6
|
+
hardwareComponentsMatch,
|
|
7
|
+
HardwareDescription,
|
|
8
|
+
} from './hardware-description';
|
|
9
|
+
|
|
10
|
+
describe('getApiIdentifierFromHardwareDescription', () => {
|
|
11
|
+
it('should return api identifier from assembly', () => {
|
|
12
|
+
const result = getApiIdentifierFromHardwareDescription({
|
|
13
|
+
assembly: { id: 'foo', version: '01', serialNumber: 'foo-sn' }, // prefer assembly over device
|
|
14
|
+
device: { id: 'bar', version: '02', serialNumber: 'bar-sn' },
|
|
15
|
+
fileVersion: '',
|
|
16
|
+
} as HardwareDescription);
|
|
17
|
+
|
|
18
|
+
expect(result).toBe('foo-01');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should return api identifier from device', () => {
|
|
22
|
+
const result = getApiIdentifierFromHardwareDescription({
|
|
23
|
+
device: { id: 'bar', version: '02', serialNumber: 'bar-sn' },
|
|
24
|
+
fileVersion: '',
|
|
25
|
+
} as HardwareDescription);
|
|
26
|
+
|
|
27
|
+
expect(result).toBe('bar-02');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('getNameFromHardwareDescription', () => {
|
|
32
|
+
it('should return name from assembly', () => {
|
|
33
|
+
const result = getNameFromHardwareDescription({
|
|
34
|
+
assembly: { id: 'foo', version: '01', serialNumber: 'foo-sn', name: 'Assembly' }, // prefer assembly over device
|
|
35
|
+
device: { id: 'bar', version: '02', serialNumber: 'bar-sn', name: 'Device' },
|
|
36
|
+
fileVersion: '',
|
|
37
|
+
} as HardwareDescription);
|
|
38
|
+
|
|
39
|
+
expect(result).toBe('Assembly');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should return name from device', () => {
|
|
43
|
+
const result = getNameFromHardwareDescription({
|
|
44
|
+
device: { id: 'bar', version: '02', serialNumber: 'bar-sn', name: 'Device' },
|
|
45
|
+
fileVersion: '',
|
|
46
|
+
} as HardwareDescription);
|
|
47
|
+
|
|
48
|
+
expect(result).toBe('Device');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('getSerialNumberFromHardwareDescription', () => {
|
|
53
|
+
it('should return serial number from assembly', () => {
|
|
54
|
+
const result = getSerialNumberFromHardwareDescription({
|
|
55
|
+
assembly: { id: 'foo', version: '01', serialNumber: 'foo-sn' }, // prefer assembly over device
|
|
56
|
+
device: { id: 'bar', version: '02', serialNumber: 'bar-sn' },
|
|
57
|
+
fileVersion: '',
|
|
58
|
+
} as HardwareDescription);
|
|
59
|
+
|
|
60
|
+
expect(result).toBe('foo-sn');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should return serial number from device', () => {
|
|
64
|
+
const result = getSerialNumberFromHardwareDescription({
|
|
65
|
+
device: { id: 'bar', version: '02', serialNumber: 'bar-sn' },
|
|
66
|
+
fileVersion: '',
|
|
67
|
+
} as HardwareDescription);
|
|
68
|
+
|
|
69
|
+
expect(result).toBe('bar-sn');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('getAllComponentsFromHardwareDescription', () => {
|
|
74
|
+
it('should return components only from device when assembly is undefined', () => {
|
|
75
|
+
const deviceComponents = [
|
|
76
|
+
{
|
|
77
|
+
name: 'Com EtherCAT',
|
|
78
|
+
serialNumber: '3333-33-3333333-3333',
|
|
79
|
+
version: 'B.2',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'Core C2X',
|
|
83
|
+
serialNumber: '1111-11-1111111-1111',
|
|
84
|
+
version: 'A.5',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'Drive 400',
|
|
88
|
+
serialNumber: '2222-22-2222222-2222',
|
|
89
|
+
version: 'E.1',
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const hardwareDescription: HardwareDescription = {
|
|
94
|
+
device: {
|
|
95
|
+
components: deviceComponents,
|
|
96
|
+
id: '8503',
|
|
97
|
+
macAddress: '01-23-45-67-89-AB',
|
|
98
|
+
name: 'Circulo 9 1800 Encoder Pos 1 & 2',
|
|
99
|
+
serialNumber: '8506-01-040595-4023',
|
|
100
|
+
version: '02',
|
|
101
|
+
},
|
|
102
|
+
fileVersion: '1.0.0',
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const result = getAllComponentsFromHardwareDescription(hardwareDescription);
|
|
106
|
+
|
|
107
|
+
expect(result).toEqual(deviceComponents);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should return combined components from assembly and device', () => {
|
|
111
|
+
const assemblyComponents = [
|
|
112
|
+
{
|
|
113
|
+
name: 'Heidrive HMP04',
|
|
114
|
+
serialNumber: '79137447',
|
|
115
|
+
version: 'REV-2',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: 'KEB gearbox',
|
|
119
|
+
serialNumber: '12344234',
|
|
120
|
+
version: 'REV-3',
|
|
121
|
+
},
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
const deviceComponents = [
|
|
125
|
+
{
|
|
126
|
+
name: 'Com EtherCAT',
|
|
127
|
+
serialNumber: '3333-33-3333333-3333',
|
|
128
|
+
version: 'B.2',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'Core C2X',
|
|
132
|
+
serialNumber: '1111-11-1111111-1111',
|
|
133
|
+
version: 'A.5',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'Drive 400',
|
|
137
|
+
serialNumber: '2222-22-2222222-2222',
|
|
138
|
+
version: 'E.1',
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
const hardwareDescription: HardwareDescription = {
|
|
143
|
+
assembly: {
|
|
144
|
+
components: assemblyComponents,
|
|
145
|
+
id: 'ASM',
|
|
146
|
+
name: 'Assembly',
|
|
147
|
+
serialNumber: '12345',
|
|
148
|
+
version: '01',
|
|
149
|
+
},
|
|
150
|
+
device: {
|
|
151
|
+
components: deviceComponents,
|
|
152
|
+
id: '8503',
|
|
153
|
+
macAddress: '01-23-45-67-89-AB',
|
|
154
|
+
name: 'Circulo 9 1800 Encoder Pos 1 & 2',
|
|
155
|
+
serialNumber: '8506-01-040595-4023',
|
|
156
|
+
version: '02',
|
|
157
|
+
},
|
|
158
|
+
fileVersion: '1.0.0',
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const result = getAllComponentsFromHardwareDescription(hardwareDescription);
|
|
162
|
+
|
|
163
|
+
expect(result).toEqual([...assemblyComponents, ...deviceComponents]);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('hardwareComponentsMatch', () => {
|
|
168
|
+
it('should return false when both arrays are empty', () => {
|
|
169
|
+
expect(hardwareComponentsMatch([], [])).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should return false when components don\'t match', () => {
|
|
173
|
+
const components1 = [
|
|
174
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
|
|
175
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
|
|
176
|
+
];
|
|
177
|
+
const components2 = [
|
|
178
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'A.2' },
|
|
179
|
+
{ name: 'Core C22', serialNumber: '1111-11-1111111-1111', version: 'A.1' },
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
expect(hardwareComponentsMatch(components1, components2)).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('should return true when components match', () => {
|
|
186
|
+
const components1 = [
|
|
187
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
|
|
188
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
|
|
189
|
+
];
|
|
190
|
+
const components2 = [
|
|
191
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
|
|
192
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
expect(hardwareComponentsMatch(components1, components2)).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should return true when components match but are not ordered the same', () => {
|
|
199
|
+
const components1 = [
|
|
200
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
|
|
201
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
|
|
202
|
+
];
|
|
203
|
+
const components2 = [
|
|
204
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
|
|
205
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
expect(hardwareComponentsMatch(components1, components2)).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should return true when revision numbers don\'t match', () => {
|
|
212
|
+
const components1 = [
|
|
213
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
|
|
214
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
|
|
215
|
+
];
|
|
216
|
+
const components2 = [
|
|
217
|
+
{ name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.7' },
|
|
218
|
+
{ name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.2' },
|
|
219
|
+
];
|
|
220
|
+
|
|
221
|
+
expect(hardwareComponentsMatch(components1, components2)).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isEqual } from 'lodash';
|
|
2
|
+
|
|
3
|
+
export interface HardwareComponent {
|
|
4
|
+
name: string;
|
|
5
|
+
version: string;
|
|
6
|
+
serialNumber: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type AssemblyComponent = HardwareComponent;
|
|
10
|
+
export type DeviceComponent = HardwareComponent;
|
|
11
|
+
|
|
12
|
+
export interface Assembly {
|
|
13
|
+
name: string;
|
|
14
|
+
id: string;
|
|
15
|
+
version: string;
|
|
16
|
+
serialNumber: string;
|
|
17
|
+
components: AssemblyComponent[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface HardwareDevice {
|
|
21
|
+
name: string;
|
|
22
|
+
id: string;
|
|
23
|
+
version: string;
|
|
24
|
+
serialNumber: string;
|
|
25
|
+
macAddress: string;
|
|
26
|
+
components: DeviceComponent[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @link https://docs.google.com/document/d/1N00-ZjxHkjoWNIsnoTtza9CUHrxm8-e54298DXLuD94
|
|
31
|
+
*/
|
|
32
|
+
export interface HardwareDescription {
|
|
33
|
+
fileVersion: string;
|
|
34
|
+
assembly?: Assembly;
|
|
35
|
+
device: HardwareDevice;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getIdFromHardwareDescription(hardwareDescription: HardwareDescription): string {
|
|
39
|
+
return hardwareDescription.assembly
|
|
40
|
+
? hardwareDescription.assembly.id
|
|
41
|
+
: hardwareDescription.device.id;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getApiIdentifierFromHardwareDescription(hardwareDescription: HardwareDescription): string {
|
|
45
|
+
return hardwareDescription.assembly
|
|
46
|
+
? `${hardwareDescription.assembly.id}-${hardwareDescription.assembly.version}`
|
|
47
|
+
: `${hardwareDescription.device.id}-${hardwareDescription.device.version}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function getNameFromHardwareDescription(hardwareDescription: HardwareDescription): string {
|
|
51
|
+
return hardwareDescription.assembly
|
|
52
|
+
? hardwareDescription.assembly.name
|
|
53
|
+
: hardwareDescription.device.name;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getSerialNumberFromHardwareDescription(hardwareDescription: HardwareDescription): string {
|
|
57
|
+
return hardwareDescription.assembly
|
|
58
|
+
? hardwareDescription.assembly.serialNumber
|
|
59
|
+
: hardwareDescription.device.serialNumber;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getAllComponentsFromHardwareDescription(hardwareDescription: HardwareDescription): HardwareComponent[] {
|
|
63
|
+
if (hardwareDescription.assembly) {
|
|
64
|
+
return [...hardwareDescription.assembly.components, ...hardwareDescription.device.components];
|
|
65
|
+
} else {
|
|
66
|
+
return hardwareDescription.device.components;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function hardwareComponentsMatch(a: HardwareComponent[], b: HardwareComponent[]): boolean {
|
|
71
|
+
if (a.length === 0 && b.length === 0) {
|
|
72
|
+
return false; // edge case: when both components are empty they don't match since there are no components to compare
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const ac = a.map((c) => `${c.name}-${c.version[0]}`.replace(/\s/g, '').toLocaleLowerCase()).sort();
|
|
76
|
+
const bc = b.map((c) => `${c.name}-${c.version[0]}`.replace(/\s/g, '').toLocaleLowerCase()).sort();
|
|
77
|
+
|
|
78
|
+
return isEqual(ac, bc);
|
|
79
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Observable } from "rxjs";
|
|
2
|
+
import { MonitoringConfig } from "./monitoring-config";
|
|
3
|
+
import { MotionMasterMessage, ParameterValueType } from "./types";
|
|
4
|
+
|
|
5
|
+
export interface MonitoringEntry {
|
|
6
|
+
config: MonitoringConfig;
|
|
7
|
+
interval: number;
|
|
8
|
+
message$: Observable<MotionMasterMessage>;
|
|
9
|
+
values$: Observable<ParameterValueType[]>;
|
|
10
|
+
parameters: MotionMasterMessage.Request.GetDeviceParameterValues.IParameter[];
|
|
11
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Observable } from "rxjs";
|
|
2
|
+
import { v4 } from "uuid";
|
|
3
|
+
import { MonitoringConfig } from "./monitoring-config";
|
|
4
|
+
import { MotionMasterPubSubClient } from "./motion-master-pub-sub-client";
|
|
5
|
+
import { MotionMasterPubSubSocket } from "./motion-master-pub-sub-socket";
|
|
6
|
+
import { MotionMasterReqResClient } from "./motion-master-req-res-client";
|
|
7
|
+
import { MotionMasterReqResSocket } from "./motion-master-req-res-socket";
|
|
8
|
+
import { mapStatusMessageToParameterValues, selectMotionMasterMessageByTopic } from "./operators";
|
|
9
|
+
import { MotionMasterMessage, ParameterAddress } from "./types";
|
|
10
|
+
|
|
11
|
+
export class MotionMasterClient {
|
|
12
|
+
|
|
13
|
+
readonly request: MotionMasterReqResClient;
|
|
14
|
+
readonly monitor: MotionMasterPubSubClient;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly reqResSocket: MotionMasterReqResSocket,
|
|
18
|
+
private readonly pubSubSocket: MotionMasterPubSubSocket,
|
|
19
|
+
) {
|
|
20
|
+
this.request = new MotionMasterReqResClient(this.reqResSocket);
|
|
21
|
+
this.monitor = new MotionMasterPubSubClient(this.pubSubSocket);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
startMonitoringDeviceParameterValues(
|
|
25
|
+
deviceAddress: number,
|
|
26
|
+
parameters: MotionMasterMessage.Request.GetDeviceParameterValues.IParameter[],
|
|
27
|
+
interval: number,
|
|
28
|
+
config: MonitoringConfig,
|
|
29
|
+
requestTimeout = 5000,
|
|
30
|
+
): [string, Observable<MotionMasterMessage>] {
|
|
31
|
+
const props: MotionMasterMessage.Request.IStartMonitoringDeviceParameterValues = {
|
|
32
|
+
interval,
|
|
33
|
+
topic: config.topic,
|
|
34
|
+
getDeviceParameterValues: { deviceAddress, parameters },
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
this.monitor.subscribe(config);
|
|
38
|
+
|
|
39
|
+
this.request.startMonitoringDeviceParameterValues(props, requestTimeout, config.messageId);
|
|
40
|
+
|
|
41
|
+
const message$ = this.monitor.socket.data$.pipe(
|
|
42
|
+
selectMotionMasterMessageByTopic(config.topic),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return [config.messageId, message$];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
startMonitoringValues<T = number[]>(
|
|
49
|
+
deviceAddress: number,
|
|
50
|
+
parameterAddresses: ParameterAddress[],
|
|
51
|
+
interval: number,
|
|
52
|
+
config?: MonitoringConfig,
|
|
53
|
+
requestTimeout = 5000,
|
|
54
|
+
): [string, Observable<T>] {
|
|
55
|
+
const parameters = parameterAddresses.map((addr) => ({ index: addr[0], subindex: addr[1], loadFromCache: false }));
|
|
56
|
+
|
|
57
|
+
if (!config) {
|
|
58
|
+
config = { messageId: v4(), topic: v4(), bufferSize: 1, distinct: false };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const [messageId, message$] = this.startMonitoringDeviceParameterValues(deviceAddress, parameters, interval, config, requestTimeout);
|
|
62
|
+
|
|
63
|
+
const values$ = message$.pipe(
|
|
64
|
+
mapStatusMessageToParameterValues(),
|
|
65
|
+
) as unknown as Observable<T>;
|
|
66
|
+
|
|
67
|
+
return [messageId, values$];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
startMonitoring<T = number[]>(
|
|
71
|
+
deviceAddress: number,
|
|
72
|
+
parameterAddresses: [number, number][],
|
|
73
|
+
interval: number,
|
|
74
|
+
config?: MonitoringConfig,
|
|
75
|
+
requestTimeout = 5000,
|
|
76
|
+
): Observable<T> {
|
|
77
|
+
return new Observable<T>((subscriber) => {
|
|
78
|
+
const [messageId, values$] = this.startMonitoringValues<T>(deviceAddress, parameterAddresses, interval, config, requestTimeout);
|
|
79
|
+
|
|
80
|
+
const subscription = values$.subscribe(subscriber);
|
|
81
|
+
|
|
82
|
+
return () => {
|
|
83
|
+
subscription.unsubscribe();
|
|
84
|
+
this.stopMonitoring(messageId);
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
stopMonitoring(messageId: string): void {
|
|
90
|
+
this.request.stopMonitoringDeviceParameterValues({ startMonitoringRequestId: messageId });
|
|
91
|
+
this.monitor.unsubscribe(messageId);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|