motion-master-client 0.0.55 → 0.0.56

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 (132) hide show
  1. package/.babelrc +3 -0
  2. package/.eslintrc.json +18 -0
  3. package/README.md +123 -123
  4. package/jest.config.ts +16 -0
  5. package/motion-master.proto +1861 -0
  6. package/package.json +6 -21
  7. package/project.json +45 -0
  8. package/src/{index.d.ts → index.ts} +26 -26
  9. package/src/lib/cia402.spec.ts +77 -0
  10. package/src/lib/cia402.ts +414 -0
  11. package/src/lib/config-file.spec.ts +114 -0
  12. package/src/lib/config-file.ts +63 -0
  13. package/src/lib/device-log-line.ts +5 -0
  14. package/src/lib/device-parameter.spec.ts +85 -0
  15. package/src/lib/device-parameter.ts +79 -0
  16. package/src/lib/device.ts +10 -0
  17. package/src/lib/hardware-description.spec.ts +253 -0
  18. package/src/lib/hardware-description.ts +129 -0
  19. package/src/lib/logger.ts +5 -0
  20. package/src/lib/monitoring-config.ts +6 -0
  21. package/src/lib/{monitoring-entry.d.ts → monitoring-entry.ts} +10 -9
  22. package/src/lib/motion-master-client.ts +266 -0
  23. package/src/lib/motion-master-pub-sub-client.ts +100 -0
  24. package/src/lib/motion-master-pub-sub-socket.ts +46 -0
  25. package/src/lib/motion-master-pub-sub-web-socket.ts +77 -0
  26. package/src/lib/motion-master-pub-sub-worker-socket.ts +57 -0
  27. package/src/lib/motion-master-req-res-client.spec.ts +740 -0
  28. package/src/lib/motion-master-req-res-client.ts +2211 -0
  29. package/src/lib/motion-master-req-res-socket.ts +68 -0
  30. package/src/lib/motion-master-req-res-web-socket.ts +123 -0
  31. package/src/lib/motion-master-req-res-worker-socket.ts +89 -0
  32. package/src/lib/motion-master.proto.d.ts +5183 -5083
  33. package/src/lib/motion-master.proto.js +53218 -52284
  34. package/src/lib/operators.ts +108 -0
  35. package/src/lib/options.ts +12 -0
  36. package/src/lib/parameter.spec.ts +160 -0
  37. package/src/lib/parameter.ts +170 -0
  38. package/src/lib/product-id-range.ts +8 -0
  39. package/src/lib/request-status-resolver.ts +403 -0
  40. package/src/lib/system-log-line.ts +9 -0
  41. package/src/lib/{types.d.ts → types.ts} +141 -209
  42. package/src/lib/urls.ts +6 -0
  43. package/src/lib/util.ts +332 -0
  44. package/src/lib/web-socket-connection-close-codes.ts +85 -0
  45. package/tsconfig.json +23 -0
  46. package/tsconfig.lib.json +10 -0
  47. package/tsconfig.spec.json +20 -0
  48. package/typedoc.json +10 -0
  49. package/src/index.js +0 -30
  50. package/src/index.js.map +0 -1
  51. package/src/lib/cia402.d.ts +0 -182
  52. package/src/lib/cia402.js +0 -392
  53. package/src/lib/cia402.js.map +0 -1
  54. package/src/lib/config-file.d.ts +0 -13
  55. package/src/lib/config-file.js +0 -50
  56. package/src/lib/config-file.js.map +0 -1
  57. package/src/lib/device-log-line.d.ts +0 -5
  58. package/src/lib/device-log-line.js +0 -3
  59. package/src/lib/device-log-line.js.map +0 -1
  60. package/src/lib/device-parameter.d.ts +0 -56
  61. package/src/lib/device-parameter.js +0 -39
  62. package/src/lib/device-parameter.js.map +0 -1
  63. package/src/lib/device.d.ts +0 -9
  64. package/src/lib/device.js +0 -3
  65. package/src/lib/device.js.map +0 -1
  66. package/src/lib/hardware-description.d.ts +0 -41
  67. package/src/lib/hardware-description.js +0 -94
  68. package/src/lib/hardware-description.js.map +0 -1
  69. package/src/lib/logger.d.ts +0 -1
  70. package/src/lib/logger.js +0 -8
  71. package/src/lib/logger.js.map +0 -1
  72. package/src/lib/monitoring-config.d.ts +0 -6
  73. package/src/lib/monitoring-config.js +0 -3
  74. package/src/lib/monitoring-config.js.map +0 -1
  75. package/src/lib/monitoring-entry.js +0 -3
  76. package/src/lib/monitoring-entry.js.map +0 -1
  77. package/src/lib/motion-master-client.d.ts +0 -56
  78. package/src/lib/motion-master-client.js +0 -167
  79. package/src/lib/motion-master-client.js.map +0 -1
  80. package/src/lib/motion-master-pub-sub-client.d.ts +0 -17
  81. package/src/lib/motion-master-pub-sub-client.js +0 -73
  82. package/src/lib/motion-master-pub-sub-client.js.map +0 -1
  83. package/src/lib/motion-master-pub-sub-socket.d.ts +0 -42
  84. package/src/lib/motion-master-pub-sub-socket.js +0 -3
  85. package/src/lib/motion-master-pub-sub-socket.js.map +0 -1
  86. package/src/lib/motion-master-pub-sub-web-socket.d.ts +0 -18
  87. package/src/lib/motion-master-pub-sub-web-socket.js +0 -66
  88. package/src/lib/motion-master-pub-sub-web-socket.js.map +0 -1
  89. package/src/lib/motion-master-pub-sub-worker-socket.d.ts +0 -18
  90. package/src/lib/motion-master-pub-sub-worker-socket.js +0 -48
  91. package/src/lib/motion-master-pub-sub-worker-socket.js.map +0 -1
  92. package/src/lib/motion-master-req-res-client.d.ts +0 -947
  93. package/src/lib/motion-master-req-res-client.js +0 -1735
  94. package/src/lib/motion-master-req-res-client.js.map +0 -1
  95. package/src/lib/motion-master-req-res-socket.d.ts +0 -60
  96. package/src/lib/motion-master-req-res-socket.js +0 -3
  97. package/src/lib/motion-master-req-res-socket.js.map +0 -1
  98. package/src/lib/motion-master-req-res-web-socket.d.ts +0 -28
  99. package/src/lib/motion-master-req-res-web-socket.js +0 -98
  100. package/src/lib/motion-master-req-res-web-socket.js.map +0 -1
  101. package/src/lib/motion-master-req-res-worker-socket.d.ts +0 -24
  102. package/src/lib/motion-master-req-res-worker-socket.js +0 -72
  103. package/src/lib/motion-master-req-res-worker-socket.js.map +0 -1
  104. package/src/lib/operators.d.ts +0 -20
  105. package/src/lib/operators.js +0 -84
  106. package/src/lib/operators.js.map +0 -1
  107. package/src/lib/options.d.ts +0 -10
  108. package/src/lib/options.js +0 -14
  109. package/src/lib/options.js.map +0 -1
  110. package/src/lib/parameter.d.ts +0 -72
  111. package/src/lib/parameter.js +0 -119
  112. package/src/lib/parameter.js.map +0 -1
  113. package/src/lib/product-id-range.d.ts +0 -7
  114. package/src/lib/product-id-range.js +0 -12
  115. package/src/lib/product-id-range.js.map +0 -1
  116. package/src/lib/request-status-resolver.d.ts +0 -4
  117. package/src/lib/request-status-resolver.js +0 -345
  118. package/src/lib/request-status-resolver.js.map +0 -1
  119. package/src/lib/system-log-line.d.ts +0 -9
  120. package/src/lib/system-log-line.js +0 -3
  121. package/src/lib/system-log-line.js.map +0 -1
  122. package/src/lib/types.js +0 -29
  123. package/src/lib/types.js.map +0 -1
  124. package/src/lib/urls.d.ts +0 -3
  125. package/src/lib/urls.js +0 -10
  126. package/src/lib/urls.js.map +0 -1
  127. package/src/lib/util.d.ts +0 -42
  128. package/src/lib/util.js +0 -327
  129. package/src/lib/util.js.map +0 -1
  130. package/src/lib/web-socket-connection-close-codes.d.ts +0 -8
  131. package/src/lib/web-socket-connection-close-codes.js +0 -89
  132. package/src/lib/web-socket-connection-close-codes.js.map +0 -1
