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,267 @@
1
+ #include "opcua.h"
2
+ #include <iostream>
3
+
4
+ OPCUAClient::OPCUAClient()
5
+ : IOClient("opcua"), endpointUrl("opc.tcp://localhost:4840") {
6
+ client = UA_Client_new();
7
+ UA_ClientConfig_setDefault(UA_Client_getConfig(client));
8
+ }
9
+
10
+ OPCUAClient::~OPCUAClient() {
11
+ UA_Client_disconnect(client);
12
+ UA_Client_delete(client);
13
+ }
14
+
15
+ void OPCUAClient::connect() {
16
+ if (!connected) {
17
+ if (UA_Client_connect(client, moduleID.c_str()) == UA_STATUSCODE_GOOD) {
18
+ connected = true;
19
+ } else {
20
+ connected = false;
21
+ }
22
+ }
23
+ }
24
+
25
+ template<typename T>
26
+ bool OPCUAClient::readValue(const std::string& nodeIdStr, T& value, const UA_DataType* type) {
27
+ UA_Variant val;
28
+ UA_Variant_init(&val);
29
+
30
+ UA_NodeId nodeId = UA_NODEID_STRING_ALLOC(1, nodeIdStr.c_str());
31
+ UA_StatusCode status = UA_Client_readValueAttribute(client, nodeId, &val);
32
+ UA_NodeId_clear(&nodeId);
33
+
34
+ if (status == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&val, type)) {
35
+ value = *(T*)val.data;
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+
41
+ template<typename T>
42
+ bool OPCUAClient::writeValue(const std::string& nodeIdStr, T value, const UA_DataType* type) {
43
+ UA_Variant val;
44
+ UA_Variant_setScalar(&val, &value, type);
45
+
46
+ UA_NodeId nodeId = UA_NODEID_STRING_ALLOC(1, nodeIdStr.c_str());
47
+ UA_StatusCode status = UA_Client_writeValueAttribute(client, nodeId, &val);
48
+ UA_NodeId_clear(&nodeId);
49
+
50
+ return status == UA_STATUSCODE_GOOD;
51
+ }
52
+
53
+ // Implement required IOClient methods
54
+
55
+ bool OPCUAClient::readBit(const std::string& remote, int& result) {
56
+ bool val;
57
+ bool success = readValue(remote, val, &UA_TYPES[UA_TYPES_BOOLEAN]);
58
+ result = val;
59
+ return success;
60
+ }
61
+
62
+ bool OPCUAClient::writeBit(const std::string& remote, int value) {
63
+ bool val = value != 0;
64
+ return writeValue(remote, val, &UA_TYPES[UA_TYPES_BOOLEAN]);
65
+ }
66
+
67
+ bool OPCUAClient::readByte(const std::string& remote, uint8_t& result) {
68
+ return readValue(remote, result, &UA_TYPES[UA_TYPES_BYTE]);
69
+ }
70
+
71
+ bool OPCUAClient::writeByte(const std::string& remote, uint8_t value) {
72
+ return writeValue(remote, value, &UA_TYPES[UA_TYPES_BYTE]);
73
+ }
74
+
75
+ bool OPCUAClient::readWord(const std::string& remote, uint16_t& result) {
76
+ return readValue(remote, result, &UA_TYPES[UA_TYPES_UINT16]);
77
+ }
78
+
79
+ bool OPCUAClient::writeWord(const std::string& remote, uint16_t value) {
80
+ return writeValue(remote, value, &UA_TYPES[UA_TYPES_UINT16]);
81
+ }
82
+
83
+ bool OPCUAClient::readDWord(const std::string& remote, uint32_t& result) {
84
+ return readValue(remote, result, &UA_TYPES[UA_TYPES_UINT32]);
85
+ }
86
+
87
+ bool OPCUAClient::writeDWord(const std::string& remote, uint32_t value) {
88
+ return writeValue(remote, value, &UA_TYPES[UA_TYPES_UINT32]);
89
+ }
90
+
91
+ static UA_StatusCode staticRead(UA_Server*, const UA_NodeId*, void*, const UA_NodeId*, void* nodeContext,
92
+ UA_Boolean, const UA_NumericRange*, UA_DataValue* dataValue) {
93
+ auto* addr = static_cast<std::string*>(nodeContext);
94
+ UA_StatusCode res = UA_STATUSCODE_BAD;
95
+ if(addr->find('.') != std::string::npos){
96
+ bool bval = readBit(*addr);
97
+ UA_Variant_setScalarCopy(&dataValue->value, &bval, &UA_TYPES[UA_TYPES_BOOLEAN]);
98
+ dataValue->hasValue = true;
99
+ res = UA_STATUSCODE_GOOD;
100
+ }
101
+ else{
102
+ char size = addr->c_str()[2];
103
+ uint8_t byval;
104
+ uint16_t wval;
105
+ uint32_t dval;
106
+ switch(size){
107
+ case 'X':
108
+ byval = readByte(*addr);
109
+ UA_Variant_setScalarCopy(&dataValue->value, &byval, &UA_TYPES[UA_TYPES_BYTE]);
110
+ dataValue->hasValue = true;
111
+ res = UA_STATUSCODE_GOOD;
112
+ break;
113
+ case 'W':
114
+ wval = readWord(*addr);
115
+ UA_Variant_setScalarCopy(&dataValue->value, &wval, &UA_TYPES[UA_TYPES_UINT16]);
116
+ dataValue->hasValue = true;
117
+ res = UA_STATUSCODE_GOOD;
118
+ break;
119
+ case 'D':
120
+ dval = readDWord(*addr);
121
+ UA_Variant_setScalarCopy(&dataValue->value, &dval, &UA_TYPES[UA_TYPES_UINT32]);
122
+ dataValue->hasValue = true;
123
+ res = UA_STATUSCODE_GOOD;
124
+ break;
125
+ }
126
+ }
127
+
128
+ return res;
129
+ }
130
+
131
+ static UA_StatusCode staticWrite(UA_Server*, const UA_NodeId*, void*, const UA_NodeId*, void* nodeContext,
132
+ const UA_NumericRange*, const UA_DataValue* dataValue) {
133
+ auto* addr = static_cast<std::string*>(nodeContext);
134
+ if (UA_Variant_hasScalarType(&dataValue->value, &UA_TYPES[UA_TYPES_UINT16])) {
135
+ uint16_t value = *(uint16_t*)dataValue->value.data;
136
+ writeWord(*addr, value);
137
+ return UA_STATUSCODE_GOOD;
138
+ }
139
+ else if (UA_Variant_hasScalarType(&dataValue->value, &UA_TYPES[UA_TYPES_UINT32])) {
140
+ uint32_t value = *(uint32_t*)dataValue->value.data;
141
+ writeDWord(*addr, value);
142
+ return UA_STATUSCODE_GOOD;
143
+ }
144
+ else if (UA_Variant_hasScalarType(&dataValue->value, &UA_TYPES[UA_TYPES_BYTE])) {
145
+ uint8_t value = *(uint8_t*)dataValue->value.data;
146
+ writeByte(*addr, value);
147
+ return UA_STATUSCODE_GOOD;
148
+ }
149
+ else if (UA_Variant_hasScalarType(&dataValue->value, &UA_TYPES[UA_TYPES_BOOLEAN])) {
150
+ bool value = *(bool*)dataValue->value.data;
151
+ writeBit(*addr, value);
152
+ return UA_STATUSCODE_GOOD;
153
+ }
154
+ return UA_STATUSCODE_BADTYPEMISMATCH;
155
+ }
156
+
157
+ OPCUAServer::OPCUAServer() {
158
+ server = UA_Server_new();
159
+ UA_ServerConfig* config = UA_Server_getConfig(server);
160
+
161
+ // Initialize config (minimal or default)
162
+ UA_ServerConfig_setDefault(config); // or UA_ServerConfig_setMinimal(config, 4840, NULL);
163
+
164
+ // Now change endpoint URL(s)
165
+ for (size_t i = 0; i < config->endpointsSize; ++i) {
166
+ UA_EndpointDescription* endpoint = &config->endpoints[i];
167
+
168
+ UA_String_clear(&endpoint->endpointUrl);
169
+ endpoint->endpointUrl = UA_STRING_ALLOC("opc.tcp://0.0.0.0:4840");
170
+ }
171
+ running = false;
172
+ }
173
+
174
+ OPCUAServer::~OPCUAServer() {
175
+ stop();
176
+ UA_Server_delete(server);
177
+ }
178
+
179
+ void OPCUAServer::start() {
180
+ if (!running) {
181
+ running = true;
182
+ serverThread = std::thread(&OPCUAServer::run, this);
183
+ }
184
+ }
185
+
186
+ void OPCUAServer::stop() {
187
+ if (running) {
188
+ running = false;
189
+ UA_Server_run_shutdown(server);
190
+ if (serverThread.joinable())
191
+ serverThread.join();
192
+ }
193
+ }
194
+
195
+ void OPCUAServer::run() {
196
+ UA_Server_run(server, (const volatile UA_Boolean*)&running);
197
+ }
198
+
199
+ void OPCUAServer::mapVariable(std::string varname, std::string addr){
200
+ auto* addrStr = new std::string(addr.c_str());
201
+
202
+ UA_DataSource ds;
203
+ ds.read = staticRead;
204
+ ds.write = staticWrite;
205
+ char* lang = (char*)malloc(6);
206
+ strcpy(lang, "en-US");
207
+ UA_VariableAttributes attr = UA_VariableAttributes_default;
208
+ attr.displayName = UA_LOCALIZEDTEXT(lang,(char*) varname.c_str());
209
+ attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
210
+ if(addr.find('.') != std::string::npos){
211
+ UA_Server_addDataSourceVariableNode(
212
+ server,
213
+ UA_NODEID_STRING(1, (char*)varname.c_str()),
214
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
215
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
216
+ UA_QUALIFIEDNAME(1, (char*)varname.c_str()),
217
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
218
+ attr,
219
+ ds,
220
+ addrStr, // pass the address as a string*
221
+ nullptr
222
+ );
223
+ }
224
+ else if(addr.c_str()[2] == 'X'){
225
+ UA_Server_addDataSourceVariableNode(
226
+ server,
227
+ UA_NODEID_STRING(1, (char*)varname.c_str()),
228
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
229
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
230
+ UA_QUALIFIEDNAME(1, (char*)varname.c_str()),
231
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
232
+ attr,
233
+ ds,
234
+ addrStr, // pass the address as a string*
235
+ nullptr
236
+ );
237
+ }
238
+ else if(addr.c_str()[2] == 'W'){
239
+ UA_Server_addDataSourceVariableNode(
240
+ server,
241
+ UA_NODEID_STRING(1, (char*)varname.c_str()),
242
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
243
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
244
+ UA_QUALIFIEDNAME(1, (char*)varname.c_str()),
245
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
246
+ attr,
247
+ ds,
248
+ addrStr, // pass the address as a string*
249
+ nullptr
250
+ );
251
+ }
252
+ else if(addr.c_str()[2] == 'D'){
253
+ UA_Server_addDataSourceVariableNode(
254
+ server,
255
+ UA_NODEID_STRING(1, (char*)varname.c_str()),
256
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
257
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
258
+ UA_QUALIFIEDNAME(1, (char*)varname.c_str()),
259
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
260
+ attr,
261
+ ds,
262
+ addrStr, // pass the address as a string*
263
+ nullptr
264
+ );
265
+ }
266
+
267
+ }
@@ -0,0 +1,50 @@
1
+ #pragma once
2
+ #include "nodalis.h"
3
+ #include "open62541.h"
4
+ #include <thread>
5
+ #include <atomic>
6
+
7
+ class OPCUAClient : public IOClient {
8
+ public:
9
+ OPCUAClient();
10
+ ~OPCUAClient();
11
+
12
+ protected:
13
+ void connect() override;
14
+
15
+ bool readBit(const std::string& remote, int& result) override;
16
+ bool writeBit(const std::string& remote, int value) override;
17
+ bool readByte(const std::string& remote, uint8_t& result) override;
18
+ bool writeByte(const std::string& remote, uint8_t value) override;
19
+ bool readWord(const std::string& remote, uint16_t& result) override;
20
+ bool writeWord(const std::string& remote, uint16_t value) override;
21
+ bool readDWord(const std::string& remote, uint32_t& result) override;
22
+ bool writeDWord(const std::string& remote, uint32_t value) override;
23
+
24
+ private:
25
+ UA_Client* client;
26
+ std::string endpointUrl;
27
+
28
+ template<typename T>
29
+ bool readValue(const std::string& nodeIdStr, T& value, const UA_DataType* type);
30
+
31
+ template<typename T>
32
+ bool writeValue(const std::string& nodeIdStr, T value, const UA_DataType* type);
33
+ };
34
+
35
+ class OPCUAServer {
36
+ public:
37
+ OPCUAServer();
38
+ ~OPCUAServer();
39
+
40
+ void start();
41
+ void stop();
42
+ void mapVariable(std::string varname, std::string addr);
43
+
44
+ private:
45
+ void run();
46
+
47
+ UA_Server* server;
48
+ std::thread serverThread;
49
+ std::atomic<bool> running;
50
+ };