motion-master-client 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/.babelrc +3 -0
  2. package/.eslintrc.json +18 -0
  3. package/jest.config.ts +16 -0
  4. package/motion-master.proto +1822 -0
  5. package/package.json +2 -17
  6. package/project.json +45 -0
  7. package/src/lib/cia402.spec.ts +77 -0
  8. package/src/lib/cia402.ts +414 -0
  9. package/src/lib/config-file.spec.ts +114 -0
  10. package/src/lib/config-file.ts +63 -0
  11. package/src/lib/device-log-line.ts +5 -0
  12. package/src/lib/device-parameter.spec.ts +85 -0
  13. package/src/lib/device-parameter.ts +79 -0
  14. package/src/lib/device.ts +10 -0
  15. package/src/lib/hardware-description.spec.ts +253 -0
  16. package/src/lib/hardware-description.ts +129 -0
  17. package/src/lib/logger.ts +5 -0
  18. package/src/lib/monitoring-config.ts +6 -0
  19. package/src/lib/{monitoring-entry.d.ts → monitoring-entry.ts} +5 -4
  20. package/src/lib/motion-master-client.ts +221 -0
  21. package/src/lib/motion-master-pub-sub-client.ts +95 -0
  22. package/src/lib/motion-master-pub-sub-socket.ts +40 -0
  23. package/src/lib/motion-master-pub-sub-web-socket.ts +78 -0
  24. package/src/lib/motion-master-pub-sub-worker-socket.ts +51 -0
  25. package/src/lib/motion-master-req-res-client.spec.ts +740 -0
  26. package/src/lib/motion-master-req-res-client.ts +2120 -0
  27. package/src/lib/motion-master-req-res-socket.ts +62 -0
  28. package/src/lib/motion-master-req-res-web-socket.ts +124 -0
  29. package/src/lib/motion-master-req-res-worker-socket.ts +87 -0
  30. package/src/lib/motion-master.proto.js +2 -2
  31. package/src/lib/operators.ts +90 -0
  32. package/src/lib/options.ts +12 -0
  33. package/src/lib/parameter.spec.ts +160 -0
  34. package/src/lib/parameter.ts +170 -0
  35. package/src/lib/product-id-range.ts +8 -0
  36. package/src/lib/request-status-resolver.ts +403 -0
  37. package/src/lib/system-log-line.ts +9 -0
  38. package/src/lib/{types.d.ts → types.ts} +74 -143
  39. package/src/lib/urls.ts +6 -0
  40. package/src/lib/util.ts +305 -0
  41. package/tsconfig.json +23 -0
  42. package/tsconfig.lib.json +10 -0
  43. package/tsconfig.spec.json +20 -0
  44. package/typedoc.json +10 -0
  45. package/src/index.js +0 -29
  46. package/src/index.js.map +0 -1
  47. package/src/lib/cia402.d.ts +0 -182
  48. package/src/lib/cia402.js +0 -392
  49. package/src/lib/cia402.js.map +0 -1
  50. package/src/lib/config-file.d.ts +0 -13
  51. package/src/lib/config-file.js +0 -50
  52. package/src/lib/config-file.js.map +0 -1
  53. package/src/lib/device-log-line.d.ts +0 -5
  54. package/src/lib/device-log-line.js +0 -3
  55. package/src/lib/device-log-line.js.map +0 -1
  56. package/src/lib/device-parameter.d.ts +0 -56
  57. package/src/lib/device-parameter.js +0 -39
  58. package/src/lib/device-parameter.js.map +0 -1
  59. package/src/lib/device.d.ts +0 -9
  60. package/src/lib/device.js +0 -3
  61. package/src/lib/device.js.map +0 -1
  62. package/src/lib/hardware-description.d.ts +0 -41
  63. package/src/lib/hardware-description.js +0 -94
  64. package/src/lib/hardware-description.js.map +0 -1
  65. package/src/lib/logger.d.ts +0 -1
  66. package/src/lib/logger.js +0 -8
  67. package/src/lib/logger.js.map +0 -1
  68. package/src/lib/monitoring-config.d.ts +0 -6
  69. package/src/lib/monitoring-config.js +0 -3
  70. package/src/lib/monitoring-config.js.map +0 -1
  71. package/src/lib/monitoring-entry.js +0 -3
  72. package/src/lib/monitoring-entry.js.map +0 -1
  73. package/src/lib/motion-master-client.d.ts +0 -52
  74. package/src/lib/motion-master-client.js +0 -151
  75. package/src/lib/motion-master-client.js.map +0 -1
  76. package/src/lib/motion-master-pub-sub-client.d.ts +0 -16
  77. package/src/lib/motion-master-pub-sub-client.js +0 -68
  78. package/src/lib/motion-master-pub-sub-client.js.map +0 -1
  79. package/src/lib/motion-master-pub-sub-socket.d.ts +0 -34
  80. package/src/lib/motion-master-pub-sub-socket.js +0 -3
  81. package/src/lib/motion-master-pub-sub-socket.js.map +0 -1
  82. package/src/lib/motion-master-pub-sub-web-socket.d.ts +0 -14
  83. package/src/lib/motion-master-pub-sub-web-socket.js +0 -67
  84. package/src/lib/motion-master-pub-sub-web-socket.js.map +0 -1
  85. package/src/lib/motion-master-pub-sub-worker-socket.d.ts +0 -14
  86. package/src/lib/motion-master-pub-sub-worker-socket.js +0 -42
  87. package/src/lib/motion-master-pub-sub-worker-socket.js.map +0 -1
  88. package/src/lib/motion-master-req-res-client.d.ts +0 -920
  89. package/src/lib/motion-master-req-res-client.js +0 -1680
  90. package/src/lib/motion-master-req-res-client.js.map +0 -1
  91. package/src/lib/motion-master-req-res-socket.d.ts +0 -52
  92. package/src/lib/motion-master-req-res-socket.js +0 -3
  93. package/src/lib/motion-master-req-res-socket.js.map +0 -1
  94. package/src/lib/motion-master-req-res-web-socket.d.ts +0 -24
  95. package/src/lib/motion-master-req-res-web-socket.js +0 -99
  96. package/src/lib/motion-master-req-res-web-socket.js.map +0 -1
  97. package/src/lib/motion-master-req-res-worker-socket.d.ts +0 -20
  98. package/src/lib/motion-master-req-res-worker-socket.js +0 -69
  99. package/src/lib/motion-master-req-res-worker-socket.js.map +0 -1
  100. package/src/lib/operators.d.ts +0 -18
  101. package/src/lib/operators.js +0 -76
  102. package/src/lib/operators.js.map +0 -1
  103. package/src/lib/options.d.ts +0 -10
  104. package/src/lib/options.js +0 -14
  105. package/src/lib/options.js.map +0 -1
  106. package/src/lib/parameter.d.ts +0 -72
  107. package/src/lib/parameter.js +0 -119
  108. package/src/lib/parameter.js.map +0 -1
  109. package/src/lib/product-id-range.d.ts +0 -7
  110. package/src/lib/product-id-range.js +0 -12
  111. package/src/lib/product-id-range.js.map +0 -1
  112. package/src/lib/request-status-resolver.d.ts +0 -4
  113. package/src/lib/request-status-resolver.js +0 -345
  114. package/src/lib/request-status-resolver.js.map +0 -1
  115. package/src/lib/system-log-line.d.ts +0 -9
  116. package/src/lib/system-log-line.js +0 -3
  117. package/src/lib/system-log-line.js.map +0 -1
  118. package/src/lib/types.js +0 -28
  119. package/src/lib/types.js.map +0 -1
  120. package/src/lib/urls.d.ts +0 -3
  121. package/src/lib/urls.js +0 -10
  122. package/src/lib/urls.js.map +0 -1
  123. package/src/lib/util.d.ts +0 -40
  124. package/src/lib/util.js +0 -316
  125. package/src/lib/util.js.map +0 -1
  126. /package/src/{index.d.ts → index.ts} +0 -0
