nodalis-compiler 1.0.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 (37) hide show
  1. package/README.md +134 -0
  2. package/package.json +59 -0
  3. package/src/compilers/CPPCompiler.js +272 -0
  4. package/src/compilers/Compiler.js +108 -0
  5. package/src/compilers/JSCompiler.js +293 -0
  6. package/src/compilers/iec-parser/parser.js +4254 -0
  7. package/src/compilers/st-parser/expressionConverter.js +155 -0
  8. package/src/compilers/st-parser/gcctranspiler.js +237 -0
  9. package/src/compilers/st-parser/jstranspiler.js +254 -0
  10. package/src/compilers/st-parser/parser.js +367 -0
  11. package/src/compilers/st-parser/tokenizer.js +78 -0
  12. package/src/compilers/support/generic/json.hpp +25526 -0
  13. package/src/compilers/support/generic/modbus.cpp +378 -0
  14. package/src/compilers/support/generic/modbus.h +124 -0
  15. package/src/compilers/support/generic/nodalis.cpp +421 -0
  16. package/src/compilers/support/generic/nodalis.h +798 -0
  17. package/src/compilers/support/generic/opcua.cpp +267 -0
  18. package/src/compilers/support/generic/opcua.h +50 -0
  19. package/src/compilers/support/generic/open62541.c +151897 -0
  20. package/src/compilers/support/generic/open62541.h +50357 -0
  21. package/src/compilers/support/jint/nodalis/Nodalis.sln +28 -0
  22. package/src/compilers/support/jint/nodalis/NodalisEngine/ModbusClient.cs +200 -0
  23. package/src/compilers/support/jint/nodalis/NodalisEngine/NodalisEngine.cs +817 -0
  24. package/src/compilers/support/jint/nodalis/NodalisEngine/NodalisEngine.csproj +16 -0
  25. package/src/compilers/support/jint/nodalis/NodalisEngine/OPCClient.cs +172 -0
  26. package/src/compilers/support/jint/nodalis/NodalisEngine/OPCServer.cs +275 -0
  27. package/src/compilers/support/jint/nodalis/NodalisPLC/NodalisPLC.csproj +19 -0
  28. package/src/compilers/support/jint/nodalis/NodalisPLC/Program.cs +197 -0
  29. package/src/compilers/support/jint/nodalis/NodalisPLC/bootstrap.bat +5 -0
  30. package/src/compilers/support/jint/nodalis/NodalisPLC/bootstrap.sh +5 -0
  31. package/src/compilers/support/jint/nodalis/build.bat +25 -0
  32. package/src/compilers/support/jint/nodalis/build.sh +31 -0
  33. package/src/compilers/support/nodejs/IOClient.js +110 -0
  34. package/src/compilers/support/nodejs/modbus.js +115 -0
  35. package/src/compilers/support/nodejs/nodalis.js +662 -0
  36. package/src/compilers/support/nodejs/opcua.js +194 -0
  37. package/src/nodalis.js +174 -0