@@ -0,0 +1,114 @@
1
+ import { ConfigFile } from './config-file';
2
+
3
+ const content = `META,FORMAT,2
4
+ # 8502-03
5
+ # v5.1.0-rc.4
6
+ 0x2001, 0, 2969
7
+ 0x2002, 0, 2
8
+ 0x2003, 1, 4
9
+ 0x2003, 2, 100000
10
+ 0x2003, 3, 250000
11
+ 0x2003, 4, 300
12
+ 0x2213, 1, 0
13
+ 0x2213, 2, 0
14
+ 0x2213, 3, 0
15
+ 0x2214, 1, 1
16
+ 0x2003, 5, 1
17
+ 0x6080, 0, 3750000
18
+ 0x6081, 0, 20000
19
+ 0x6083, 0, 30000
20
+ 0x2004, 1, 0
21
+ 0x2004, 2, 0
22
+ 0x2004, 3, 0
23
+ 0x2004, 4, 0
24
+ 0x20f2, 0, YOCTO
25
+ 0x2004, 5, 100
26
+ 0x2004, 6, 20
27
+ 0x6092, 1, 4294967295
28
+ 0x6092, 2, 1
29
+ 0x6098, 0, 0
30
+ 0x6099, 1, 0
31
+ `;
32
+
33
+ const contentNoHeader = `0x2001, 0, 2969
34
+ 0x2002, 0, 2
35
+ 0x2003, 1, 4
36
+ `;
37
+
38
+ describe('ConfigFile', () => {
39
+
40
+ describe('constructor', () => {
41
+
42
+ it('should parse the config file with header', () => {
43
+ const configFile = new ConfigFile(content);
44
+
45
+ expect(configFile.apiId).toBe('8502-03');
46
+ expect(configFile.firmwareVersion).toBe('v5.1.0-rc.4');
47
+ expect(configFile.toString()).toBe(`META,FORMAT,2
48
+ # 8502-03
49
+ # v5.1.0-rc.4
50
+ 0x2001, 0, 2969
51
+ 0x2002, 0, 2
52
+ 0x2003, 1, 4
53
+ 0x2003, 2, 100000
54
+ 0x2003, 3, 250000
55
+ 0x2003, 4, 300
56
+ 0x2003, 5, 1
57
+ 0x2004, 1, 0
58
+ 0x2004, 2, 0
59
+ 0x2004, 3, 0
60
+ 0x2004, 4, 0
61
+ 0x2004, 5, 100
62
+ 0x2004, 6, 20
63
+ 0x20f2, 0, YOCTO
64
+ 0x2213, 1, 0
65
+ 0x2213, 2, 0
66
+ 0x2213, 3, 0
67
+ 0x2214, 1, 1
68
+ 0x6080, 0, 3750000
69
+ 0x6081, 0, 20000
70
+ 0x6083, 0, 30000
71
+ 0x6092, 1, 4294967295
72
+ 0x6092, 2, 1
73
+ 0x6098, 0, 0
74
+ 0x6099, 1, 0
75
+ `);
76
+ });
77
+
78
+ it('should throw an exception if parse fails', () => {
79
+ const t = () => {
80
+ new ConfigFile(`
81
+ asdfasdf
82
+ `);
83
+ };
84
+ expect(t).toThrow('Failed to parse the config csv file');
85
+ });
86
+
87
+ it('should parse a config file without header', () => {
88
+ const configFile = new ConfigFile(contentNoHeader);
89
+
90
+ expect(configFile.toString()).toBe(`0x2001, 0, 2969
91
+ 0x2002, 0, 2
92
+ 0x2003, 1, 4
93
+ `)
94
+ });
95
+
96
+ });
97
+
98
+ describe('toString', () => {
99
+ it('should assemble the config file from changed parameters', () => {
100
+ const configFile = new ConfigFile(content);
101
+ configFile.parameters = configFile.parameters.slice(0, 3);
102
+ configFile.parameters[1].value = 123;
103
+
104
+ expect(configFile.toString()).toBe(`META,FORMAT,2
105
+ # 8502-03
106
+ # v5.1.0-rc.4
107
+ 0x2001, 0, 2969
108
+ 0x2002, 0, 123
109
+ 0x2003, 1, 4
110
+ `);
111
+ });
112
+ })
113
+
114
+ });
@@ -0,0 +1,63 @@
1
+ import * as Papa from 'papaparse';
2
+ import { Parameter, parametersCompareFn } from './parameter';
3
+ import { Optional } from './types';
4
+
5
+ export type ConfigParameter = Optional<Parameter, 'name' | 'typeValueKey'>;
6
+
7
+ export class ConfigFile {
8
+
9
+ readonly apiId?: string;
10
+ readonly firmwareVersion?: string;
11
+ readonly header?: string;
12
+
13
+ parameters: ConfigParameter[];
14
+
15
+ constructor(
16
+ public readonly content: string,
17
+ public readonly file?: Pick<File, 'name' | 'type' | 'size' | 'lastModified'>,
18
+ ) {
19
+ const parseResult = Papa.parse<string[]>(content, {
20
+ skipEmptyLines: true,
21
+ transform: (value: string) => value.trim(),
22
+ });
23
+
24
+ if (parseResult?.errors?.length > 0) {
25
+ throw new Error('Failed to parse the config csv file');
26
+ }
27
+
28
+ const matchApiId = content.match(/^#\s+(\d{4}-\d{2})$/m);
29
+ if (matchApiId) {
30
+ this.apiId = matchApiId[1];
31
+ }
32
+
33
+ const matchFirmwareVersion = content.match(/^#\s+(v\d.*)$/m);
34
+ if (matchFirmwareVersion) {
35
+ this.firmwareVersion = matchFirmwareVersion[1];
36
+ }
37
+
38
+ const matchFirstParameterRow = content.match(/^0x\d{4}/m);
39
+ if (matchFirstParameterRow?.index) {
40
+ this.header = content.slice(0, matchFirstParameterRow.index - 1);
41
+ }
42
+
43
+ this.parameters = parseResult.data
44
+ .filter(([c0]) => c0.startsWith('0x'))
45
+ .map(([c0, c1, c2]) => {
46
+ const index = parseInt(c0, 16);
47
+ const subindex = parseInt(c1, 10);
48
+ const numValue = Number(c2);
49
+ const value = isNaN(numValue) ? c2 : numValue;
50
+ return { index, subindex, value };
51
+ })
52
+ .sort(parametersCompareFn);
53
+ }
54
+
55
+ toString(): string {
56
+ let out = this.parameters.map((p) => `0x${p.index?.toString(16)}, ${p.subindex?.toString(10)}, ${p.value}`).join('\n');
57
+ if (this.header) {
58
+ out = this.header + '\n' + out;
59
+ }
60
+ return out + '\n';
61
+ }
62
+
63
+ }
@@ -0,0 +1,5 @@
1
+ export interface DeviceLogLine {
2
+ time: string;
3
+ level: string;
4
+ message: string;
5
+ }
@@ -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,79 @@
1
+ import { makeParameterId, Parameter } from "./parameter";
2
+
3
+ export interface DeviceParameter extends Parameter {
4
+ id: string;
5
+ flags?: {
6
+ access?: 'ro' | 'rw' | 'wo'; // readonly (default), readwrite, writeonly
7
+ category?: 'm' | 'o' | 'c'; // mandatory, optional (default), conditional
8
+ pdoMapping?: 't' | 'r' | 'tr'; // Transmit PDO (Inputs), Receive PDO (Outputs), Transmit or Receive PDO
9
+ safetyMapping?: 'si' | 'so' | 'sio' | 'sp'; // Safe Inputs, Safe Outputs, Safe Input or Output, Safety Parameter Set
10
+ };
11
+ }
12
+
13
+ /**
14
+ * Make device parameter id by providing a device serial number and tuple of index and subindex.
15
+ *
16
+ * @param serialNumber - device serial number from the hardware description file
17
+ * @param tuple - an array of index and subindex
18
+ * @throws {Error} if index or subindex are less than 0
19
+ * @returns combined index and subindex in uppercase hexadecimal format, e.g. "0x60FE:02"
20
+ */
21
+ export function makeDeviceParameterId(serialNumber: string, tuple: [(number | null | undefined), (number | null | undefined)]): string;
22
+
23
+ /**
24
+ * Make device parameter id by providing a device serial number and object which has index and subindex properties.
25
+ *
26
+ * @param serialNumber - device serial number from the hardware description file
27
+ * @param parameter - an object with optional index and subindex properties
28
+ * @throws {Error} if index or subindex are less than 0
29
+ * @returns combined index and subindex in uppercase hexadecimal format, e.g. "0x60FE:02"
30
+ */
31
+ export function makeDeviceParameterId(serialNumber: string, parameter: { index?: (number | null), subindex?: (number | null) }): string;
32
+
33
+ /**
34
+ * Make parameter id by providing a device serial number and index and subindex.
35
+ *
36
+ * @param serialNumber - device serial number from the hardware description file
37
+ * @param index - from 0x0000 to 0xFFFF for objects defined in ESI and >0xFFFF for custom object
38
+ * @param subindex - defaults to 0 if not provided
39
+ * @throws {Error} if index or subindex are less than 0
40
+ * @returns combined index and subindex in uppercase hexadecimal format, e.g. "0x60FE:02"
41
+ */
42
+ export function makeDeviceParameterId(serialNumber: string, index?: (number | null), subindex?: (number | null)): string;
43
+
44
+ export function makeDeviceParameterId(serialNumber: string, a?: (number | null) | { index?: (number | null), subindex?: (number | null) } | [(number | null | undefined), (number | null | undefined)], b?: (number | null)): string {
45
+ const parameterId = makeParameterId(a, b);
46
+ return `${parameterId}.${serialNumber}`;
47
+ }
48
+
49
+ /**
50
+ * Example of device parameter id is "0x2110:1A.8502-03-0001353-2115" where:
51
+ * - 0x2110 is object index in hexadecimal format
52
+ * - 1A is subindex in hexadecimal format
53
+ * - 8502-03-0001353-2115 is device serial number from hardware description file
54
+ */
55
+ export const deviceParameterIdRegExp = /^0x([0-9a-fA-F]{4,}):([0-9a-fA-F]{2})\.([\d-]+)$/;
56
+
57
+ /**
58
+ * Split device parameter id into parts.
59
+ *
60
+ * @param id - device parameter id like "0x2110:1A.8502-03-0001353-2115"
61
+ * @returns tuple of device serial number, index, and subindex
62
+ */
63
+ export function splitDeviceParameterId(id: string): [string, number, number] {
64
+ const match = id.match(deviceParameterIdRegExp);
65
+
66
+ if (!match) {
67
+ throw new Error(`Device parameter id "${id}" doesn't match the regular expression: ${deviceParameterIdRegExp}`);
68
+ }
69
+
70
+ return [
71
+ match[3], // device serial number
72
+ parseInt(match[1], 16), // index
73
+ parseInt(match[2], 16), // subindex
74
+ ];
75
+ }
76
+
77
+ export function isDeviceParameterId(id: string): boolean {
78
+ return deviceParameterIdRegExp.test(id);
79
+ }
@@ -0,0 +1,10 @@
1
+ import { HardwareDescription } from "./hardware-description";
2
+
3
+ export interface Device {
4
+ id: string;
5
+ deviceAddress: number;
6
+ type?: number,
7
+ position?: number;
8
+ alias?: number;
9
+ hardwareDescription?: HardwareDescription;
10
+ }
@@ -0,0 +1,253 @@
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
+ it('should return api identifier from device having keyId', () => {
31
+ const result = getApiIdentifierFromHardwareDescription({
32
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn', keyId: '1234' },
33
+ fileVersion: '',
34
+ } as HardwareDescription);
35
+
36
+ expect(result).toBe('bar-02-1234');
37
+ });
38
+
39
+ it('should return api identifier from device when having both assembly and keyId', () => {
40
+ const result = getApiIdentifierFromHardwareDescription({
41
+ assembly: { id: 'asm', version: '09', serialNumber: 'asm-sn', name: 'Assembly' },
42
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn', keyId: '3388' },
43
+ fileVersion: '',
44
+ } as HardwareDescription);
45
+
46
+ expect(result).toBe('asm-09-3388');
47
+ });
48
+
49
+ it('should skip keyId in cases when product image needs to be fetched by api identifier without keyId', () => {
50
+ const result = getApiIdentifierFromHardwareDescription({
51
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn', keyId: '1234' },
52
+ fileVersion: '',
53
+ } as HardwareDescription, true);
54
+
55
+ expect(result).toBe('bar-02');
56
+ });
57
+ });
58
+
59
+ describe('getNameFromHardwareDescription', () => {
60
+ it('should return name from assembly', () => {
61
+ const result = getNameFromHardwareDescription({
62
+ assembly: { id: 'foo', version: '01', serialNumber: 'foo-sn', name: 'Assembly' }, // prefer assembly over device
63
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn', name: 'Device' },
64
+ fileVersion: '',
65
+ } as HardwareDescription);
66
+
67
+ expect(result).toBe('Assembly');
68
+ });
69
+
70
+ it('should return name from device', () => {
71
+ const result = getNameFromHardwareDescription({
72
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn', name: 'Device' },
73
+ fileVersion: '',
74
+ } as HardwareDescription);
75
+
76
+ expect(result).toBe('Device');
77
+ });
78
+ });
79
+
80
+ describe('getSerialNumberFromHardwareDescription', () => {
81
+ it('should return serial number from assembly', () => {
82
+ const result = getSerialNumberFromHardwareDescription({
83
+ assembly: { id: 'foo', version: '01', serialNumber: 'foo-sn' }, // prefer assembly over device
84
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn' },
85
+ fileVersion: '',
86
+ } as HardwareDescription);
87
+
88
+ expect(result).toBe('foo-sn');
89
+ });
90
+
91
+ it('should return serial number from device', () => {
92
+ const result = getSerialNumberFromHardwareDescription({
93
+ device: { id: 'bar', version: '02', serialNumber: 'bar-sn' },
94
+ fileVersion: '',
95
+ } as HardwareDescription);
96
+
97
+ expect(result).toBe('bar-sn');
98
+ });
99
+ });
100
+
101
+ describe('getAllComponentsFromHardwareDescription', () => {
102
+ it('should return components only from device when assembly is undefined', () => {
103
+ const deviceComponents = [
104
+ {
105
+ name: 'Com EtherCAT',
106
+ serialNumber: '3333-33-3333333-3333',
107
+ version: 'B.2',
108
+ },
109
+ {
110
+ name: 'Core C2X',
111
+ serialNumber: '1111-11-1111111-1111',
112
+ version: 'A.5',
113
+ },
114
+ {
115
+ name: 'Drive 400',
116
+ serialNumber: '2222-22-2222222-2222',
117
+ version: 'E.1',
118
+ },
119
+ ];
120
+
121
+ const hardwareDescription: HardwareDescription = {
122
+ device: {
123
+ components: deviceComponents,
124
+ id: '8503',
125
+ macAddress: '01-23-45-67-89-AB',
126
+ name: 'Circulo 9 1800 Encoder Pos 1 & 2',
127
+ serialNumber: '8506-01-040595-4023',
128
+ version: '02',
129
+ keyId: '1234',
130
+ },
131
+ fileVersion: '1.0.0',
132
+ };
133
+
134
+ const result = getAllComponentsFromHardwareDescription(hardwareDescription);
135
+
136
+ expect(result).toEqual(deviceComponents);
137
+ });
138
+
139
+ it('should return combined components from assembly and device', () => {
140
+ const assemblyComponents = [
141
+ {
142
+ name: 'Heidrive HMP04',
143
+ serialNumber: '79137447',
144
+ version: 'REV-2',
145
+ },
146
+ {
147
+ name: 'KEB gearbox',
148
+ serialNumber: '12344234',
149
+ version: 'REV-3',
150
+ },
151
+ ];
152
+
153
+ const deviceComponents = [
154
+ {
155
+ name: 'Com EtherCAT',
156
+ serialNumber: '3333-33-3333333-3333',
157
+ version: 'B.2',
158
+ },
159
+ {
160
+ name: 'Core C2X',
161
+ serialNumber: '1111-11-1111111-1111',
162
+ version: 'A.5',
163
+ },
164
+ {
165
+ name: 'Drive 400',
166
+ serialNumber: '2222-22-2222222-2222',
167
+ version: 'E.1',
168
+ },
169
+ ];
170
+
171
+ const hardwareDescription: HardwareDescription = {
172
+ assembly: {
173
+ components: assemblyComponents,
174
+ id: 'ASM',
175
+ name: 'Assembly',
176
+ serialNumber: '12345',
177
+ version: '01',
178
+ },
179
+ device: {
180
+ components: deviceComponents,
181
+ id: '8503',
182
+ macAddress: '01-23-45-67-89-AB',
183
+ name: 'Circulo 9 1800 Encoder Pos 1 & 2',
184
+ serialNumber: '8506-01-040595-4023',
185
+ version: '02',
186
+ keyId: '1234',
187
+ },
188
+ fileVersion: '1.0.0',
189
+ };
190
+
191
+ const result = getAllComponentsFromHardwareDescription(hardwareDescription);
192
+
193
+ expect(result).toEqual([...assemblyComponents, ...deviceComponents]);
194
+ });
195
+ });
196
+
197
+ describe('hardwareComponentsMatch', () => {
198
+ it('should return false when both arrays are empty', () => {
199
+ expect(hardwareComponentsMatch([], [])).toBe(false);
200
+ });
201
+
202
+ it('should return false when components don\'t match', () => {
203
+ const components1 = [
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
+ const components2 = [
208
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'A.2' },
209
+ { name: 'Core C22', serialNumber: '1111-11-1111111-1111', version: 'A.1' },
210
+ ];
211
+
212
+ expect(hardwareComponentsMatch(components1, components2)).toBe(false);
213
+ });
214
+
215
+ it('should return true when components match', () => {
216
+ const components1 = [
217
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
218
+ { name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
219
+ ];
220
+ const components2 = [
221
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
222
+ { name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
223
+ ];
224
+
225
+ expect(hardwareComponentsMatch(components1, components2)).toBe(true);
226
+ });
227
+
228
+ it('should return true when components match but are not ordered the same', () => {
229
+ const components1 = [
230
+ { name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
231
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
232
+ ];
233
+ const components2 = [
234
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
235
+ { name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
236
+ ];
237
+
238
+ expect(hardwareComponentsMatch(components1, components2)).toBe(true);
239
+ });
240
+
241
+ it('should return true when revision numbers don\'t match', () => {
242
+ const components1 = [
243
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.2' },
244
+ { name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.5' },
245
+ ];
246
+ const components2 = [
247
+ { name: 'Com EtherCAT', serialNumber: '3333-33-3333333-3333', version: 'B.7' },
248
+ { name: 'Core C2X', serialNumber: '1111-11-1111111-1111', version: 'A.2' },
249
+ ];
250
+
251
+ expect(hardwareComponentsMatch(components1, components2)).toBe(true);
252
+ });
253
+ });