nodalis-compiler 1.0.31 → 1.0.32

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 (96) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/package.json +4 -1
  3. package/src/compilers/JSCompiler.js +15 -0
  4. package/src/compilers/support/generic/modbus.cpp +57 -18
  5. package/src/compilers/support/jint/nodalis/NodalisEngine/NodalisEngine.csproj +2 -2
  6. package/src/compilers/support/jint/nodalis/NodalisEngine/OPCClient.cs +63 -10
  7. package/src/compilers/support/jint/nodalis/NodalisEngine/OPCServer.cs +69 -9
  8. package/src/compilers/support/jint/nodalis/NodalisEngine/README.md +5 -0
  9. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Debug/net8.0/NodalisEngine.deps.json +263 -162
  10. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Debug/net8.0/NodalisEngine.dll +0 -0
  11. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Debug/net8.0/NodalisEngine.pdb +0 -0
  12. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Debug/net8.0/NodalisEngine.xml +2 -1
  13. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/NodalisEngine.1.0.10.nupkg +0 -0
  14. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/NodalisEngine.1.0.11.nupkg +0 -0
  15. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/NodalisEngine.1.0.12.nupkg +0 -0
  16. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/net8.0/NodalisEngine.deps.json +263 -162
  17. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/net8.0/NodalisEngine.dll +0 -0
  18. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/net8.0/NodalisEngine.pdb +0 -0
  19. package/src/compilers/support/jint/nodalis/NodalisEngine/bin/Release/net8.0/NodalisEngine.xml +2 -1
  20. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.AssemblyInfo.cs +3 -3
  21. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.AssemblyInfoInputs.cache +1 -1
  22. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.assets.cache +0 -0
  23. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.csproj.AssemblyReference.cache +0 -0
  24. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.csproj.CoreCompileInputs.cache +1 -1
  25. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.dll +0 -0
  26. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.pdb +0 -0
  27. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.sourcelink.json +1 -1
  28. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/NodalisEngine.xml +2 -1
  29. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/ref/NodalisEngine.dll +0 -0
  30. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Debug/net8.0/refint/NodalisEngine.dll +0 -0
  31. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/NodalisEngine.csproj.nuget.dgspec.json +2 -2
  32. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/NodalisEngine.csproj.nuget.g.targets +3 -2
  33. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/NodalisEngine.1.0.10.nuspec +2 -2
  34. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/NodalisEngine.1.0.11.nuspec +31 -0
  35. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/NodalisEngine.1.0.12.nuspec +31 -0
  36. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.AssemblyInfo.cs +3 -3
  37. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.AssemblyInfoInputs.cache +1 -1
  38. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.assets.cache +0 -0
  39. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.csproj.AssemblyReference.cache +0 -0
  40. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.csproj.CoreCompileInputs.cache +1 -1
  41. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.dll +0 -0
  42. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.pdb +0 -0
  43. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.sourcelink.json +1 -1
  44. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/NodalisEngine.xml +2 -1
  45. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/ref/NodalisEngine.dll +0 -0
  46. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/Release/net8.0/refint/NodalisEngine.dll +0 -0
  47. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/project.assets.json +495 -224
  48. package/src/compilers/support/jint/nodalis/NodalisEngine/obj/project.nuget.cache +24 -19
  49. package/src/compilers/support/jint/nodalis/NodalisPLC/Program.cs +14 -5
  50. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/BouncyCastle.Cryptography.dll +0 -0
  51. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Esprima.dll +0 -0
  52. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Jint.dll +0 -0
  53. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
  54. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
  55. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Newtonsoft.Json.dll +0 -0
  56. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisEngine.dll +0 -0
  57. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisEngine.pdb +0 -0
  58. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisEngine.xml +0 -693
  59. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisPLC +0 -0
  60. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisPLC.deps.json +0 -358
  61. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisPLC.dll +0 -0
  62. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisPLC.pdb +0 -0
  63. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/NodalisPLC.runtimeconfig.json +0 -12
  64. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Client.dll +0 -0
  65. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Configuration.dll +0 -0
  66. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Core.dll +0 -0
  67. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Gds.Client.Common.dll +0 -0
  68. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Gds.Server.Common.dll +0 -0
  69. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Security.Certificates.dll +0 -0
  70. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/Opc.Ua.Server.dll +0 -0
  71. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/System.IO.Pipelines.dll +0 -0
  72. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/System.Text.Encodings.Web.dll +0 -0
  73. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/System.Text.Json.dll +0 -0
  74. package/src/compilers/support/jint/nodalis/NodalisPLC/bin/Debug/net8.0/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll +0 -0
  75. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +0 -4
  76. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.AssemblyInfo.cs +0 -22
  77. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.AssemblyInfoInputs.cache +0 -1
  78. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.GeneratedMSBuildEditorConfig.editorconfig +0 -15
  79. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.GlobalUsings.g.cs +0 -8
  80. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.assets.cache +0 -0
  81. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.csproj.AssemblyReference.cache +0 -0
  82. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.csproj.CoreCompileInputs.cache +0 -1
  83. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.csproj.FileListAbsolute.txt +0 -37
  84. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.csproj.Up2Date +0 -0
  85. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.dll +0 -0
  86. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.genruntimeconfig.cache +0 -1
  87. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.pdb +0 -0
  88. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/NodalisPLC.sourcelink.json +0 -1
  89. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/apphost +0 -0
  90. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/ref/NodalisPLC.dll +0 -0
  91. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/Debug/net8.0/refint/NodalisPLC.dll +0 -0
  92. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/NodalisPLC.csproj.nuget.dgspec.json +0 -282
  93. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/NodalisPLC.csproj.nuget.g.props +0 -15
  94. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/NodalisPLC.csproj.nuget.g.targets +0 -7
  95. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/project.assets.json +0 -3181
  96. package/src/compilers/support/jint/nodalis/NodalisPLC/obj/project.nuget.cache +0 -51