@@ -0,0 +1,25 @@
1
+ @echo off
2
+ echo Building NodalisEngine...
3
+ dotnet build NodalisEngine/NodalisEngine.csproj
4
+
5
+ echo Publishing NodalisPLC for Windows...
6
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/win-x64
7
+ copy "NodalisPLC/bootstrap.bat" publish/win-x64/bootstrap.bat
8
+
9
+ echo Publishing NodalisPLC for Linux...
10
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r linux-x64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/linux-x64
11
+ copy "NodalisPLC/bootstrap.sh" publish/linux-x64/bootstrap.sh
12
+
13
+ echo Publishing NodalisPLC for macOS...
14
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r osx-x64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/osx-x64
15
+ copy "NodalisPLC/bootstrap.sh" publish/osx-x64/bootstrap.sh
16
+
17
+ echo Publishing NodalisPLC for Linux ARM 32-bit...
18
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r linux-arm --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/linux-arm
19
+ copy "NodalisPLC/bootstrap.sh" publish/linux-arm/bootstrap.sh
20
+
21
+ echo Publishing NodalisPLC for Linux ARM 64-bit...
22
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r linux-arm64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/linux-arm64
23
+ copy "NodalisPLC/bootstrap.sh" publish/linux-arm64/bootstrap.sh
24
+
25
+ echo Build complete.
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "Building NodalisEngine..."
5
+ dotnet build NodalisEngine/NodalisEngine.csproj
6
+
7
+ echo "Publishing NodalisPLC for Windows..."
8
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/win-x64
9
+ cp "NodalisPLC/bootstrap.bat" publish/win-x64/bootstrap.bat
10
+
11
+ echo "Publishing NodalisPLC for Linux..."
12
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r linux-x64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/linux-x64
13
+ cp "NodalisPLC/bootstrap.sh" publish/linux-x64/bootstrap.sh
14
+
15
+ echo "Publishing NodalisPLC for macOS..."
16
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r osx-x64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/osx-x64
17
+ cp "NodalisPLC/bootstrap.sh" publish/osx-x64/bootstrap.sh
18
+
19
+ echo "Publishing NodalisPLC for macOS ARM64..."
20
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r osx-arm64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/osx-arm64
21
+ cp "NodalisPLC/bootstrap.sh" publish/osx-arm64/bootstrap.sh
22
+
23
+ echo Publishing NodalisPLC for Linux ARM 32-bit...
24
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r linux-arm --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/linux-arm
25
+ cp "NodalisPLC/bootstrap.sh" publish/linux-arm/bootstrap.sh
26
+
27
+ echo Publishing NodalisPLC for Linux ARM 64-bit...
28
+ dotnet publish NodalisPLC/NodalisPLC.csproj -c Release -r linux-arm64 --self-contained true /p:PublishSingleFile=true /p:Trim=true -o publish/linux-arm64
29
+ cp "NodalisPLC/bootstrap.sh" publish/linux-arm64/bootstrap.sh
30
+
31
+ echo "Build complete."
@@ -0,0 +1,110 @@
1
+ let elapsed = () => {return Date.now();};
2
+ let readBit = null;
3
+ let writeBit = null;
4
+ let readByte = null;
5
+ let writeByte = null;
6
+ let readWord = null;
7
+ let writeWord = null;
8
+ let readDWord = null;
9
+ let writeDWord = null;
10
+
11
+ export function setTiming(el){
12
+ elapsed = el;
13
+ }
14
+
15
+ export function setMemoryAccess(options){
16
+ const { readBitFunc, readByteFunc, readWordFunc, readDWordFunc, writeBitFunc, writeByteFunc, writeWordFunc, writeDWordFunc } = options;
17
+ readBit = readBitFunc;
18
+ readByte = readByteFunc;
19
+ readWord = readWordFunc;
20
+ readDWord = readDWordFunc;
21
+ writeBit = writeBitFunc;
22
+ writeByte = writeByteFunc;
23
+ writeWord = writeWordFunc;
24
+ writeDWord = writeDWordFunc;
25
+ }
26
+
27
+ export class IOMap {
28
+ constructor(jsonStr) {
29
+ const j = JSON.parse(jsonStr);
30
+ this.moduleID = j.ModuleID;
31
+ this.modulePort = j.ModulePort;
32
+ this.localAddress = j.InternalAddress;
33
+ this.remoteAddress = j.RemoteAddress;
34
+ this.width = parseInt(j.RemoteSize);
35
+ this.interval = parseInt(j.PollTime);
36
+ this.protocol = j.Protocol;
37
+ this.additionalProperties = j.AdditionalProperties || {};
38
+ this.direction = this.localAddress.includes("%Q") ? "Output" : "Input";
39
+ this.lastPoll = elapsed();
40
+ this.bit = -1;
41
+ }
42
+ }
43
+
44
+ export class IOClient {
45
+ constructor(protocol) {
46
+ this.protocol = protocol;
47
+ this.connected = false;
48
+ this.moduleID = "";
49
+ this.lastAttempt = 0;
50
+ this.mappings = [];
51
+ }
52
+
53
+ addMapping(map) {
54
+ if (!this.hasMapping(map.localAddress)) {
55
+ if (this.mappings.length === 0) {
56
+ this.moduleID = map.moduleID;
57
+ }
58
+ console.log(`Adding map for ${map.moduleID}:${map.modulePort}->${map.localAddress}`);
59
+ this.mappings.push(map);
60
+ }
61
+ }
62
+
63
+ hasMapping(localAddress) {
64
+ return this.mappings.some(m => m.localAddress === localAddress);
65
+ }
66
+
67
+ poll() {
68
+ if (this.connected) {
69
+ for (const map of this.mappings) {
70
+ try {
71
+ if (elapsed() - map.lastPoll > map.interval) {
72
+ map.lastPoll = elapsed();
73
+ if (map.direction === "Output") {
74
+ let val;
75
+ switch (map.width) {
76
+ case 1: val = readBit(map.localAddress); this.writeBit(map.remoteAddress, val ? 1 : 0); break;
77
+ case 8: val = readByte(map.localAddress); this.writeByte(map.remoteAddress, val); break;
78
+ case 16: val = readWord(map.localAddress); this.writeWord(map.remoteAddress, val); break;
79
+ case 32: val = readDWord(map.localAddress); this.writeDWord(map.remoteAddress, val); break;
80
+ }
81
+ } else if (map.direction === "Input") {
82
+ switch (map.width) {
83
+ case 1: this.readBit(map.remoteAddress, (bit) => writeBit(map.localAddress, !!bit)); break;
84
+ case 8: this.readByte(map.remoteAddress, (val) => writeByte(map.localAddress, val)); break;
85
+ case 16: this.readWord(map.remoteAddress, (val) => writeWord(map.localAddress, val)); break;
86
+ case 32: this.readDWord(map.remoteAddress, (val) => writeDWord(map.localAddress, val)); break;
87
+ }
88
+ }
89
+ }
90
+ } catch (e) {
91
+ console.error("IO Poll Error:", e);
92
+ }
93
+ }
94
+ } else if (elapsed() - this.lastAttempt >= 15000) {
95
+ this.lastAttempt = elapsed();
96
+ this.connect();
97
+ }
98
+ }
99
+
100
+ // Abstract methods
101
+ readBit(remote, callback) {}
102
+ writeBit(remote, value) {}
103
+ readByte(remote, callback) {}
104
+ writeByte(remote, value) {}
105
+ readWord(remote, callback) {}
106
+ writeWord(remote, value) {}
107
+ readDWord(remote, callback) {}
108
+ writeDWord(remote, value) {}
109
+ connect() {}
110
+ }
@@ -0,0 +1,115 @@
1
+ // Copyright [2025] Nathan Skipper
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+
16
+ /**
17
+ * @description Modbus Client for NodeJS
18
+ * @author Nathan Skipper, MTI
19
+ * @version 1.0.2
20
+ * @copyright Apache 2.0
21
+ */
22
+ import * as Modbus from "jsmodbus";
23
+ import * as net from "net";
24
+ import {IOClient, IOMap} from "./IOClient.js";
25
+
26
+ export class ModbusClient extends IOClient {
27
+ constructor() {
28
+ super('MODBUS-TCP');
29
+ this.socket = null;
30
+ this.client = null;
31
+ }
32
+
33
+ connect() {
34
+ try {
35
+ this.socket = new net.Socket();
36
+ this.client = new Modbus.client.TCP(this.socket);
37
+ const map = this.mappings[0];
38
+ const [host, port] = [map.moduleID, map.modulePort];
39
+ this.socket.connect({ host, port: parseInt(port) }, () => {
40
+ console.log('Modbus connected to', host, port);
41
+ this.connected = true;
42
+ });
43
+ this.socket.on('error', err => {
44
+ console.error('Modbus socket error:', err.message);
45
+ this.connected = false;
46
+ });
47
+ this.socket.on('close', () => {
48
+ this.connected = false;
49
+ });
50
+ } catch (e) {
51
+ console.error('Connect error:', e.message);
52
+ this.connected = false;
53
+ }
54
+ }
55
+
56
+ readBit(address, cb) {
57
+ const reg = parseInt(address);
58
+ this.client.readDiscreteInputs(reg, 1)
59
+ .then(res =>
60
+ cb(res.response._body.valuesAsArray[0]))
61
+ .catch(err => console.error('readBit error', err.message));
62
+ }
63
+
64
+ writeBit(address, value) {
65
+ const reg = parseInt(address);
66
+ this.client.writeSingleCoil(reg, value)
67
+ .catch(err => console.error('writeBit error', err.message));
68
+ }
69
+
70
+ readByte(address, cb) {
71
+ const reg = parseInt(address);
72
+ this.client.readHoldingRegisters(reg, 1)
73
+ .then(res => cb(res.response._body.valuesAsBuffer[1]))
74
+ .catch(err => console.error('readByte error', err.message));
75
+ }
76
+
77
+ writeByte(address, value) {
78
+ const reg = parseInt(address);
79
+ this.client.writeSingleRegister(reg, value)
80
+ .catch(err => console.error('writeByte error', err.message));
81
+ }
82
+
83
+ readWord(address, cb) {
84
+ const reg = parseInt(address);
85
+ this.client.readHoldingRegisters(reg, 1)
86
+ .then(res => cb(res.response._body.valuesAsBuffer.readUInt16BE(0)))
87
+ .catch(err => console.error('readWord error', err.message));
88
+ }
89
+
90
+ writeWord(address, value) {
91
+ const reg = parseInt(address);
92
+ this.client.writeSingleRegister(reg, value)
93
+ .catch(err => console.error('writeWord error', err.message));
94
+ }
95
+
96
+ readDWord(address, cb) {
97
+ const reg = parseInt(address);
98
+ this.client.readHoldingRegisters(reg, 2)
99
+ .then(res => {
100
+ const b = res.response._body.valuesAsBuffer;
101
+ const val = b.readUInt32BE(0);
102
+ cb(val);
103
+ })
104
+ .catch(err => console.error('readDWord error', err.message));
105
+ }
106
+
107
+ writeDWord(address, value) {
108
+ const reg = parseInt(address);
109
+ const buf = Buffer.alloc(4);
110
+ buf.writeUInt32BE(value);
111
+ this.client.writeMultipleRegisters(reg, buf)
112
+ .catch(err => console.error('writeDWord error', err.message));
113
+ }
114
+ }
115
+