node-red-contrib-ta-cmi-coe 1.0.0 → 1.1.0

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 (39) hide show
  1. package/CHANGELOG.md +28 -17
  2. package/README.de.md +225 -0
  3. package/README.md +134 -187
  4. package/coe/coe-input.js +49 -36
  5. package/coe/coe-monitor.html +1 -1
  6. package/coe/coe-monitor.js +32 -41
  7. package/coe/coe-output.html +67 -28
  8. package/coe/coe-output.js +159 -24
  9. package/coe/config.js +14 -7
  10. package/coe/locales/de/coe-input.html +2 -2
  11. package/coe/locales/de/coe-input.json +8 -2
  12. package/coe/locales/de/coe-monitor.html +1 -2
  13. package/coe/locales/de/coe-monitor.json +9 -4
  14. package/coe/locales/de/coe-output.html +8 -2
  15. package/coe/locales/de/coe-output.json +11 -5
  16. package/coe/locales/de/config.html +3 -3
  17. package/coe/locales/de/config.json +1 -1
  18. package/coe/locales/en-US/coe-input.html +2 -2
  19. package/coe/locales/en-US/coe-input.json +8 -2
  20. package/coe/locales/en-US/coe-monitor.html +1 -2
  21. package/coe/locales/en-US/coe-monitor.json +9 -4
  22. package/coe/locales/en-US/coe-output.html +8 -2
  23. package/coe/locales/en-US/coe-output.json +10 -4
  24. package/coe/locales/en-US/config.html +3 -3
  25. package/coe/locales/en-US/config.json +1 -1
  26. package/coe/units-config.js +2 -1
  27. package/examples/Example Flow.json +56 -0
  28. package/lib/coe-v1.js +152 -0
  29. package/lib/coe-v2.js +78 -116
  30. package/lib/old.js +133 -0
  31. package/lib/protocol.js +19 -0
  32. package/lib/queueing.js +92 -137
  33. package/lib/units.js +7 -7
  34. package/lib/utils.js +71 -66
  35. package/package.json +14 -2
  36. package/__tests__/blockinfo.test.js +0 -24
  37. package/__tests__/conversion.test.js +0 -22
  38. package/__tests__/udp.test.js +0 -46
  39. package/lib/coe.js +0 -109
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-ta-cmi-coe",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Node-RED nodes for TA CMI CoE (CAN over Ethernet)",
5
5
  "author": "Florian Mayrhofer",
6
6
  "license": "Apache-2.0",
@@ -16,6 +16,7 @@
16
16
  "automation"
17
17
  ],
18
18
  "node-red": {
19
+ "version": ">=2.0.0",
19
20
  "nodes": {
20
21
  "coe-input": "coe/coe-input.js",
21
22
  "coe-output": "coe/coe-output.js",
@@ -25,10 +26,21 @@
25
26
  }
26
27
  },
27
28
  "dependencies": {},
28
- "devDependencies": {},
29
+ "devDependencies": {
30
+ "jest": "^30.2.0"
31
+ },
29
32
  "engines": {
30
33
  "node": ">=14.0.0"
31
34
  },