package/package.json CHANGED
@@ -1,21 +1,6 @@
1
1
  {
2
2
  "name": "motion-master-client",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "type": "commonjs",
5
- "description": "A library and CLI program used for communicating with Motion Master.",
6
- "dependencies": {
7
- "fast-deep-equal": "^3.1.3",
8
- "lodash": "^4.17.21",
9
- "papaparse": "^5.4.1",
10
- "protobufjs": "^7.2.3",
11
- "roarr": "^7.15.0",
12
- "rxjs": "^7.8.1",
13
- "semver": "7.4.0",
14
- "uuid": "^9.0.0"
15
- },
16
- "peerDependencies": {
17
- "tslib": "2.5.2"
18
- },
19
- "main": "./src/index.js",
20
- "types": "./src/index.d.ts"
5
+ "description": "A library and CLI program used for communicating with Motion Master."
21
6
  }
package/project.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "motion-master-client",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "libs/motion-master-client/src",
5
+ "projectType": "library",
6
+ "targets": {
7
+ "build": {
8
+ "executor": "@nrwl/js:tsc",
9
+ "outputs": ["{options.outputPath}"],
10
+ "options": {
11
+ "outputPath": "dist/libs/motion-master-client",
12
+ "main": "libs/motion-master-client/src/index.ts",
13
+ "tsConfig": "libs/motion-master-client/tsconfig.lib.json",
14
+ "assets": [
15
+ "libs/motion-master-client/*.md",
16
+ "libs/motion-master-client/src/lib/motion-master.proto.js",
17
+ "libs/motion-master-client/src/lib/motion-master.proto.d.ts"
18
+ ]
19
+ }
20
+ },
21
+ "publish": {
22
+ "executor": "nx:run-commands",
23
+ "options": {
24
+ "command": "node tools/scripts/publish.mjs motion-master-client {args.ver} {args.tag}"
25
+ },
26
+ "dependsOn": ["build"]
27
+ },
28
+ "lint": {
29
+ "executor": "@nx/linter:eslint",
30
+ "outputs": ["{options.outputFile}"],
31
+ "options": {
32
+ "lintFilePatterns": ["libs/motion-master-client/**/*.ts"]
33
+ }
34
+ },
35
+ "test": {
36
+ "executor": "@nx/jest:jest",
37
+ "outputs": ["{workspaceRoot}/coverage/libs/motion-master-client"],
38
+ "options": {
39
+ "jestConfig": "libs/motion-master-client/jest.config.ts",
40
+ "passWithNoTests": true
41
+ }
42
+ }
43
+ },
44
+ "tags": []
45
+ }
@@ -0,0 +1,77 @@
1
+ import { Cia402State, ControlwordCommand, createControlwordCommand, getCia402State, getCommandFromControlword } from "./cia402";
2
+
3
+ describe('cia402', () => {
4
+ describe('getControlwordState', () => {
5
+ test.each([
6
+ [0b0000110, ControlwordCommand.SHUTDOWN],
7
+ [0b0001110, ControlwordCommand.SHUTDOWN],
8
+ [0b0000111, ControlwordCommand.SWITCH_ON],
9
+ [0b0001111, ControlwordCommand.SWITCH_ON_ENABLE_OPERATION],
10
+ [0b0000000, ControlwordCommand.DISABLE_VOLTAGE],
11
+ [0b0000001, ControlwordCommand.DISABLE_VOLTAGE],
12
+ [0b0001100, ControlwordCommand.DISABLE_VOLTAGE],
13
+ [0b0001101, ControlwordCommand.DISABLE_VOLTAGE],
14
+ [0b0000010, ControlwordCommand.QUICK_STOP],
15
+ [0b0000011, ControlwordCommand.QUICK_STOP],
16
+ [0b0001010, ControlwordCommand.QUICK_STOP],
17
+ [0b0001011, ControlwordCommand.QUICK_STOP],
18
+ // [0b0000111, ControlwordCommand.DISABLE_OPERATION], // NOTE: never returned, same as SWITCH_ON, depends on transition
19
+ // [0b0001111, ControlwordCommand.ENABLE_OPERATION], // NOTE: never returned, same as SWITCH_ON_ENABLE_OPERATION, depends on transition
20
+ [0b1000000, ControlwordCommand.FAULT_RESET],
21
+ [0b1001111, ControlwordCommand.FAULT_RESET],
22
+ [0b1001001, ControlwordCommand.FAULT_RESET],
23
+ ])('for the value %d it should return the correct controlword state %d', (controlword, expected) => {
24
+ expect(getCommandFromControlword(controlword)).toBe(expected);
25
+ });
26
+ });
27
+
28
+ describe('getStatuswordState', () => {
29
+ test.each([
30
+ [0b0000000, Cia402State.NOT_READY_TO_SWITCH_ON],
31
+ [0b0110000, Cia402State.NOT_READY_TO_SWITCH_ON],
32
+ [0b0010000, Cia402State.NOT_READY_TO_SWITCH_ON],
33
+ [0b1000000, Cia402State.SWITCH_ON_DISABLED],
34
+ [0b1110000, Cia402State.SWITCH_ON_DISABLED],
35
+ [0b0100001, Cia402State.READY_TO_SWITCH_ON],
36
+ [0b0110001, Cia402State.READY_TO_SWITCH_ON],
37
+ [0b0100011, Cia402State.SWITCHED_ON],
38
+ [0b0110011, Cia402State.SWITCHED_ON],
39
+ [0b0100111, Cia402State.OPERATION_ENABLED],
40
+ [0b0110111, Cia402State.OPERATION_ENABLED],
41
+ [0b0000111, Cia402State.QUICK_STOP_ACTIVE],
42
+ [0b0010111, Cia402State.QUICK_STOP_ACTIVE],
43
+ [0b0001111, Cia402State.FAULT_REACTION_ACTIVE],
44
+ [0b0111111, Cia402State.FAULT_REACTION_ACTIVE],
45
+ [0b0001000, Cia402State.FAULT],
46
+ [0b0111000, Cia402State.FAULT],
47
+ ])('for the value %d it should return the correct statusword state %d', (value, expected) => {
48
+ expect(getCia402State(value)).toBe(expected);
49
+ });
50
+ });
51
+
52
+ describe('createControlwordCommand', () => {
53
+ test.each([
54
+ [0b0000000000000000, ControlwordCommand.SHUTDOWN, 0b0000000000000110],
55
+ [0b0000000000001000, ControlwordCommand.SHUTDOWN, 0b0000000000001110],
56
+ [0b0000000010000000, ControlwordCommand.SHUTDOWN, 0b0000000000000110],
57
+ [0b1011000010000000, ControlwordCommand.SHUTDOWN, 0b1011000000000110],
58
+ [0b0000000000000000, ControlwordCommand.SWITCH_ON, 0b0000000000000111],
59
+ [0b1100000010000000, ControlwordCommand.SWITCH_ON, 0b1100000000000111],
60
+ [0b0000000000000000, ControlwordCommand.SWITCH_ON_ENABLE_OPERATION, 0b0000000000001111],
61
+ [0b1100000010000000, ControlwordCommand.SWITCH_ON_ENABLE_OPERATION, 0b1100000000001111],
62
+ [0b0000000000000000, ControlwordCommand.DISABLE_VOLTAGE, 0b0000000000000000],
63
+ [0b0000000010000010, ControlwordCommand.DISABLE_VOLTAGE, 0b0000000000000000],
64
+ [0b0100000000001111, ControlwordCommand.DISABLE_VOLTAGE, 0b0100000000001101],
65
+ [0b0000000000000000, ControlwordCommand.QUICK_STOP, 0b0000000000000010],
66
+ [0b1100000010001101, ControlwordCommand.QUICK_STOP, 0b1100000000001011],
67
+ [0b0000000000000000, ControlwordCommand.DISABLE_OPERATION, 0b0000000000000111],
68
+ [0b1100000010000000, ControlwordCommand.DISABLE_OPERATION, 0b1100000000000111],
69
+ [0b0000000000000000, ControlwordCommand.ENABLE_OPERATION, 0b0000000000001111],
70
+ [0b1100000010000000, ControlwordCommand.ENABLE_OPERATION, 0b1100000000001111],
71
+ [0b0000000000000000, ControlwordCommand.FAULT_RESET, 0b0000000010000000],
72
+ [0b1110000000000111, ControlwordCommand.FAULT_RESET, 0b1110000010000111],
73
+ ])('for the value %d and command %s it should create controlword %d', (value, state, expected) => {
74
+ expect(createControlwordCommand(value, state)).toBe(expected);
75
+ });
76
+ });
77
+ });
@@ -0,0 +1,414 @@
1
+ export const statuswordBits = [
2
+ 'rtso = ready to switch on',
3
+ 'so = switched on',
4
+ 'oe = operation enabled',
5
+ 'f = fault',
6
+ 've = voltage enabled',
7
+ 'qs = quick stop',
8
+ 'sod = switch on disabled',
9
+ 'w = warning',
10
+ 'ms = manufacturer-specific',
11
+ 'rm = remote',
12
+ 'tr = target reached',
13
+ 'ila = internal limit active',
14
+ 'oms = operation-mode-specific',
15
+ 'oms = operation-mode-specific',
16
+ 'ms = manufacturer-specific',
17
+ 'ms = manufacturer-specific',
18
+ ];
19
+
20
+ /**
21
+ * CIA402 refers to the CANopen application profile for drives and motion control.
22
+ * It defines various states that a CiA402-compliant device, such as a motor drive, can be in.
23
+ *
24
+ * @enum
25
+ */
26
+ export enum Cia402State {
27
+ /**
28
+ * Not ready to switch on (NRS).
29
+ *
30
+ * This is the initial state where the drive is not ready to be switched on.
31
+ * In this state, the drive is not powered or initialized.
32
+ */
33
+ NOT_READY_TO_SWITCH_ON = 'NOT_READY_TO_SWITCH_ON',
34
+
35
+ /**
36
+ * Switch on disabled (SOD).
37
+ *
38
+ * In this state, the drive is powered and initialized but cannot be switched on.
39
+ * This state is usually used for safety purposes or when certain conditions need to be met before enabling the drive.
40
+ */
41
+ SWITCH_ON_DISABLED = 'SWITCH_ON_DISABLED',
42
+
43
+ /**
44
+ * Ready to switch on (RTS).
45
+ *
46
+ * In this state, the drive is ready to be switched on.
47
+ * It has been powered and initialized, and it is waiting for the switch-on command.
48
+ */
49
+ READY_TO_SWITCH_ON = 'READY_TO_SWITCH_ON',
50
+
51
+ /**
52
+ * Switched on (SWO).
53
+ *
54
+ * When the switch-on command is received, the drive enters this state.
55
+ * In this state, the drive is energized and ready to start motion.
56
+ */
57
+ SWITCHED_ON = 'SWITCHED_ON',
58
+
59
+ /**
60
+ * Operation enabled (OP).
61
+ *
62
+ * This state indicates that the drive is enabled and ready to perform its intended operation.
63
+ * It can receive motion commands and execute them.
64
+ */
65
+ OPERATION_ENABLED = 'OPERATION_ENABLED',
66
+
67
+ /**
68
+ * Quick stop active (QSA).
69
+ *
70
+ * This state is used to bring the drive to an immediate stop.
71
+ * It is typically triggered by an emergency stop or a quick stop command.
72
+ */
73
+ QUICK_STOP_ACTIVE = 'QUICK_STOP_ACTIVE',
74
+
75
+ /**
76
+ * Fault reaction active (FRA).
77
+ *
78
+ * When a fault or error condition occurs, the drive enters this state.
79
+ * It indicates that the drive is responding to the fault by taking appropriate actions,
80
+ * such as shutting down or entering a safe state.
81
+ */
82
+ FAULT_REACTION_ACTIVE = 'FAULT_REACTION_ACTIVE',
83
+
84
+ /**
85
+ * Fault (FLT).
86
+ *
87
+ * This state signifies that a fault condition has been detected and the drive is no longer operational.
88
+ * It requires manual intervention or troubleshooting to resolve the fault
89
+ * and bring the drive back to a functional state.
90
+ */
91
+ FAULT = 'FAULT',
92
+ };
93
+
94
+ export const cia402StateMap = new Map([
95
+ [0b00000000, Cia402State.NOT_READY_TO_SWITCH_ON],
96
+ [0b01000000, Cia402State.SWITCH_ON_DISABLED],
97
+ [0b00100001, Cia402State.READY_TO_SWITCH_ON],
98
+ [0b00100011, Cia402State.SWITCHED_ON],
99
+ [0b00100111, Cia402State.OPERATION_ENABLED],
100
+ [0b00000111, Cia402State.QUICK_STOP_ACTIVE],
101
+ [0b00001111, Cia402State.FAULT_REACTION_ACTIVE],
102
+ [0b00001000, Cia402State.FAULT],
103
+ ]);
104
+
105
+ export function getCia402State(value: number) {
106
+ return (cia402StateMap.get(value & 0b01101111)
107
+ ?? cia402StateMap.get(value & 0b01001111)) ?? Cia402State.NOT_READY_TO_SWITCH_ON;
108
+ }
109
+
110
+ export function isInternalLimitActive(statusword: number) {
111
+ return (0x800 & statusword) === 0x800;
112
+ }
113
+
114
+ export const controlwordBits = [
115
+ 'so = switch on',
116
+ 'ev = enable voltage',
117
+ 'qs = quick stop',
118
+ 'eo = enable operation',
119
+ 'oms = operation mode specific',
120
+ 'oms = operation mode specific',
121
+ 'oms = operation mode specific',
122
+ 'fr = fault reset',
123
+ 'h = halt',
124
+ 'oms = operation mode specific',
125
+ 'r = reserved',
126
+ 'ms = manufacturer-specific',
127
+ 'ms = manufacturer-specific',
128
+ 'ms = manufacturer-specific',
129
+ 'ms = manufacturer-specific',
130
+ 'ms = manufacturer-specific',
131
+ ];
132
+
133
+ /**
134
+ * In the CiA402 standard for drives and motion control, the controlword is a key component
135
+ * used to command and control the operation of a CiA402-compliant device, such as a motor drive.
136
+ * The controlword is typically a 16-bit value,
137
+ * and it consists of several bits that represent different control commands.
138
+ *
139
+ * @enum
140
+ */
141
+ export enum ControlwordCommand {
142
+ SHUTDOWN = 'SHUTDOWN',
143
+ SWITCH_ON = 'SWITCH_ON',
144
+ SWITCH_ON_ENABLE_OPERATION = 'SWITCH_ON_ENABLE_OPERATION',
145
+ DISABLE_VOLTAGE = 'DISABLE_VOLTAGE',
146
+
147
+ /**
148
+ * Quick Stop.
149
+ *
150
+ * This command initiates a quick stop of the drive.
151
+ * When this bit is set to 1, the drive enters the "Quick stop active" state,
152
+ * causing the motor to decelerate and come to a stop as quickly as possible.
153
+ */
154
+ QUICK_STOP = 'QUICK_STOP',
155
+
156
+ DISABLE_OPERATION = 'DISABLE_OPERATION',
157
+
158
+ /**
159
+ * Enable Operation.
160
+ *
161
+ * This command enables the drive to perform its intended operation.
162
+ * When this bit is set to 1, the drive transitions from the "Ready to switch on" state to the "Operation enabled" state.
163
+ */
164
+ ENABLE_OPERATION = 'ENABLE_OPERATION',
165
+
166
+ /**
167
+ * Fault Reset.
168
+ *
169
+ * This command resets a fault condition and clears any fault flags or errors that may have occurred.
170
+ * When this bit is set to 1, the drive attempts to recover from a fault and return to an operational state.
171
+ */
172
+ FAULT_RESET = 'FAULT_RESET',
173
+ }
174
+
175
+ /**
176
+ * Return one of the controlword commands based its value.
177
+ *
178
+ * NOTE: DISABLE_OPERATION and ENABLE_OPERATION are never returned.
179
+ * Their values are the same as SWITCH_ON and SWITCH_ON_ENABLE_OPERATION.
180
+ * What controlword is commanded depends on the transition.
181
+ */
182
+ export function getCommandFromControlword(value: number) {
183
+ if ((value & 0b1000111) === 0b0000110) {
184
+ return ControlwordCommand.SHUTDOWN;
185
+ }
186
+
187
+ if ((value & 0b1001111) === 0b0000111) {
188
+ return ControlwordCommand.SWITCH_ON;
189
+ }
190
+
191
+ if ((value & 0b1001111) === 0b0001111) {
192
+ return ControlwordCommand.SWITCH_ON_ENABLE_OPERATION;
193
+ }
194
+
195
+ if ((value & 0b1000010) === 0b0000000) {
196
+ return ControlwordCommand.DISABLE_VOLTAGE;
197
+ }
198
+
199
+ if ((value & 0b1000110) === 0b0000010) {
200
+ return ControlwordCommand.QUICK_STOP;
201
+ }
202
+
203
+ if ((value & 0b1001111) === 0b0000111) {
204
+ return ControlwordCommand.DISABLE_OPERATION;
205
+ }
206
+
207
+ if ((value & 0b1001111) === 0b0001111) {
208
+ return ControlwordCommand.ENABLE_OPERATION;
209
+ }
210
+
211
+ if ((value & 0b1000000) === 0b1000000) {
212
+ return ControlwordCommand.FAULT_RESET;
213
+ }
214
+
215
+ return;
216
+ }
217
+
218
+ export const controlwordOptions = {
219
+ 'Shutdown': 0b00000110, // transitions 2, 6, 8
220
+ 'Switch on': 0b00000111, // transitions 3
221
+ 'Switch on + enable operation': 0b00001111, // transitions 3 + 4, automatic transition to Enable Operation state after executing SWITCHED ON state functionality
222
+ 'Disable voltage': 0b00000000, // transitions 7, 9, 10, 12
223
+ 'Quick stop': 0b00000010, // transitions 7, 10, 11
224
+ 'Disable operation': 0b00000111, // transitions 5
225
+ 'Enable operation': 0b00001111, // transitions 4, 16
226
+ 'Fault reset': 0b10000000, // fault reset 15
227
+ };
228
+
229
+ export const controlwordCommandOptions = Object.values(ControlwordCommand);
230
+
231
+ export const controlwordCommandBitmasks = {
232
+ [ControlwordCommand.SHUTDOWN]: [
233
+ 0b1111111101111110,
234
+ 0b0000000000000110,
235
+ ],
236
+ [ControlwordCommand.SWITCH_ON]: [
237
+ 0b1111111101110111,
238
+ 0b0000000000000111,
239
+ ],
240
+ [ControlwordCommand.SWITCH_ON_ENABLE_OPERATION]: [
241
+ 0b1111111101111111,
242
+ 0b0000000000001111,
243
+ ],
244
+ [ControlwordCommand.DISABLE_VOLTAGE]: [
245
+ 0b1111111101111101,
246
+ 0b0000000000000000,
247
+ ],
248
+ [ControlwordCommand.QUICK_STOP]: [
249
+ 0b1111111101111011,
250
+ 0b0000000000000010,
251
+ ],
252
+ [ControlwordCommand.DISABLE_OPERATION]: [
253
+ 0b1111111101110111,
254
+ 0b0000000000000111,
255
+ ],
256
+ [ControlwordCommand.ENABLE_OPERATION]: [
257
+ 0b1111111101111111,
258
+ 0b0000000000001111,
259
+ ],
260
+ [ControlwordCommand.FAULT_RESET]: [
261
+ 0b1111111111111111,
262
+ 0b0000000010000000,
263
+ ],
264
+ };
265
+
266
+ export function createControlwordCommand(value: number, command: ControlwordCommand) {
267
+ const bitmasks = controlwordCommandBitmasks[command];
268
+ return ((value & bitmasks[0]) | bitmasks[1]);
269
+ }
270
+
271
+ /**
272
+ * CiA402 transitions.
273
+ *
274
+ * List of allowed transitions with controlword command.
275
+ *
276
+ * The following transitions are automatic:
277
+ * - 0: START -> NOT_READY_TO_SWITCH_ON
278
+ * - 1: NOT_READY_TO_SWITCH_ON -> SWITCH_ON_DISABLED
279
+ * - 13: ANY -> FAULT_REACTION_ACTIVE
280
+ * - 14: FAULT_REACTION_ACTIVE -> FAULT
281
+ */
282
+ export const cia402Transitions = [
283
+ {
284
+ from: Cia402State.SWITCH_ON_DISABLED,
285
+ to: Cia402State.READY_TO_SWITCH_ON,
286
+ transitions: [2],
287
+ command: ControlwordCommand.SHUTDOWN,
288
+ },
289
+ {
290
+ from: Cia402State.READY_TO_SWITCH_ON,
291
+ to: Cia402State.SWITCHED_ON,
292
+ transitions: [3],
293
+ command: ControlwordCommand.SWITCH_ON,
294
+ },
295
+ {
296
+ from: Cia402State.READY_TO_SWITCH_ON,
297
+ to: Cia402State.OPERATION_ENABLED,
298
+ transitions: [3, 4],
299
+ command: ControlwordCommand.SWITCH_ON_ENABLE_OPERATION,
300
+ },
301
+ {
302
+ from: Cia402State.SWITCHED_ON,
303
+ to: Cia402State.OPERATION_ENABLED,
304
+ transitions: [4],
305
+ command: ControlwordCommand.ENABLE_OPERATION,
306
+ },
307
+ {
308
+ from: Cia402State.OPERATION_ENABLED,
309
+ to: Cia402State.SWITCHED_ON,
310
+ transitions: [5],
311
+ command: ControlwordCommand.DISABLE_OPERATION,
312
+ },
313
+ {
314
+ from: Cia402State.SWITCHED_ON,
315
+ to: Cia402State.READY_TO_SWITCH_ON,
316
+ transitions: [6],
317
+ command: ControlwordCommand.SHUTDOWN,
318
+ },
319
+ {
320
+ from: Cia402State.READY_TO_SWITCH_ON,
321
+ to: Cia402State.SWITCH_ON_DISABLED,
322
+ transitions: [7],
323
+ command: ControlwordCommand.DISABLE_VOLTAGE,
324
+ },
325
+ {
326
+ from: Cia402State.OPERATION_ENABLED,
327
+ to: Cia402State.READY_TO_SWITCH_ON,
328
+ transitions: [8],
329
+ command: ControlwordCommand.SHUTDOWN,
330
+ },
331
+ {
332
+ from: Cia402State.OPERATION_ENABLED,
333
+ to: Cia402State.SWITCH_ON_DISABLED,
334
+ transitions: [9],
335
+ command: ControlwordCommand.DISABLE_VOLTAGE,
336
+ },
337
+ {
338
+ from: Cia402State.SWITCHED_ON,
339
+ to: Cia402State.SWITCH_ON_DISABLED,
340
+ transitions: [10],
341
+ command: ControlwordCommand.DISABLE_VOLTAGE,
342
+ },
343
+ {
344
+ from: Cia402State.OPERATION_ENABLED,
345
+ to: Cia402State.QUICK_STOP_ACTIVE,
346
+ transitions: [11],
347
+ command: ControlwordCommand.QUICK_STOP,
348
+ },
349
+ {
350
+ from: Cia402State.QUICK_STOP_ACTIVE,
351
+ to: Cia402State.SWITCH_ON_DISABLED,
352
+ transitions: [12],
353
+ command: ControlwordCommand.DISABLE_VOLTAGE,
354
+ },
355
+ {
356
+ from: Cia402State.FAULT,
357
+ to: Cia402State.SWITCH_ON_DISABLED,
358
+ transitions: [15],
359
+ command: ControlwordCommand.FAULT_RESET,
360
+ },
361
+ {
362
+ from: Cia402State.QUICK_STOP_ACTIVE,
363
+ to: Cia402State.OPERATION_ENABLED,
364
+ transitions: [16],
365
+ command: ControlwordCommand.ENABLE_OPERATION,
366
+ },
367
+ ];
368
+
369
+ export enum ModesOfOperation {
370
+ OPEN_LOOP_FIELD_MODE = -3,
371
+ DIAGNOSTICS_MODE = -2,
372
+ COGGING_COMPENSATION_RECORDING_MODE = -1,
373
+ NO_MODE_ASSIGNED = 0,
374
+ PROFILE_POSITION_MODE = 1,
375
+ PROFILE_VELOCITY_MODE = 3,
376
+ TORQUE_PROFILE_MODE = 4,
377
+ HOMING_MODE = 6,
378
+ CYCLIC_SYNC_POSITION_MODE = 8,
379
+ CYCLIC_SYNC_VELOCITY_MODE = 9,
380
+ CYCLIC_SYNC_TORQUE_MODE = 10,
381
+ }
382
+
383
+ export const modesOfOperationOptions = {
384
+ 'Open loop field mode': ModesOfOperation.OPEN_LOOP_FIELD_MODE,
385
+ 'Diagnostics mode': ModesOfOperation.DIAGNOSTICS_MODE,
386
+ 'Cogging compensation recording mode': ModesOfOperation.COGGING_COMPENSATION_RECORDING_MODE,
387
+ 'No mode assigned': ModesOfOperation.NO_MODE_ASSIGNED,
388
+ 'Profile position mode': ModesOfOperation.PROFILE_POSITION_MODE,
389
+ 'Profile velocity mode': ModesOfOperation.PROFILE_VELOCITY_MODE,
390
+ 'Torque profile mode': ModesOfOperation.TORQUE_PROFILE_MODE,
391
+ 'Homing mode': ModesOfOperation.HOMING_MODE,
392
+ 'Cyclic synchronous position mode': ModesOfOperation.CYCLIC_SYNC_POSITION_MODE,
393
+ 'Cyclic synchronous velocity mode': ModesOfOperation.CYCLIC_SYNC_VELOCITY_MODE,
394
+ 'Cyclic synchronous torque mode': ModesOfOperation.CYCLIC_SYNC_TORQUE_MODE,
395
+ };
396
+
397
+ export const supportedDriveModesBits = [
398
+ 'pp = profile position mode',
399
+ 'vl = velocity mode',
400
+ 'pv = profile velocity mode',
401
+ 'tq = torque mode',
402
+ 'r = reserved',
403
+ 'hm = homing mode',
404
+ 'ip = interpolated position mode',
405
+ 'csp = cyclic synchronous position mode',
406
+ 'csv = cyclic synchronous velocity mode',
407
+ 'cst = cyclic synchronous torque mode',
408
+ 'r = reserved',
409
+ 'r = reserved',
410
+ 'r = reserved',
411
+ 'r = reserved',
412
+ 'r = reserved',
413
+ 'r = reserved',
414
+ ];
@@ -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
+ });