package/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.32] 2026-06-05
4
+ - Fixed problems with writing registers to Modbus.
5
+
3
6
  ## [1.0.31] 2026-04-28
4
7
  - Added an "exports.json" file that can be used to designate exported local variables in
5
8
  programs when compiling a folder of ST files.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodalis-compiler",
3
- "version": "1.0.31",
3
+ "version": "1.0.32",
4
4
  "description": "Compiles IEC-61131-3/10 languages into code that can be used as a PLC on multiple platforms.",
5
5
  "icon": "nodalis.png",
6
6
  "main": "src/nodalis.js",
@@ -16,6 +16,9 @@
16
16
  },
17
17
  "files": [
18
18
  "src/",
19
+ "!src/compilers/support/jint/nodalis/NodalisPLC/bin/",
20
+ "!src/compilers/support/jint/nodalis/NodalisPLC/obj/",
21
+ "!src/compilers/support/jint/nodalis/publish/",
19
22
  "README.md",
20
23
  "LICENSE",
21
24
  "package.json",
@@ -114,6 +114,7 @@ export class JSCompiler extends Compiler {
114
114
  let tasks = [];
115
115
  let programs = [];
116
116
  let globals = [];
117
+ let csharpGlobals = [];
117
118
  let taskCode = "";
118
119
  let mapCode = "";
119
120
  let plcname = "NodalisPLC";
@@ -143,6 +144,7 @@ export class JSCompiler extends Compiler {
143
144
  else if(line.indexOf("//Global=") > -1){
144
145
  let global = JSON.parse(line.substring(line.indexOf("=") + 1).trim());
145
146
  globals.push(`opcServer.mapVariable("${global.Name}", "${global.Address}");`)
147
+ csharpGlobals.push(`opcServer.MapVariable(${toCSharpStringLiteral(global.Name)}, ${toCSharpStringLiteral(global.Address)});`)
146
148
 
147
149
  }
148
150
  else if(line.trim().startsWith("PROGRAM")){
@@ -273,6 +275,7 @@ export function run(){
273
275
 
274
276
  // Keep the Jint project sources in the main output directory.
275
277
  fs.cpSync(supportDir, projectOutputDir, { recursive: true, force: true });
278
+ patchJintProgramOpcMappings(projectOutputDir, csharpGlobals);
276
279
 
277
280
  // Build from the main output directory, then move publish artifacts under bin.
278
281
  const buildPath = path.resolve(path.join(projectOutputDir, buildScript));
@@ -347,3 +350,15 @@ function installDependencies(outputDir) {
347
350
  shell: true
348
351
  });
349
352
  }
353
+
354
+ function patchJintProgramOpcMappings(projectOutputDir, csharpGlobals) {
355
+ const programPath = path.join(projectOutputDir, "NodalisPLC", "Program.cs");
356
+ let programSource = fs.readFileSync(programPath, "utf-8");
357
+ const mappingCode = csharpGlobals.map((line) => ` ${line}`).join("\n");
358
+ programSource = programSource.replace(" // {opcServerMappings}", mappingCode);
359
+ fs.writeFileSync(programPath, programSource, "utf-8");
360
+ }
361
+
362
+ function toCSharpStringLiteral(value) {
363
+ return `"${String(value).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
364
+ }
@@ -197,47 +197,86 @@ ModbusRequest ModbusClient::createWriteSingleRegister(uint16_t address, uint16_t
197
197
  return { deviceAddress, WRITE_SINGLE_REGISTER, address, 1, data };
198
198
  }
199
199
 
200
- bool ModbusClient::sendRequest(const ModbusRequest& req, ModbusResponse& resp) {
200
+ bool ModbusClient::sendRequest(const ModbusRequest &req, ModbusResponse &resp)
201
+ {
201
202
  std::vector<uint8_t> pdu;
202
203
 
203
- // Handle function-specific encoding
204
- if (req.function == WRITE_SINGLE_COIL) {
205
- // Function 0x05: Write Single Coil
204
+ if (req.function == WRITE_SINGLE_COIL)
205
+ {
206
+ pdu = {
207
+ req.function,
208
+ static_cast<uint8_t>(req.startAddress >> 8),
209
+ static_cast<uint8_t>(req.startAddress & 0xFF)};
210
+
211
+ if (req.data.size() != 2)
212
+ {
213
+ std::cerr << "Invalid data size for Write Single Coil.\n";
214
+ return false;
215
+ }
216
+
217
+ pdu.push_back(req.data[0]);
218
+ pdu.push_back(req.data[1]);
219
+ }
220
+ else if (req.function == WRITE_SINGLE_REGISTER)
221
+ {
206
222
  pdu = {
207
223
  req.function,
208
224
  static_cast<uint8_t>(req.startAddress >> 8),
209
- static_cast<uint8_t>(req.startAddress & 0xFF)
210
- };
211
- if (req.data.size() == 2) {
212
- pdu.push_back(req.data[0]); // Hi byte (0xFF or 0x00)
213
- pdu.push_back(req.data[1]); // Lo byte (always 0x00)
214
- } else {
215
- std::cerr << "Invalid data size for Write Single Coil (expected 2 bytes).\n";
225
+ static_cast<uint8_t>(req.startAddress & 0xFF)};
226
+
227
+ if (req.data.size() != 2)
228
+ {
229
+ std::cerr << "Invalid data size for Write Single Register.\n";
216
230
  return false;
217
231
  }
218
- } else {
219
- // Default encoding for most function codes
232
+
233
+ pdu.push_back(req.data[0]); // value high byte
234
+ pdu.push_back(req.data[1]); // value low byte
235
+ }
236
+ else if (req.function == READ_HOLDING_REGISTERS ||
237
+ req.function == READ_INPUT_REGISTERS ||
238
+ req.function == READ_COILS ||
239
+ req.function == READ_DISCRETE_INPUTS)
240
+ {
220
241
  pdu = {
221
242
  req.function,
222
243
  static_cast<uint8_t>(req.startAddress >> 8),
223
244
  static_cast<uint8_t>(req.startAddress & 0xFF),
224
245
  static_cast<uint8_t>(req.quantity >> 8),
225
- static_cast<uint8_t>(req.quantity & 0xFF)
226
- };
246
+ static_cast<uint8_t>(req.quantity & 0xFF)};
247
+ }
248
+ else if (req.function == WRITE_MULTIPLE_REGISTERS)
249
+ {
250
+ pdu = {
251
+ req.function,
252
+ static_cast<uint8_t>(req.startAddress >> 8),
253
+ static_cast<uint8_t>(req.startAddress & 0xFF),
254
+ static_cast<uint8_t>(req.quantity >> 8),
255
+ static_cast<uint8_t>(req.quantity & 0xFF),
256
+ static_cast<uint8_t>(req.data.size())};
257
+
227
258
  pdu.insert(pdu.end(), req.data.begin(), req.data.end());
228
259
  }
260
+ else
261
+ {
262
+ std::cerr << "Unsupported Modbus function: " << static_cast<int>(req.function) << "\n";
263
+ return false;
264
+ }
229
265
 
230
266
  std::vector<uint8_t> response;
231
- if (!sendRaw(pdu, response)) return false;
267
+ if (!sendRaw(pdu, response))
268
+ return false;
232
269
 
233
- if (response.size() < 2) return false;
270
+ if (response.size() < 2)
271
+ return false;
234
272
 
235
273
  resp.address = req.address;
236
274
  resp.function = response[0];
237
275
  resp.data.assign(response.begin() + 1, response.end());
238
276
  resp.exceptionCode = (resp.function & 0x80) ? resp.data[0] : 0;
239
277
 
240
- if (resp.exceptionCode > 0) {
278
+ if (resp.exceptionCode > 0)
279
+ {
241
280
  std::cerr << "MODBUS exception code: " << static_cast<int>(resp.exceptionCode) << "\n";
242
281
  return false;
243
282
  }
@@ -12,7 +12,7 @@
12
12
  <PackageReference Include="BACnet" Version="3.0.2" />
13
13
  <PackageReference Include="Jint" Version="4.4.2" />
14
14
  <PackageReference Include="System.Text.Json" Version="*" />
15
- <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.5.374.118" />
15
+ <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.5.378.134" />
16
16
  </ItemGroup>
17
17
  <ItemGroup>
18
18
  <None Include="README.md" Pack="true" PackagePath="\" />
@@ -24,7 +24,7 @@
24
24
  <PropertyGroup>
25
25
  <TargetFrameworks>net8.0</TargetFrameworks>
26
26
  <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <!-- optional -->
27
- <Version>1.0.10</Version>
27
+ <Version>1.0.12</Version>
28
28
  <Authors>Nathan Skipper</Authors>
29
29
  <Company>Montgomery Technology, Inc.</Company>
30
30
  <PackageId>NodalisEngine</PackageId>
@@ -21,6 +21,7 @@ using Opc.Ua.Client;
21
21
  using Opc.Ua.Configuration;
22
22
  using System;
23
23
  using System.Collections.Generic;
24
+ using System.IO;
24
25
  using System.Threading.Tasks;
25
26
 
26
27
  namespace Nodalis
@@ -30,7 +31,7 @@ namespace Nodalis
30
31
  /// </summary>
31
32
  public class OPCClient : IOClient
32
33
  {
33
- private Session? _session;
34
+ private ISession? _session;
34
35
  private ApplicationConfiguration? _config;
35
36
  /// <summary>
36
37
  /// Instantiates a new OPCClient.
@@ -52,23 +53,35 @@ namespace Nodalis
52
53
  {
53
54
  ApplicationName = "NodalisOPCUAClient",
54
55
  ApplicationType = ApplicationType.Client,
55
- SecurityConfiguration = new SecurityConfiguration
56
- {
57
- ApplicationCertificate = new CertificateIdentifier(),
58
- AutoAcceptUntrustedCertificates = true,
59
- },
56
+ SecurityConfiguration = CreateSecurityConfiguration(),
60
57
  TransportConfigurations = new TransportConfigurationCollection(),
61
58
  TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
62
59
  ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
63
60
  };
64
61
  await _config.Validate(ApplicationType.Client);
62
+ await _config.CertificateValidator.UpdateAsync(_config, default);
65
63
 
66
64
  var app = new ApplicationInstance { ApplicationName = "NodalisOPCUAClient", ApplicationType = ApplicationType.Client, ApplicationConfiguration = _config };
67
- var endpoint = CoreClientUtils.SelectEndpoint(endpointUrl, false, 15000);
68
- var endpointConfig = EndpointConfiguration.Create(_config);
69
- var endpointDesc = new ConfiguredEndpoint(null, endpoint, endpointConfig);
65
+ await app.CheckApplicationInstanceCertificatesAsync(false, 0);
70
66
 
71
- _session = await Session.Create(_config, endpointDesc, false, "", 60000, null, null);
67
+ var endpoint = CoreClientUtils.SelectEndpoint(_config, endpointUrl, false, 15000);
68
+ var endpointConfig = EndpointConfiguration.Create(_config);
69
+ var configuredEndpoint = new ConfiguredEndpoint(null, endpoint, endpointConfig);
70
+
71
+ var sessionFactory = new DefaultSessionFactory();
72
+
73
+ _session = await sessionFactory.CreateAsync(
74
+ _config,
75
+ (ITransportWaitingConnection?)null,
76
+ configuredEndpoint,
77
+ true,
78
+ false,
79
+ _config.ApplicationName,
80
+ 60000,
81
+ new UserIdentity(),
82
+ null,
83
+ default
84
+ );
72
85
  connected = true;
73
86
  Console.WriteLine("OPC UA connected.");
74
87
  }
@@ -80,6 +93,46 @@ namespace Nodalis
80
93
  });
81
94
  }
82
95
 
96
+ private static SecurityConfiguration CreateSecurityConfiguration()
97
+ {
98
+ string pkiRoot = Path.Combine(AppContext.BaseDirectory, "pki");
99
+ string ownStore = Path.Combine(pkiRoot, "own");
100
+ string trustedPeerStore = Path.Combine(pkiRoot, "trusted");
101
+ string trustedIssuerStore = Path.Combine(pkiRoot, "issuer");
102
+ string rejectedStore = Path.Combine(pkiRoot, "rejected");
103
+
104
+ Directory.CreateDirectory(ownStore);
105
+ Directory.CreateDirectory(trustedPeerStore);
106
+ Directory.CreateDirectory(trustedIssuerStore);
107
+ Directory.CreateDirectory(rejectedStore);
108
+
109
+ return new SecurityConfiguration
110
+ {
111
+ ApplicationCertificate = new CertificateIdentifier
112
+ {
113
+ StoreType = CertificateStoreType.Directory,
114
+ StorePath = ownStore,
115
+ SubjectName = "CN=NodalisOPCUAClient"
116
+ },
117
+ TrustedPeerCertificates = new CertificateTrustList
118
+ {
119
+ StoreType = CertificateStoreType.Directory,
120
+ StorePath = trustedPeerStore
121
+ },
122
+ TrustedIssuerCertificates = new CertificateTrustList
123
+ {
124
+ StoreType = CertificateStoreType.Directory,
125
+ StorePath = trustedIssuerStore
126
+ },
127
+ RejectedCertificateStore = new CertificateTrustList
128
+ {
129
+ StoreType = CertificateStoreType.Directory,
130
+ StorePath = rejectedStore
131
+ },
132
+ AutoAcceptUntrustedCertificates = true
133
+ };
134
+ }
135
+
83
136
  private NodeId GetNodeId(string remote) => new NodeId($"s={remote}", 1);
84
137
 
85
138
  public override bool ReadBit(string address, out int result)
@@ -21,6 +21,7 @@ using Opc.Ua.Configuration;
21
21
  using Opc.Ua.Server;
22
22
  using System;
23
23
  using System.Collections.Generic;
24
+ using System.IO;
24
25
  using System.Threading.Tasks;
25
26
 
26
27
  namespace Nodalis
@@ -57,8 +58,9 @@ namespace Nodalis
57
58
  /// <summary>
58
59
  /// Starts the server.
59
60
  /// </summary>
61
+ /// <param name="hostname">The hostname or IP address for the server.</param>
60
62
  /// <returns></returns>
61
- public async Task StartAsync()
63
+ public async Task StartAsync(string hostname = "localhost")
62
64
  {
63
65
  _application = new ApplicationInstance
64
66
  {
@@ -71,30 +73,83 @@ namespace Nodalis
71
73
  {
72
74
  ApplicationName = "NodalisServer",
73
75
  ApplicationType = ApplicationType.Server,
74
- ApplicationUri = "urn:localhost:NodalisServer",
76
+ ApplicationUri = $"urn:{hostname}:NodalisServer",
75
77
  ServerConfiguration = new ServerConfiguration
76
78
  {
77
- BaseAddresses = { "opc.tcp://localhost:4840/UA/Nodalis" }
79
+ BaseAddresses = { $"opc.tcp://{hostname}:4840/UA/Nodalis" },
80
+ SecurityPolicies =
81
+ {
82
+ new ServerSecurityPolicy
83
+ {
84
+ SecurityMode = MessageSecurityMode.None,
85
+ SecurityPolicyUri = SecurityPolicies.None
86
+ }
87
+ },
88
+ UserTokenPolicies =
89
+ {
90
+ new UserTokenPolicy
91
+ {
92
+ TokenType = UserTokenType.Anonymous
93
+ }
94
+ }
78
95
  },
79
96
  TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
80
- SecurityConfiguration = new SecurityConfiguration
81
- {
82
- ApplicationCertificate = new CertificateIdentifier(),
83
- AutoAcceptUntrustedCertificates = true
84
- },
97
+ SecurityConfiguration = CreateSecurityConfiguration(),
85
98
  CertificateValidator = new CertificateValidator(),
86
99
  //DiagnosticsConfiguration = new DiagnosticsConfiguration { Enabled = true },
87
100
  Extensions = new XmlElementCollection()
88
101
  };
89
102
 
90
103
  await config.Validate(ApplicationType.Server);
104
+ await config.CertificateValidator.UpdateAsync(config, default);
91
105
 
92
106
  _application.ApplicationConfiguration = config;
107
+ await _application.CheckApplicationInstanceCertificatesAsync(false, 0);
93
108
 
94
109
  _server = new NodalisServer(_engine, _addressMap);
95
110
  _application.Start(_server);
96
111
 
97
- Console.WriteLine("OPC UA Server started at: opc.tcp://localhost:4840/UA/Nodalis");
112
+ Console.WriteLine($"OPC UA Server started at: opc.tcp://{hostname}:4840/UA/Nodalis");
113
+ }
114
+
115
+ private static SecurityConfiguration CreateSecurityConfiguration()
116
+ {
117
+ string pkiRoot = Path.Combine(AppContext.BaseDirectory, "pki");
118
+ string ownStore = Path.Combine(pkiRoot, "own");
119
+ string trustedPeerStore = Path.Combine(pkiRoot, "trusted");
120
+ string trustedIssuerStore = Path.Combine(pkiRoot, "issuer");
121
+ string rejectedStore = Path.Combine(pkiRoot, "rejected");
122
+
123
+ Directory.CreateDirectory(ownStore);
124
+ Directory.CreateDirectory(trustedPeerStore);
125
+ Directory.CreateDirectory(trustedIssuerStore);
126
+ Directory.CreateDirectory(rejectedStore);
127
+
128
+ return new SecurityConfiguration
129
+ {
130
+ ApplicationCertificate = new CertificateIdentifier
131
+ {
132
+ StoreType = CertificateStoreType.Directory,
133
+ StorePath = ownStore,
134
+ SubjectName = "CN=NodalisServer"
135
+ },
136
+ TrustedPeerCertificates = new CertificateTrustList
137
+ {
138
+ StoreType = CertificateStoreType.Directory,
139
+ StorePath = trustedPeerStore
140
+ },
141
+ TrustedIssuerCertificates = new CertificateTrustList
142
+ {
143
+ StoreType = CertificateStoreType.Directory,
144
+ StorePath = trustedIssuerStore
145
+ },
146
+ RejectedCertificateStore = new CertificateTrustList
147
+ {
148
+ StoreType = CertificateStoreType.Directory,
149
+ StorePath = rejectedStore
150
+ },
151
+ AutoAcceptUntrustedCertificates = true
152
+ };
98
153
  }
99
154
  /// <summary>
100
155
  /// Stops the server.
@@ -222,6 +277,7 @@ namespace Nodalis
222
277
  var variable = new BaseDataVariableState(folder)
223
278
  {
224
279
  SymbolicName = name,
280
+ ReferenceTypeId = ReferenceTypeIds.Organizes,
225
281
  NodeId = new NodeId(name, NamespaceIndex),
226
282
  BrowseName = new QualifiedName(name, NamespaceIndex),
227
283
  DisplayName = name,
@@ -251,6 +307,7 @@ namespace Nodalis
251
307
  }
252
308
  };
253
309
 
310
+ folder.AddChild(variable);
254
311
  AddPredefinedNode(SystemContext, variable);
255
312
  }
256
313
  }
@@ -261,6 +318,7 @@ namespace Nodalis
261
318
  else if (address.Contains("X")) return _engine.ReadByte(address);
262
319
  else if (address.Contains("W")) return _engine.ReadWord(address);
263
320
  else if (address.Contains("D")) return _engine.ReadDWord(address);
321
+ else if (address.Contains("L")) return _engine.ReadLWord(address);
264
322
  return false;
265
323
  }
266
324
 
@@ -272,6 +330,7 @@ namespace Nodalis
272
330
  case byte bt: _engine.WriteByte(address, bt); break;
273
331
  case ushort us: _engine.WriteWord(address, us); break;
274
332
  case uint ui: _engine.WriteDWord(address, ui); break;
333
+ case ulong ui64: _engine.WriteLWord(address, ui64); break;
275
334
  default: throw new InvalidCastException($"Unsupported value type: {value?.GetType()?.Name}");
276
335
  }
277
336
  }
@@ -283,6 +342,7 @@ namespace Nodalis
283
342
  else if (address.Contains("X")) return DataTypeIds.Byte;
284
343
  else if (address.Contains("W")) return DataTypeIds.UInt16;
285
344
  else if (address.Contains("D")) return DataTypeIds.UInt32;
345
+ else if (address.Contains("L")) return DataTypeIds.UInt64;
286
346
  return DataTypeIds.Boolean;
287
347
  }
288
348
 
@@ -88,6 +88,11 @@ NodalisEngine is distributed under the Apache 2.0 license. See the headers insid
88
88
 
89
89
  # Changelog
90
90
 
91
+ ## [1.0.12] - 2026-05-04
92
+ - Added ability to set hostname for OPCServer.
93
+ - Added support for LWord types to OPCServer.
94
+ - Fixed problems with connecting to OPCServer
95
+
91
96
  ## [1.0.9] - 2026-02-12
92
97
 
93
98
  - Fixed TP function block.