35
+ "files": [
36
+ "coe/",
37
+ "examples/",
38
+ "lib/",
39
+ "CHANGELOG.md",
40
+ "LICENSE",
41
+ "README.de.md",
42
+ "README.md"
43
+ ],
32
44
  "repository": {
33
45
  "type": "git",
34
46
  "url": "https://github.com/mayflo/node-red-contrib-ta-cmi-coe.git"
@@ -1,24 +0,0 @@
1
- const { getBlockInfo } = require("../lib/utils");
2
-
3
- describe("Block Info Tests", () => {
4
- test("Analog Output 1 → Block 1, Position 0", () => {
5
- expect(getBlockInfo("analog", 1)).toEqual({ block: 1, position: 0 });
6
- });
7
-
8
- test("Analog Output 5 → Block 2, Position 0", () => {
9
- expect(getBlockInfo("analog", 5)).toEqual({ block: 2, position: 0 });
10
- });
11
-
12
- test("Digital Output 10 → Block 0, Position 9", () => {
13
- expect(getBlockInfo("digital", 10)).toEqual({ block: 0, position: 9 });
14
- });
15
-
16
- test("Digital Output 20 → Block 9, Position 3", () => {
17
- expect(getBlockInfo("digital", 20)).toEqual({ block: 9, position: 3 });
18
- });
19
-
20
- test("Ungültiger Output → Default", () => {
21
- expect(getBlockInfo("analog", 0)).toEqual({ block: 1, position: 0 });
22
- });
23
- });
24
-
@@ -1,22 +0,0 @@
1
- const { convertCoEToValue, convertValueToCoE, getUnitInfo } = require("../lib/utils");
2
-
3
- describe("CoE Conversion Utilities", () => {
4
- test("°C mit Unit=1, decimals=1", () => {
5
- const unitInfo = { decimals: 1 };
6
- expect(convertCoEToValue(225, 1, 1)).toBe(22.5);
7
- expect(convertValueToCoE(22.5, 1, 1)).toBe(225);
8
- });
9
-
10
- test("kW mit Unit=10, Protocol V2 override", () => {
11
- // V2 überschreibt decimals=2
12
- expect(convertCoEToValue(2500, 10, 2)).toBe(25.0);
13
- expect(convertValueToCoE(25.0, 10, 2)).toBe(2500);
14
- });
15
-
16
- test("Unknown Unit", () => {
17
- const info = getUnitInfo(999, "de");
18
- expect(info.name).toMatch(/Unknown/);
19
- expect(convertCoEToValue(1234, 999, 1)).toBe(1234); // decimals=0
20
- });
21
- });
22
-
@@ -1,46 +0,0 @@
1
- const dgram = require("dgram");
2
-
3
- describe("UDP Integration mit Mock", () => {
4
- let server;
5
- let received;
6
-
7
- beforeAll(() => {
8
- return new Promise((resolve) => {
9
- server = dgram.createSocket("udp4");
10
- server.on("listening", resolve);
11
- server.on("message", (msg) => {
12
- received = msg.toString();
13
- });
14
- server.bind(5555); // besser eigenen Test-Port nehmen
15
- });
16
- });
17
-
18
- afterAll(() => {
19
- server.close();
20
- });
21
-
22
- test("Sendet Testpaket", () => {
23
- return new Promise((resolve, reject) => {
24
- const client = dgram.createSocket("udp4");
25
- const payload = Buffer.from("Hallo UDP-Mock!");
26
-
27
- client.send(payload, 5555, "127.0.0.1", (err) => {
28
- if (err) {
29
- client.close();
30
- return reject(err);
31
- }
32
- client.close();
33
- });
34
-
35
- setTimeout(() => {
36
- try {
37
- expect(received).toBe("Hallo UDP-Mock!");
38
- resolve();
39
- } catch (e) {
40
- reject(e);
41
- }
42
- }, 200);
43
- });
44
- });
45
- });
46
-
package/lib/coe.js DELETED
@@ -1,109 +0,0 @@
1
- /**
2
- * CoE Protocol Parsing and Creation Module
3
- *
4
- * Copyright 2025 Florian Mayrhofer
5
- * Licensed under the Apache License, Version 2.0
6
- *
7
- */
8
-
9
- const { parseCoEV2Packet, createCoEV2Packet, convertV2ToLegacyFormat, convertLegacyToV2Format } = require('./coe-v2');
10
- const { convertCoEToValue, convertValueToCoE } = require('./utils');
11
-
12
- // Parse CoE packet from buffer
13
- function parseCoEPacket(buffer, version) {
14
-
15
- // If V2 Protokoll is used
16
- if (version === 2) {
17
- const v2Data = parseCoEV2Packet(buffer);
18
- if (!v2Data) {
19
- console.warn('V2: Unable to parse packet.');
20
- return null;
21
- }
22
-
23
- // Convert to legacy format for further processing
24
- const legacyBlocks = convertV2ToLegacyFormat(v2Data);
25
-
26
- // Return all blocks (can be multiple)
27
- return legacyBlocks;
28
- }
29
-
30
- const nodeNumber = buffer.readUInt8(0);
31
- const blockNumber = buffer.readUInt8(1);
32
-
33
- let values = [];
34
- let units = [];
35
-
36
- if (blockNumber === 0 || blockNumber === 9) {
37
- // digital
38
- const bitField = buffer.readUInt16LE(2);
39
- const unitId = buffer.readUInt8(11); // Block-wise unit id → byte 11
40
- for (let i = 0; i < 16; i++) {
41
- values.push((bitField >> i) & 1);
42
- units.push(unitId);
43
- }
44
- } else {
45
- // analog V1
46
- for (let i = 0; i < 4; i++) {
47
- const value = buffer.readInt16LE(2 + i * 2);
48
- const unitId = buffer.readUInt8(10 + i);
49
-
50
- const convertedValue = convertCoEToValue(value, unitId, 1); // V1 decimals
51
- values.push(convertedValue);
52
- units.push(unitId);
53
- }
54
- }
55
-
56
- return [{
57
- nodeNumber: nodeNumber,
58
- blockNumber: blockNumber,
59
- values: values,
60
- units: units
61
- }];
62
- }
63
-
64
- // Create CoE Packet from values
65
- function createCoEPacket(nodeNumber, blockNumber, values, units, dataType, version) {
66
- // If V2 Protokoll is used
67
- if (version === 2) {
68
- const outputs = convertLegacyToV2Format(nodeNumber, blockNumber, values, units, dataType);
69
- return createCoEV2Packet(nodeNumber, outputs);
70
- }
71
-
72
- let buffer;
73
-
74
- if (dataType === 'digital') {
75
- buffer = Buffer.alloc(14);
76
- buffer.writeUInt8(nodeNumber, 0);
77
- buffer.writeUInt8(blockNumber, 1);
78
-
79
- let bitField = 0;
80
- for (let i = 0; i < 16; i++) {
81
- if (values[i]) {
82
- bitField |= (1 << i);
83
- }
84
- }
85
- buffer.writeUInt16LE(bitField, 2);
86
- buffer.fill(0, 4, buffer.length);
87
-
88
- } else { // analog
89
- buffer = Buffer.alloc(14);
90
- buffer.writeUInt8(nodeNumber, 0);
91
- buffer.writeUInt8(blockNumber, 1);
92
-
93
- for (let i = 0; i < 4; i++) {
94
- const unitId = units ? units[i] : 0;
95
- const rawValue = convertValueToCoE(values[i], unitId, 1); // V1 Decimal places
96
-
97
- if (rawValue > 32767 || rawValue < -32768) {
98
- console.warn(`Value ${values[i]} exceeds V1 limits. Consider using V2.`);
99
- }
100
-
101
- buffer.writeInt16LE(Math.max(-32768, Math.min(32767, rawValue)), 2 + i * 2);
102
- buffer.writeUInt8(unitId, 10 + i);
103
- }
104
- }
105
-
106
- return buffer;
107
- }
108
-
109
- module.exports = { parseCoEPacket, createCoEPacket};