diff --git a/Opc.Ua.Publisher.Module.sln b/Opc.Ua.Publisher.Module.sln
deleted file mode 100644
index 2ab605b..0000000
--- a/Opc.Ua.Publisher.Module.sln
+++ /dev/null
@@ -1,49 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26430.13
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0E241D3D-7C66-4E4F-99AB-9FF5780180D1}"
- ProjectSection(SolutionItems) = preProject
- .travis.yml = .travis.yml
- appveyor.yml = appveyor.yml
- Dockerfile = Dockerfile
- License.txt = License.txt
- README.md = README.md
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GatewayApp.NetCore", "src\GatewayApp.NetCore\GatewayApp.NetCore.csproj", "{592A483D-5F91-400E-B4EF-C25092143A4F}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.Publisher.Module", "src\Opc.Ua.Publisher.Module\Opc.Ua.Publisher.Module.csproj", "{A1CC3B57-A186-4C3E-9E36-30A54A947369}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTHubCredentialTools", "src\IoTHubCredentialTools\IoTHubCredentialTools.csproj", "{2605E447-DF6E-4FB8-B226-CD1DB643F186}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.IoTHub.Module", "src\Opc.Ua.IoTHub.Module\Opc.Ua.IoTHub.Module.csproj", "{B7B97F4D-B753-4E1B-A745-2E99B9D11D74}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {592A483D-5F91-400E-B4EF-C25092143A4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {592A483D-5F91-400E-B4EF-C25092143A4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {592A483D-5F91-400E-B4EF-C25092143A4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {592A483D-5F91-400E-B4EF-C25092143A4F}.Release|Any CPU.Build.0 = Release|Any CPU
- {A1CC3B57-A186-4C3E-9E36-30A54A947369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A1CC3B57-A186-4C3E-9E36-30A54A947369}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A1CC3B57-A186-4C3E-9E36-30A54A947369}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A1CC3B57-A186-4C3E-9E36-30A54A947369}.Release|Any CPU.Build.0 = Release|Any CPU
- {2605E447-DF6E-4FB8-B226-CD1DB643F186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2605E447-DF6E-4FB8-B226-CD1DB643F186}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2605E447-DF6E-4FB8-B226-CD1DB643F186}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2605E447-DF6E-4FB8-B226-CD1DB643F186}.Release|Any CPU.Build.0 = Release|Any CPU
- {B7B97F4D-B753-4E1B-A745-2E99B9D11D74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B7B97F4D-B753-4E1B-A745-2E99B9D11D74}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B7B97F4D-B753-4E1B-A745-2E99B9D11D74}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B7B97F4D-B753-4E1B-A745-2E99B9D11D74}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/src/Opc.Ua.Publisher.Module/BuildServerModel.cmd b/src/BuildServerModel.cmd
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/BuildServerModel.cmd
rename to src/BuildServerModel.cmd
diff --git a/src/GatewayApp.NetCore/GatewayApp.NetCore.csproj b/src/GatewayApp.NetCore/GatewayApp.NetCore.csproj
deleted file mode 100644
index f25a70a..0000000
--- a/src/GatewayApp.NetCore/GatewayApp.NetCore.csproj
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
- netcoreapp1.1
- GatewayApp.NetCore
- Exe
- GatewayApp.NetCore
- win10-x64;win81-x64;win8-x64;win7-x64;debian.8-x64;ubuntu.16.04-x64
- 1.1.2
- false
- true
- false
- true
-
- Microsoft
-
-
-
-
-
-
-
-
-
- PreserveNewest
- PreserveNewest
-
-
- PreserveNewest
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/GatewayApp.NetCore/Program.cs b/src/GatewayApp.NetCore/Program.cs
deleted file mode 100644
index ecc1d25..0000000
--- a/src/GatewayApp.NetCore/Program.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-
-using System;
-using System.IO;
-using Microsoft.Azure.Devices.Gateway;
-using IoTHubCredentialTools;
-using System.Runtime.InteropServices;
-using System.Collections.Generic;
-
-namespace GatewayApp.NetCore
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- // check for OSX, which we don't support
- if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
- {
- throw new NotSupportedException("OSX is not supported by the Gateway App on .Net Core");
- }
-
- // patch IoT Hub module DLL name
- string gatewayConfigFile = "gatewayconfig.json";
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
- {
- Console.WriteLine("Target system is Linux.");
- File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("iothub.dll", "libiothub.so"));
- }
- else
- {
- Console.WriteLine("Target system is Windows.");
- File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("libiothub.so", "iothub.dll"));
- }
- Console.WriteLine(RuntimeInformation.OSDescription);
-
- // print target system info
- if (IsX64Process())
- {
- Console.WriteLine("Target system is 64-bit.");
- }
- else
- {
- Console.WriteLine("Target system is 32-bit.");
- throw new Exception("32-bit systems are currently not supported.");
- }
-
- // check if we got command line arguments to patch our gateway config file and register ourselves with IoT Hub
- if ((args.Length > 0) && !string.IsNullOrEmpty(args[0]))
- {
- string applicationName = args[0];
- File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("", applicationName));
- Console.WriteLine("Gateway config file patched with application name: " + applicationName);
-
- // check if we also received an owner connection string to register ourselves with IoT Hub
- if ((args.Length > 1) && !string.IsNullOrEmpty(args[1]))
- {
- string ownerConnectionString = args[1];
-
- Console.WriteLine("Attemping to register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
- string deviceConnectionString = IoTHubRegistration.RegisterDeviceWithIoTHub(applicationName, ownerConnectionString);
- if (!string.IsNullOrEmpty(deviceConnectionString))
- {
- SecureIoTHubToken.Write(applicationName, deviceConnectionString);
- }
- else
- {
- Console.WriteLine("Could not register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
- }
- }
- else
- {
- Console.WriteLine("IoT Hub owner connection string not passed as argument, registration with IoT Hub abandoned.");
- }
-
- // try to read connection string from secure store and patch gateway config file
- Console.WriteLine("Attemping to read connection string from secure store with certificate name: " + applicationName);
- string connectionString = SecureIoTHubToken.Read(applicationName);
- if (!string.IsNullOrEmpty(connectionString))
- {
- Console.WriteLine("Attemping to configure publisher with connection string: " + connectionString);
- string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(connectionString, true);
- if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
- {
- string _IoTHubName = parsedConnectionString[0];
- if (_IoTHubName.Contains("."))
- {
- _IoTHubName = _IoTHubName.Substring(0, _IoTHubName.IndexOf('.'));
- }
- File.WriteAllText(gatewayConfigFile, File.ReadAllText(gatewayConfigFile).Replace("", _IoTHubName));
- Console.WriteLine("Gateway config file patched with IoT Hub name: " + _IoTHubName);
- }
- else
- {
- throw new Exception("Could not parse persisted device connection string!");
- }
- }
- else
- {
- Console.WriteLine("Device connection string not found in secure store.");
- }
- }
- else
- {
- Console.WriteLine("Application name not passed as argument, patching gateway config file abandoned");
- }
-
- IntPtr gateway = GatewayInterop.CreateFromJson(gatewayConfigFile);
- if (gateway != IntPtr.Zero)
- {
- Console.WriteLine(".NET Core Gateway is running. Press enter to quit.");
- Console.ReadLine();
- GatewayInterop.Destroy(gateway);
- }
- else
- {
- Console.WriteLine(".NET Core Gateway failed to initialize. Please make sure you have published the GatewayApp.NetCore app to make sure the depend DLLs are available!");
- }
- }
-
- private static bool IsX64Process()
- {
- return (IntPtr.Size == 8);
- }
- }
-}
diff --git a/src/GatewayApp.NetCore/Properties/PublishProfiles/FolderProfile.pubxml b/src/GatewayApp.NetCore/Properties/PublishProfiles/FolderProfile.pubxml
deleted file mode 100644
index 6f3aaf4..0000000
--- a/src/GatewayApp.NetCore/Properties/PublishProfiles/FolderProfile.pubxml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- FileSystem
- Debug
- netcoreapp1.1
- bin\Debug\netcoreapp1.1\
- win10-x64
-
-
\ No newline at end of file
diff --git a/src/GatewayApp.NetCore/Properties/launchSettings.json b/src/GatewayApp.NetCore/Properties/launchSettings.json
deleted file mode 100644
index 685b5aa..0000000
--- a/src/GatewayApp.NetCore/Properties/launchSettings.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "profiles": {
- "GatewayApp.NetCore": {
- "commandName": "Project",
- "commandLineArgs": "myapp",
- "workingDirectory": ".\\bin\\Debug\\netcoreapp1.1"
- }
- }
-}
\ No newline at end of file
diff --git a/src/GatewayApp.NetCore/gatewayconfig.json b/src/GatewayApp.NetCore/gatewayconfig.json
deleted file mode 100644
index 7bae607..0000000
--- a/src/GatewayApp.NetCore/gatewayconfig.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "modules": [
- {
- "name": "OpcUa",
- "loader": {
- "name": "dotnetcore",
- "entrypoint": {
- "assembly.name": "Opc.Ua.Publisher.Module",
- "entry.type": "Opc.Ua.Publisher.Module"
- }
- },
- "args": {
- "Configuration": {
- "ApplicationName": "",
- "ApplicationType": "ClientAndServer",
- "ApplicationUri": "urn:localhost:microsoft:publisher"
- }
- }
- },
- {
- "name": "IoTHub",
- "loader": {
- "name": "dotnetcore",
- "entrypoint": {
- "assembly.name": "Opc.Ua.IoTHub.Module",
- "entry.type": "Opc.Ua.IoTHub.Module"
- }
- },
- "args": ""
- }
- ],
- "links": [
- {
- "source": "OpcUa",
- "sink": "IoTHub"
- }
- ]
-}
diff --git a/src/IoTHubCredentialTools/IoTHubCredentialTools.csproj b/src/IoTHubCredentialTools/IoTHubCredentialTools.csproj
deleted file mode 100644
index a9617e9..0000000
--- a/src/IoTHubCredentialTools/IoTHubCredentialTools.csproj
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- netstandard1.3
- IoTHubCredentialTools
- IoTHubCredentialTools
- 1.6.1
- false
- true
- false
- true
-
- Microsoft
-
-
-
-
-
-
-
-
diff --git a/src/IoTHubCredentialTools/IoTHubRegistration.cs b/src/IoTHubCredentialTools/IoTHubRegistration.cs
deleted file mode 100644
index 8dfeeca..0000000
--- a/src/IoTHubCredentialTools/IoTHubRegistration.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-
-using System;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace IoTHubCredentialTools
-{
- public class IoTHubRegistration
- {
- public const string _IoTHubAPIVersion = "?api-version=2016-11-14";
-
- ///
- /// Returns an array of the parsed parts of a connection string
- ///
- public static string[] ParseConnectionString(string connectionString, bool isDevice)
- {
- string[] connectionStringParts = connectionString.Split(';');
- if (connectionStringParts.Length == 3)
- {
- if (connectionStringParts[0].StartsWith("HostName="))
- {
- connectionStringParts[0] = connectionStringParts[0].Substring(connectionStringParts[0].IndexOf('=') + 1);
- }
- else
- {
- return null;
- }
-
- if (connectionStringParts[1].StartsWith("DeviceId=") && (isDevice == true))
- {
- connectionStringParts[1] = connectionStringParts[1].Substring(connectionStringParts[1].IndexOf('=') + 1);
- }
- else if (connectionStringParts[1].StartsWith("SharedAccessKeyName=") && (isDevice == false))
- {
- connectionStringParts[1] = connectionStringParts[1].Substring(connectionStringParts[1].IndexOf('=') + 1);
- }
- else
- {
- return null;
- }
-
- if (connectionStringParts[2].StartsWith("SharedAccessKey="))
- {
- connectionStringParts[2] = connectionStringParts[2].Substring(connectionStringParts[2].IndexOf('=') + 1);
- }
- else
- {
- return null;
- }
-
- return connectionStringParts;
- }
- else
- {
- return null;
- }
- }
-
- ///
- /// Creates a device in the IoT Hub device registry using the IoT Hub REST API
- ///
- public static async Task CreateDeviceInIoTHubDeviceRegistry(HttpClient httpClient, string deviceName)
- {
- // check if device already registered
- HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "/devices/" + deviceName + _IoTHubAPIVersion);
-
- HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
- if (response.IsSuccessStatusCode)
- {
- // already registered, delete existing device first
- request = new HttpRequestMessage(HttpMethod.Delete, "/devices/" + deviceName + _IoTHubAPIVersion);
- request.Headers.IfMatch.Add(new EntityTagHeaderValue("\"*\""));
-
- response = await httpClient.SendAsync(request).ConfigureAwait(false);
- if (!response.IsSuccessStatusCode)
- {
- throw new Exception("Delete device failed with " + response.Content.ReadAsStringAsync().Result);
- }
- }
-
- // now create a new one
- string jsonMessage = "{\"deviceId\": \"" + deviceName + "\"}";
- request = new HttpRequestMessage(HttpMethod.Put, "/devices/" + deviceName + _IoTHubAPIVersion)
- {
- Content = new StringContent(jsonMessage, Encoding.ASCII, "application/json")
- };
-
- response = await httpClient.SendAsync(request).ConfigureAwait(false);
- if (!response.IsSuccessStatusCode)
- {
- throw new Exception("Create device failed with " + response.Content.ReadAsStringAsync().Result);
- }
-
- string result = response.Content.ReadAsStringAsync().Result;
- if (result.Contains("primaryKey"))
- {
- const string keyIdentifier = "\"primaryKey\":\"";
- const int keylength = 44;
- return result.Substring(result.IndexOf(keyIdentifier) + keyIdentifier.Length, keylength);
- }
- else
- {
- throw new Exception("Could not find primary key in response: " + response.Content.ReadAsStringAsync().Result);
- }
- }
-
- ///
- /// Registers a device with IoT Hub
- ///
- public static string RegisterDeviceWithIoTHub(string deviceName, string IoTHubOwnerConnectionString)
- {
- string[] parsedConnectionString = ParseConnectionString(IoTHubOwnerConnectionString, false);
- string deviceConnectionString = string.Empty;
- if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
- {
- string IoTHubName = parsedConnectionString[0];
- string name = parsedConnectionString[1];
- string accessToken = parsedConnectionString[2];
-
- using (HttpClient httpClient = new HttpClient())
- {
- httpClient.BaseAddress = new UriBuilder { Scheme = "https", Host = IoTHubName }.Uri;
-
- string sharedAccessSignature = GenerateSharedAccessToken(name, Convert.FromBase64String(accessToken), IoTHubName, 60000);
- httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessSignature);
- deviceConnectionString = CreateDeviceInIoTHubDeviceRegistry(httpClient, deviceName.Replace(" ", "")).Result;
-
- // prepend the rest of the connection string
- deviceConnectionString = "HostName=" + IoTHubName + ";DeviceId=" + deviceName.Replace(" ", "") + ";SharedAccessKey=" + deviceConnectionString;
- return deviceConnectionString;
- }
- }
- else
- {
- throw new Exception("Could not parse IoT Hub owner connection string: " + IoTHubOwnerConnectionString);
- }
- }
-
- ///
- /// Sas token generation
- ///
- ///
- ///
- ///
- ///
- /// shared access token
- public static string GenerateSharedAccessToken(string keyName, byte[] key, string tokenScope, int ttl)
- {
- // http://msdn.microsoft.com/en-us/library/azure/dn170477.aspx
- // signature is computed from joined encoded request Uri string and expiry string
-
- DateTime expiryTime = DateTime.UtcNow + TimeSpan.FromMilliseconds(ttl);
- string expiry = ((long)(expiryTime - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString();
- string encodedScope = Uri.EscapeDataString(tokenScope);
- string sig;
-
- // the connection string signature is base64 encoded
- using (var hmac = new HMACSHA256(key))
- {
- sig = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedScope + "\n" + expiry)));
- }
-
- return string.Format(
- "sr={0}&sig={1}&se={2}&skn={3}",
- encodedScope,
- Uri.EscapeDataString(sig),
- Uri.EscapeDataString(expiry),
- Uri.EscapeDataString(keyName)
- );
- }
- }
-}
diff --git a/src/Logs/myApp.Publisher.Module.log.txt b/src/Logs/myApp.Publisher.Module.log.txt
new file mode 100644
index 0000000..9b14759
--- /dev/null
+++ b/src/Logs/myApp.Publisher.Module.log.txt
@@ -0,0 +1,11 @@
+
+************************* Logging started at 06/30/2017 18:35:20
+18:35:20.513 Attemping to load nodes file from: C:\Users\erichb\Source\Repos\iot-gateway-opc-ua\src\publishednodes.json
+18:35:20.823 Loaded 2 nodes.
+18:35:20.825 Starting server on endpoint opc.tcp://myapp:62222/UA/Publisher...
+18:35:21.379 Server: Session Monitor Thread Started.
+18:35:21.411 Server: Publish Subscriptions Thread Started.
+18:35:21.414 Server started.
+18:35:21.414 Attemping to connect to servers...
+18:35:21.415 Connecting to server: opc.tcp://myopcservername:51210/UA/SampleServer
+18:35:21.435 Channel 0 in Connecting state.
diff --git a/src/Opc.Ua.Publisher.Module/ModuleConfiguration.cs b/src/ModuleConfiguration.cs
similarity index 87%
rename from src/Opc.Ua.Publisher.Module/ModuleConfiguration.cs
rename to src/ModuleConfiguration.cs
index 660a2b0..6acef7f 100644
--- a/src/Opc.Ua.Publisher.Module/ModuleConfiguration.cs
+++ b/src/ModuleConfiguration.cs
@@ -1,8 +1,5 @@
-
-using Newtonsoft.Json;
-using System;
+using System;
using System.Collections.Generic;
-using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
namespace Opc.Ua.Publisher
@@ -10,26 +7,19 @@ namespace Opc.Ua.Publisher
///
/// Module configuration object to deserialize / serialize
///
- [JsonObject(MemberSerialization.OptIn)]
public class ModuleConfiguration
{
///
/// Opc client configuration
///
- [JsonProperty]
public ApplicationConfiguration Configuration { get; set; }
- ///
- /// Called when the object is deserialized
- ///
- ///
- [OnDeserialized]
- internal void OnDeserializedMethod(StreamingContext context)
+ public ModuleConfiguration(string applicationName)
{
- // Validate configuration and set reasonable defaults
-
- Configuration.ApplicationUri = Configuration.ApplicationUri.Replace("localhost", Utils.GetHostName());
-
+ // set reasonable defaults
+ Configuration = new ApplicationConfiguration();
+ Configuration.ApplicationName = applicationName;
+ Configuration.ApplicationUri = "urn:" + Utils.GetHostName() + ":microsoft:" + Configuration.ApplicationName;
Configuration.ApplicationType = ApplicationType.ClientAndServer;
Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 };
Configuration.ClientConfiguration = new ClientConfiguration();
@@ -120,13 +110,13 @@ namespace Opc.Ua.Publisher
ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();
if (store == null)
{
- Module.Trace("Could not open trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
+ Program.Trace("Could not open trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
}
else
{
try
{
- Module.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
+ Program.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
X509Certificate2 publicKey = new X509Certificate2(certificate.RawData);
store.Add(publicKey).Wait();
}
@@ -138,7 +128,7 @@ namespace Opc.Ua.Publisher
}
catch (Exception e)
{
- Module.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
+ Program.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath);
}
// patch our base address
diff --git a/src/Opc.Ua.Publisher.Module/NodeManager.cs b/src/NodeManager.cs
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/NodeManager.cs
rename to src/NodeManager.cs
diff --git a/src/Opc.Ua.IoTHub.Module/AmqpConnection.cs b/src/Opc.Ua.IoTHub.Module/AmqpConnection.cs
deleted file mode 100644
index 31f25dd..0000000
--- a/src/Opc.Ua.IoTHub.Module/AmqpConnection.cs
+++ /dev/null
@@ -1,599 +0,0 @@
-
-using System;
-using System.Text;
-using System.Threading.Tasks;
-using Amqp;
-using Amqp.Framing;
-using Amqp.Sasl;
-using System.IO;
-using System.Net;
-using System.Threading;
-using System.Diagnostics;
-using System.Collections.Generic;
-using IoTHubCredentialTools;
-
-namespace Opc.Ua.IoTHub
-{
- public class AmqpConnection
- {
- #region Serialized Configuration Properties
-
- public string Host { get; set; }
-
- public int Port { get; set; }
-
- public string Endpoint { get; set; }
-
- public string WebSocketEndpoint { get; set; }
-
- public string KeyName { get; set; }
-
- public string KeyValue { get; set; }
-
- public string KeyEncoding { get; set; }
-
- public bool UseCbs { get; set; }
-
- public string TokenType { get; set; }
-
- public string TokenScope { get; set; }
-
- public int TokenLifetime { get; set; }
-
- #endregion
-
- #region Private members
-
- private Connection m_connection;
- private Session m_session;
- private SenderLink m_link;
- private LinkedList> messages;
-
- private DateTime m_currentExpiryTime;
- private Timer m_tokenRenewalTimer;
- private bool m_closed;
- private int m_sendCounter;
- private int m_sendAcceptedCounter;
- private int m_sendRejectedCounter;
- private object m_sending;
- private int m_sendallthreads;
-
- #endregion
-
- #region Constructor
-
- ///
- /// Default Constructor
- ///
- public AmqpConnection()
- {
- Initialize();
- }
-
- ///
- /// Initialize the connection class
- ///
- private void Initialize()
- {
- m_connection = null;
- m_session = null;
- m_link = null;
- m_closed = true;
- m_sending = new object();
- m_sendallthreads = 0;
- messages = new LinkedList>();
- m_sendCounter = 0;
- m_sendAcceptedCounter = 0;
- m_sendRejectedCounter = 0;
- }
-
- #endregion
-
- ///
- /// Open the connection
- ///
- public async Task OpenAsync()
- {
- // make sure only one SendAll or OpenAsync task is active
- if (Interlocked.Increment(ref m_sendallthreads) != 1)
- {
- Interlocked.Decrement(ref m_sendallthreads);
- return;
- }
-
- try
- {
- Close();
-
- ConnectionFactory factory = new ConnectionFactory();
- factory.AMQP.ContainerId = Guid.NewGuid().ToString();
- if (UseCbs)
- {
- factory.SASL.Profile = SaslProfile.External;
- }
-
- m_connection = await factory.CreateAsync(GetAddress());
- m_connection.Closed += new ClosedCallback(OnConnectionClosed);
-
- if (UseCbs && KeyName != null && KeyValue != null)
- {
- await StartCbs();
- }
- else
- {
- await ResetLinkAsync();
- }
-
- Module.Trace("AMQP Connection opened, connected to '{0}'...", Endpoint);
-
- m_closed = false;
- }
- catch (Exception e)
- {
- Module.Trace("AMQP Connection failed to open, exception: {0}...", e.Message);
- }
- finally
- {
- Interlocked.Decrement(ref m_sendallthreads);
- }
-
- // Push out the messages we have so far
- SendAll();
- }
-
- ///
- /// Publish a JSON message
- ///
- ///
- public void Publish(ArraySegment body)
- {
- lock (messages)
- {
- messages.AddLast(body);
- }
-
- if (IsClosed())
- {
- Task.Run(OpenAsync);
- }
- else
- {
- // Push out the messages we have so far
- Task.Run(new Action(SendAll));
- }
- }
-
- ///
- /// Work until all messages have been send...
- ///
- protected void SendAll()
- {
- // make sure only one send all task is active
- if (Interlocked.Increment(ref m_sendallthreads) != 1)
- {
- Interlocked.Decrement(ref m_sendallthreads);
- return;
- }
-
- try
- {
-
- while (!IsClosed())
- {
- ArraySegment onemessage;
- lock (messages)
- {
- if (messages.Count == 0)
- {
- break;
- }
- onemessage = messages.First.Value;
- messages.RemoveFirst();
- }
-
- bool sent;
- lock (m_sending)
- {
- sent = SendOneAsync(onemessage, SendAllCallback);
- }
-
- if (!sent)
- {
- lock (messages)
- {
- messages.AddFirst(onemessage);
- }
- }
- }
- }
- catch (Exception)
- {
- Close();
- }
- finally
- {
- Interlocked.Decrement(ref m_sendallthreads);
- }
- }
-
- ///
- /// Send outcome callback
- ///
- ///
- /// Whether message was sent
- void SendAllCallback(Message message, Outcome outcome, object state)
- {
- if (outcome.Descriptor.Code == 36)
- {
- // accepted
- m_sendAcceptedCounter++;
- }
- else
- {
- // rejected or other fail reason
- m_sendRejectedCounter++;
- }
- if (((m_sendRejectedCounter + m_sendAcceptedCounter) % 100) == 0)
- {
- Module.Trace("Send Statistics: {0} sent {1} accepted {2} rejected",
- m_sendCounter, m_sendAcceptedCounter, m_sendRejectedCounter);
- }
- }
-
- ///
- /// Send message
- ///
- ///
- /// Whether message was sent
- protected bool SendOneAsync(ArraySegment body, OutcomeCallback SendCallback)
- {
- if (IsClosed())
- {
- return false;
- }
-
- using (var istrm = new MemoryStream(body.Array, body.Offset, body.Count, false))
- {
- Message message = new Message()
- {
- BodySection = new Data() { Binary = istrm.ToArray() }
- };
-
- message.Properties = new Properties()
- {
- MessageId = Guid.NewGuid().ToString(),
- ContentType = "application/opcua+json"
- };
-
- if (m_link != null)
- {
- m_sendCounter++;
- m_link.Send(message, SendCallback, null);
- return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Close and therefore dispose of all resources
- ///
- public void Close()
- {
- m_closed = true;
- if (m_tokenRenewalTimer != null)
- {
- m_tokenRenewalTimer.Dispose();
- m_tokenRenewalTimer = null;
- }
- Dispose(true);
- }
-
- ///
- /// is the connection closed?
- ///
- /// true or false
- public bool IsClosed()
- {
- return m_closed;
- }
-
- ///
- /// Destructor
- ///
- public void Dispose()
- {
- Dispose(true);
- }
-
- ///
- /// Close all resources
- ///
- ///
- public virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (m_tokenRenewalTimer != null)
- {
- m_tokenRenewalTimer.Dispose();
- m_tokenRenewalTimer = null;
- }
-
- if (m_link != null)
- {
- try
- {
- m_link.Close(3000);
- }
- catch(Exception)
- {
- }
- m_link = null;
- }
-
- if (m_session != null)
- {
- try
- {
- m_session.Close(3000);
- }
- catch (Exception)
- {
- }
- m_session = null;
- }
-
- if (m_connection != null)
- {
- try
- {
- m_connection.Close(3000);
- }
- catch (Exception)
- {
- }
- m_connection = null;
- }
- }
- }
-
- ///
- /// Returns the amqp.net lite broker address to connect to.
- ///
- /// Address to connect to
- protected Address GetAddress()
- {
- if (Port == 0)
- {
- // Set default port
- if (WebSocketEndpoint != null)
- Port = 443;
- else
- Port = 5671;
- }
-
- if (WebSocketEndpoint != null)
- {
- return new Address(Host, Port, null, null, WebSocketEndpoint, "wss");
- }
- else if (UseCbs)
- {
- return new Address(Host, Port);
- }
- else
- {
- return new Address(Host, Port, KeyName.Trim(), KeyValue.Trim());
- }
- }
-
- ///
- /// Start cbs protocol on the underlying connection
- ///
- /// Task to wait on
- protected async Task StartCbs()
- {
- if (m_connection == null)
- {
- throw new Exception("No connection to run cbs renewal on!");
- }
-
- if (TokenType == null || TokenScope == null)
- {
- throw new Exception("Must specifiy token scope and type");
- }
-
- if (TokenLifetime == 0)
- {
- TokenLifetime = 60000;
- }
-
- // Ensure we have a token
- await RenewTokenAsync(GenerateSharedAccessToken());
-
- // then start the periodic renewal
- int interval = (int)(TokenLifetime * 0.8);
- m_tokenRenewalTimer = new Timer(OnTokenRenewal, null, interval, interval);
- }
-
- ///
- /// Return decoded key from configured key value
- ///
- /// decoded key
- protected byte[] DecodeKey()
- {
- if (!KeyEncoding.Equals("base64", StringComparison.CurrentCultureIgnoreCase))
- {
- return Encoding.UTF8.GetBytes(KeyValue.Trim());
- }
- else
- {
- return Convert.FromBase64String(KeyValue.Trim());
- }
- }
-
- ///
- /// Generate token for member values
- ///
- /// Token string
- protected string GenerateSharedAccessToken()
- {
- m_currentExpiryTime = DateTime.UtcNow + TimeSpan.FromMilliseconds(TokenLifetime);
- return "SharedAccessSignature " + IoTHubRegistration.GenerateSharedAccessToken(KeyName.Trim(), DecodeKey(), TokenScope.Trim(), TokenLifetime);
- }
-
-
- ///
- /// Callback for connection close events
- ///
- ///
- ///
- protected virtual void OnConnectionClosed(AmqpObject sender, Error error)
- {
- if (error != null)
- {
- Debug.WriteLine("Connection Closed {0} {1}", error.Condition, error.Description);
- }
- m_closed = true;
- }
-
- ///
- /// Callback for session close event
- ///
- ///
- ///
- protected virtual void OnSessionClosed(AmqpObject sender, Error error)
- {
- if (error != null)
- {
- Debug.WriteLine("Session Closed {0} {1}", error.Condition, error.Description);
- }
- }
-
- ///
- /// Callback for link close events
- ///
- ///
- ///
- protected virtual void OnLinkClosed(AmqpObject sender, Error error)
- {
- if (error != null)
- {
- Debug.WriteLine("Link Closed {0} {1}", error.Condition, error.Description);
- }
- }
-
- ///
- /// Timer callback for token renewal
- ///
- ///
- private void OnTokenRenewal(object state)
- {
- try
- {
- lock (m_sending)
- {
- bool result = RenewTokenAsync(GenerateSharedAccessToken()).Wait(TokenLifetime);
- if (!result)
- {
- Module.Trace("Unexpected timeout error renewing token.");
- }
- }
- }
- catch (Exception e)
- {
- Module.Trace(e, "Unexpected error renewing token.");
-
- if (e is AggregateException ae)
- {
- foreach (var ie in ae.InnerExceptions)
- {
- Module.Trace("[{0}] {1}", ie.GetType().Name, ie.Message);
- }
- }
- }
- }
-
- ///
- /// Reset the link and session
- ///
- /// Task to wait on
- private async Task ResetLinkAsync()
- {
- SenderLink link;
- Session session;
-
- session = new Session(m_connection);
- session.Closed += new ClosedCallback(OnSessionClosed);
-
- link = new SenderLink(session, Guid.NewGuid().ToString(), Endpoint);
- link.Closed += new ClosedCallback(OnLinkClosed);
-
- if (m_link != null)
- {
- await m_link.CloseAsync();
- }
-
- if (m_session != null)
- {
- await m_session.CloseAsync();
- }
-
- m_session = session;
- m_link = link;
- }
-
- ///
- /// renews the cbs token
- ///
- /// token to renew
- /// Task to wait on
- private async Task RenewTokenAsync(string sharedAccessToken)
- {
- var session = new Session(m_connection);
- string cbsClientAddress = "cbs-client-reply-to";
- var cbsSender = new SenderLink(session, "cbs-sender", "$cbs");
- var receiverAttach = new Attach()
- {
- Source = new Source() { Address = "$cbs" },
- Target = new Target() { Address = cbsClientAddress }
- };
- var cbsReceiver = new ReceiverLink(session, "cbs-receiver", receiverAttach, null);
-
- // construct the put-token message
- var request = new Message(sharedAccessToken);
- request.Properties = new Properties();
- request.Properties.MessageId = "1";
- request.Properties.ReplyTo = cbsClientAddress;
- request.ApplicationProperties = new ApplicationProperties();
-
- request.ApplicationProperties["operation"] = "put-token";
- request.ApplicationProperties["type"] = TokenType;
- request.ApplicationProperties["name"] = TokenScope.Trim();
-
- await cbsSender.SendAsync(request);
-
- // receive the response
- var response = await cbsReceiver.ReceiveAsync();
- if (response == null || response.Properties == null || response.ApplicationProperties == null)
- {
- throw new Exception("invalid response received");
- }
-
- int statusCode = (int)response.ApplicationProperties["status-code"];
-
- await cbsSender.CloseAsync();
- await cbsReceiver.CloseAsync();
- await session.CloseAsync();
-
- if (statusCode != (int)HttpStatusCode.Accepted && statusCode != (int)HttpStatusCode.OK)
- {
- throw new Exception("put-token message was not accepted. Error code: " + statusCode);
- }
-
- // Now create new link
- await ResetLinkAsync();
- }
- }
-}
diff --git a/src/Opc.Ua.IoTHub.Module/Module.cs b/src/Opc.Ua.IoTHub.Module/Module.cs
deleted file mode 100644
index a14f5d8..0000000
--- a/src/Opc.Ua.IoTHub.Module/Module.cs
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using IoTHubCredentialTools;
-using Microsoft.Azure.Devices.Gateway;
-using System;
-using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Opc.Ua.IoTHub
-{
- ///
- /// Gateway module that acts as IoT Hub connectivity
- ///
- public class Module : IGatewayModule
- {
- private static AmqpConnection m_publisher = new AmqpConnection();
- private static StreamWriter m_trace = null;
-
- ///
- /// Trace message helper
- ///
- public static void Trace(string message, params object[] args)
- {
- m_trace.WriteLine(message, args);
- Console.WriteLine(message, args);
- }
-
- public static void Trace(int traceMask, string format, params object[] args)
- {
- m_trace.WriteLine(format, args);
- Console.WriteLine(format, args);
- }
-
- public static void Trace(Exception e, string format, params object[] args)
- {
- m_trace.WriteLine(e.ToString());
- m_trace.WriteLine(format, args);
- Console.WriteLine(e.ToString());
- Console.WriteLine(format, args);
- }
-
- ///
- /// Create module, throws if configuration is bad
- ///
- public void Create(Broker broker, byte[] configuration)
- {
- string appName = Encoding.UTF8.GetString(configuration).Replace("\"","");
-
- // enable logging
- m_trace = new StreamWriter(File.Open("./Logs/" + appName + ".IoTHub.Module.log.txt", FileMode.Create));
-
- Trace("Opc.Ua.IoTHub.Module: Creating...");
-
- // configure connection
- try
- {
- ConfigureAMQPConnectionToIoTHub(appName).Wait();
- }
- catch (Exception ex)
- {
- Module.Trace(ex, "Failed to configure AMQP connection, dropping....");
- }
-
- Trace("Opc.Ua.IoTHub.Module: Created.");
- }
-
- ///
- /// Disconnect all sessions
- ///
- public void Destroy()
- {
- m_publisher.Close();
-
- Trace("Opc.Ua.IoTHub.Module: Closed.");
-
- m_trace.Flush();
- m_trace.Dispose();
- }
-
- ///
- /// Receive message from broker
- ///
- public void Receive(Message received_message)
- {
- try
- {
- if (!m_publisher.IsClosed())
- {
- m_publisher.Publish(new ArraySegment(received_message.Content));
- }
- }
- catch (Exception ex)
- {
- Module.Trace(ex, "Failed to publish message, dropping....");
- }
- }
-
- ///
- /// Publish message to bus
- ///
- public static void Publish(Message message)
- {
- // NO-OP
- }
-
- ///
- /// Configures the AMQP (telemetry) connection to IoT Hub
- ///
- public static async Task ConfigureAMQPConnectionToIoTHub(string appName)
- {
- Trace("Opc.Ua.IoTHub.Module: Attemping to read connection string from secure store with certificate name: " + appName);
- string connectionString = SecureIoTHubToken.Read(appName);
-
- Trace("Opc.Ua.IoTHub.Module: Attemping to configure IoTHub module with connection string: " + connectionString);
- string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(connectionString, true);
- string IoTHubName = parsedConnectionString[0];
- string deviceName = parsedConnectionString[1];
- string accessToken = parsedConnectionString[2];
-
- m_publisher.Endpoint = "/devices/" + deviceName + "/messages/events";
- m_publisher.WebSocketEndpoint = null; // not used
- m_publisher.Host = IoTHubName;
- m_publisher.Port = 0; // use default
- m_publisher.KeyName = ""; // not used
- m_publisher.KeyValue = accessToken;
- m_publisher.KeyEncoding = "Base64";
- m_publisher.UseCbs = true;
- m_publisher.TokenType = "servicebus.windows.net:sastoken";
- m_publisher.TokenScope = m_publisher.Host + "/devices/" + deviceName;
- m_publisher.TokenLifetime = 60000;
-
- await m_publisher.OpenAsync();
- }
- }
-}
diff --git a/src/Opc.Ua.IoTHub.Module/Opc.Ua.IoTHub.Module.csproj b/src/Opc.Ua.IoTHub.Module/Opc.Ua.IoTHub.Module.csproj
deleted file mode 100644
index ef6aaa5..0000000
--- a/src/Opc.Ua.IoTHub.Module/Opc.Ua.IoTHub.Module.csproj
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- netstandard1.3
- portable
- Opc.Ua.IoTHub.Module
- Opc.Ua.IoTHub.Module
- false
- true
- false
- true
-
- Microsoft
- Opc.Ua.IoTHub
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Opc.Ua.Publisher.Module/Opc.Ua.Publisher.Module.csproj b/src/Opc.Ua.Publisher.Module/Opc.Ua.Publisher.Module.csproj
deleted file mode 100644
index f5d2199..0000000
--- a/src/Opc.Ua.Publisher.Module/Opc.Ua.Publisher.Module.csproj
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
- netstandard1.3
- portable
- Opc.Ua.Publisher.Module
- Opc.Ua.Publisher.Module
- false
- true
- false
- true
-
- Microsoft
- Opc.Ua.Publisher
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Opc.Ua.Publisher.csproj b/src/Opc.Ua.Publisher.csproj
new file mode 100644
index 0000000..a1dc00a
--- /dev/null
+++ b/src/Opc.Ua.Publisher.csproj
@@ -0,0 +1,36 @@
+
+
+
+ netcoreapp1.1
+ Opc.Ua.Publisher
+ Exe
+ Opc.Ua.Publisher
+ 1.1.2
+ true
+ true
+
+ Microsoft
+ 1.1.2
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Opc.Ua.Publisher.sln b/src/Opc.Ua.Publisher.sln
new file mode 100644
index 0000000..369aedf
--- /dev/null
+++ b/src/Opc.Ua.Publisher.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opc.Ua.Publisher", "Opc.Ua.Publisher.csproj", "{EAC47E1C-39F4-4E51-A241-88432552D461}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EAC47E1C-39F4-4E51-A241-88432552D461}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EAC47E1C-39F4-4E51-A241-88432552D461}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EAC47E1C-39F4-4E51-A241-88432552D461}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EAC47E1C-39F4-4E51-A241-88432552D461}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/Opc.Ua.Publisher.Module/Module.cs b/src/Program.cs
similarity index 54%
rename from src/Opc.Ua.Publisher.Module/Module.cs
rename to src/Program.cs
index 5f3d9a9..0299f43 100644
--- a/src/Opc.Ua.Publisher.Module/Module.cs
+++ b/src/Program.cs
@@ -1,38 +1,28 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
+
+using IoTHubCredentialTools;
+using Microsoft.Azure.Devices;
+using Microsoft.Azure.Devices.Client;
+using Newtonsoft.Json;
+using Opc.Ua.Client;
+using Publisher;
using System;
using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Text;
-using Newtonsoft.Json;
-using Microsoft.Azure.Devices.Gateway;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using Publisher;
-using Opc.Ua.Client;
-using IoTHubCredentialTools;
using System.IO;
-using System.Net;
+using System.Text;
+using System.Threading.Tasks;
namespace Opc.Ua.Publisher
{
- ///
- /// Gateway module that acts as Opc.Ua Publisher and Server
- ///
- public class Module : IGatewayModule, IGatewayModuleStart
+ public class Program
{
public static ApplicationConfiguration m_configuration = null;
public static List m_sessions = new List();
public static PublishedNodesCollection m_nodesLookups = new PublishedNodesCollection();
public static List m_endpointUrls = new List();
- public static string m_deviceName = string.Empty;
- public static string m_accessKey = string.Empty;
+ public static string m_applicationName = string.Empty;
+ public static DeviceClient m_deviceClient = null;
- private static Broker m_broker = null;
- private PublisherServer m_server = new PublisherServer();
-
- private const string m_IoTHubAPIVersion = "?api-version=2016-11-14";
+ private static PublisherServer m_server = new PublisherServer();
///
/// Trace message helper
@@ -56,29 +46,79 @@ namespace Opc.Ua.Publisher
Console.WriteLine(format, args);
}
- ///
- /// Create module, throws if configuration is bad
- ///
- public void Create(Broker broker, byte[] configuration)
+ public static void Main(string[] args)
{
- Trace("Opc.Ua.Publisher.Module: Creating...");
-
- m_broker = broker;
-
- string configString = Encoding.UTF8.GetString(configuration);
-
- // Deserialize from configuration string
- ModuleConfiguration moduleConfiguration = null;
- try
+ if ((args.Length == 0) || string.IsNullOrEmpty(args[0]))
{
- moduleConfiguration = JsonConvert.DeserializeObject(configString);
- }
- catch (Exception ex)
- {
- Trace("Opc.Ua.Publisher.Module: Module config string " + configString + " could not be deserialized: " + ex.Message);
- throw;
+ Console.WriteLine("Please specify an application name as argument!");
+ return;
}
+ m_applicationName = args[0];
+ string ownerConnectionString = string.Empty;
+
+ // check if we also received an owner connection string
+ if ((args.Length > 1) && !string.IsNullOrEmpty(args[1]))
+ {
+ ownerConnectionString = args[1];
+ }
+ else
+ {
+ Trace("IoT Hub owner connection string not passed as argument.");
+
+ // check if we have an environment variable to register ourselves with IoT Hub
+ if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_HUB_CS")))
+ {
+ ownerConnectionString = Environment.GetEnvironmentVariable("_HUB_CS");
+ }
+ }
+
+ // register ourselves with IoT Hub
+ if (ownerConnectionString != string.Empty)
+ {
+ Trace("Attemping to register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
+ RegistryManager manager = RegistryManager.CreateFromConnectionString(ownerConnectionString);
+
+ // remove any existing device
+ Device existingDevice = manager.GetDeviceAsync(m_applicationName).Result;
+ if (existingDevice != null)
+ {
+ manager.RemoveDeviceAsync(m_applicationName).Wait();
+ }
+
+ Device newDevice = manager.AddDeviceAsync(new Device(m_applicationName)).Result;
+ if (newDevice != null)
+ {
+ string hostname = ownerConnectionString.Substring(0, ownerConnectionString.IndexOf(";"));
+ string deviceConnectionString = hostname + ";DeviceId=" + m_applicationName + ";SharedAccessKey=" + newDevice.Authentication.SymmetricKey.PrimaryKey;
+ SecureIoTHubToken.Write(m_applicationName, deviceConnectionString);
+ }
+ else
+ {
+ Trace("Could not register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
+ }
+ }
+ else
+ {
+ Trace("IoT Hub owner connection string not found, registration with IoT Hub abandoned.");
+ }
+
+ // try to read connection string from secure store and open IoTHub client
+ Trace("Attemping to read connection string from secure store with certificate name: " + m_applicationName);
+ string connectionString = SecureIoTHubToken.Read(m_applicationName);
+ if (!string.IsNullOrEmpty(connectionString))
+ {
+ Trace("Attemping to configure publisher with connection string: " + connectionString);
+ m_deviceClient = DeviceClient.CreateFromConnectionString(connectionString, Microsoft.Azure.Devices.Client.TransportType.Mqtt);
+ m_deviceClient.RetryPolicy = RetryPolicyType.Exponential_Backoff_With_Jitter;
+ m_deviceClient.OpenAsync().Wait();
+ }
+ else
+ {
+ Trace("Device connection string not found in secure store.");
+ }
+
+ ModuleConfiguration moduleConfiguration = new ModuleConfiguration(m_applicationName);
m_configuration = moduleConfiguration.Configuration;
m_configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
@@ -99,15 +139,15 @@ namespace Opc.Ua.Publisher
publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP");
}
- Trace("Opc.Ua.Publisher.Module: Attemping to load nodes file from: " + publishedNodesFilePath);
+ Trace("Attemping to load nodes file from: " + publishedNodesFilePath);
m_nodesLookups = JsonConvert.DeserializeObject(File.ReadAllText(publishedNodesFilePath));
- Trace("Opc.Ua.Publisher.Module: Loaded " + m_nodesLookups.Count.ToString() + " nodes.");
+ Trace("Loaded " + m_nodesLookups.Count.ToString() + " nodes.");
}
catch (Exception ex)
{
- Trace("Opc.Ua.Publisher.Module: Nodes file loading failed with: " + ex.Message);
+ Trace("Nodes file loading failed with: " + ex.Message);
}
-
+
foreach (NodeLookup nodeLookup in m_nodesLookups)
{
if (!m_endpointUrls.Contains(nodeLookup.EndPointURL))
@@ -119,46 +159,23 @@ namespace Opc.Ua.Publisher
// start the server
try
{
- Trace("Opc.Ua.Publisher.Module: Starting server on endpoint " + m_configuration.ServerConfiguration.BaseAddresses[0].ToString() + "...");
+ Trace("Starting server on endpoint " + m_configuration.ServerConfiguration.BaseAddresses[0].ToString() + "...");
m_server.Start(m_configuration);
- Trace("Opc.Ua.Publisher.Module: Server started.");
+ Trace("Server started.");
}
catch (Exception ex)
{
- Trace("Opc.Ua.Publisher.Module: Starting server failed with: " + ex.Message);
+ Trace("Starting server failed with: " + ex.Message);
}
- // check if we have an environment variable to register ourselves with IoT Hub
- if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_HUB_CS")))
- {
- string ownerConnectionString = Environment.GetEnvironmentVariable("_HUB_CS");
-
- if ((m_configuration != null) && (!string.IsNullOrEmpty(m_configuration.ApplicationName)))
- {
- Trace("Attemping to register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
- string deviceConnectionString = IoTHubRegistration.RegisterDeviceWithIoTHub(m_configuration.ApplicationName, ownerConnectionString);
- if (!string.IsNullOrEmpty(deviceConnectionString))
- {
- SecureIoTHubToken.Write(m_configuration.ApplicationName, deviceConnectionString);
- }
- else
- {
- Trace("Could not register ourselves with IoT Hub using owner connection string: " + ownerConnectionString);
- }
- }
- }
-
- // try to configure our publisher component
- TryConfigurePublisherAsync().Wait();
-
// connect to servers
- Trace("Opc.Ua.Publisher.Module: Attemping to connect to servers...");
+ Trace("Attemping to connect to servers...");
try
{
List connectionAttempts = new List();
foreach (Uri endpointUrl in m_endpointUrls)
{
- Trace("Opc.Ua.Publisher.Module: Connecting to server: " + endpointUrl);
+ Trace("Connecting to server: " + endpointUrl);
connectionAttempts.Add(EndpointConnect(endpointUrl));
}
@@ -167,105 +184,11 @@ namespace Opc.Ua.Publisher
}
catch (Exception ex)
{
- Trace("Opc.Ua.Publisher.Module: Exception: " + ex.ToString() + "\r\n" + ex.InnerException != null ? ex.InnerException.ToString() : null);
+ Trace("Exception: " + ex.ToString() + "\r\n" + ex.InnerException != null ? ex.InnerException.ToString() : null);
}
- Trace("Opc.Ua.Publisher.Module: Created.");
- }
-
- ///
- /// Disconnect all sessions
- ///
- public void Destroy()
- {
- foreach (Session session in m_sessions)
- {
- session.Close();
- }
-
- Trace("Opc.Ua.Publisher.Module: All sessions closed.");
- }
-
- ///
- /// Receive message from broker
- ///
- public void Receive(Message received_message)
- {
- // No-op
- }
-
- ///
- /// Try to configure our Publisher settings
- ///
- public static async Task TryConfigurePublisherAsync()
- {
- // read connection string from secure store and configure publisher, if possible
- if ((m_configuration != null) && (!string.IsNullOrEmpty(m_configuration.ApplicationName)))
- {
- Trace("Opc.Ua.Publisher.Module: Attemping to read connection string from secure store with certificate name: " + m_configuration.ApplicationName);
- string connectionString = SecureIoTHubToken.Read(m_configuration.ApplicationName);
- if (!string.IsNullOrEmpty(connectionString))
- {
- Trace("Opc.Ua.Publisher.Module: Attemping to configure publisher with connection string: " + connectionString);
- string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(connectionString, true);
- if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
- {
- // note: IoTHub name can't be changed during runtime in the GW IoTHub module
- string _IoTHubName = parsedConnectionString[0];
- m_deviceName = parsedConnectionString[1];
- m_accessKey = parsedConnectionString[2];
-
- Trace("Opc.Ua.Publisher.Module: Publisher configured for device: " + m_deviceName);
-
- // try to connect to IoT Hub
- using (HttpClient httpClient = new HttpClient())
- {
- httpClient.BaseAddress = new UriBuilder { Scheme = "https", Host = _IoTHubName }.Uri;
-
- string sharedAccessToken = IoTHubRegistration.GenerateSharedAccessToken(string.Empty, Convert.FromBase64String(m_accessKey), _IoTHubName, 60000);
- httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessToken);
-
- // send an empty d2c message
- HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "/devices/" + m_deviceName + "/messages/events" + IoTHubRegistration._IoTHubAPIVersion);
- HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
- if (response.StatusCode != HttpStatusCode.NoContent)
- {
- throw new Exception("Opc.Ua.Publisher.Module: Could not connect to IoT Hub. Response: " + response.ToString());
- }
- }
- }
- else
- {
- throw new Exception("Opc.Ua.Publisher.Module: Publisher configuration failed!");
- }
- }
- else
- {
- Trace("Opc.Ua.Publisher.Module: Connection string not found in secure store.");
- }
- }
- }
-
- ///
- /// Publish message to bus
- ///
- public static void Publish(Message message)
- {
- if (m_broker != null)
- {
- m_broker.Publish(message);
- }
- }
-
- ///
- /// Called when gateway starts, establishes the connections to endpoints
- ///
- public void Start()
- {
- Trace("Opc.Ua.Publisher.Module: Starting...");
-
// subscribe to preconfigured nodes
- Trace("Opc.Ua.Publisher.Module: Attemping to subscribe to published nodes...");
+ Trace("Attemping to subscribe to published nodes...");
if (m_nodesLookups != null)
{
foreach (NodeLookup nodeLookup in m_nodesLookups)
@@ -276,43 +199,20 @@ namespace Opc.Ua.Publisher
}
catch (Exception ex)
{
- Trace("Opc.Ua.Publisher.Module: Unexpected error publishing node: " + ex.Message + "\r\nIgnoring node: " + nodeLookup.EndPointURL.AbsoluteUri + ", " + nodeLookup.NodeID.ToString());
+ Trace("Unexpected error publishing node: " + ex.Message + "\r\nIgnoring node: " + nodeLookup.EndPointURL.AbsoluteUri + ", " + nodeLookup.NodeID.ToString());
}
}
}
- Trace("Opc.Ua.Publisher.Module: Started.");
- }
- ///
- /// Registers ourselves with IoTHub so we can send messages to it
- ///
- private void SelfRegisterWithIoTHub(string ownerConnectionString)
- {
- string[] parsedConnectionString = IoTHubRegistration.ParseConnectionString(ownerConnectionString, false);
- string deviceConnectionString = string.Empty;
- if ((parsedConnectionString != null) && (parsedConnectionString.Length == 3))
+ Console.WriteLine("Publisher is running. Press enter to quit.");
+ Console.ReadLine();
+
+ foreach (Session session in m_sessions)
{
- string IoTHubName = parsedConnectionString[0];
- string name = parsedConnectionString[1];
- string accessToken = parsedConnectionString[2];
-
- using (HttpClient httpClient = new HttpClient())
- {
- httpClient.BaseAddress = new UriBuilder { Scheme = "https", Host = IoTHubName }.Uri;
-
- string sharedAccessSignature = IoTHubRegistration.GenerateSharedAccessToken(name, Convert.FromBase64String(accessToken), IoTHubName, 60000);
- httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SharedAccessSignature", sharedAccessSignature);
- deviceConnectionString = IoTHubRegistration.CreateDeviceInIoTHubDeviceRegistry(httpClient, m_configuration.ApplicationName.Replace(" ", "")).Result;
-
- // prepend the rest of the connection string
- deviceConnectionString = "HostName=" + IoTHubName + ";DeviceId=" + m_configuration.ApplicationName.Replace(" ", "") + ";SharedAccessKey=" + deviceConnectionString;
- SecureIoTHubToken.Write(m_configuration.ApplicationName, deviceConnectionString);
- }
- }
- else
- {
- Trace("Opc.Ua.Publisher.Module: Could not parse IoT Hub owner connection string: " + ownerConnectionString);
+ session.Close();
}
+
+ m_deviceClient.CloseAsync().Wait();
}
///
@@ -336,7 +236,7 @@ namespace Opc.Ua.Publisher
if (newSession != null)
{
- Trace("Opc.Ua.Publisher.Module: Created session with updated endpoint " + selectedEndpoint.EndpointUrl + " from server!");
+ Trace("Created session with updated endpoint " + selectedEndpoint.EndpointUrl + " from server!");
newSession.KeepAlive += new KeepAliveEventHandler((sender, e) => StandardClient_KeepAlive(sender, e, newSession));
m_sessions.Add(newSession);
}
@@ -386,14 +286,14 @@ namespace Opc.Ua.Publisher
monitoredItem.QueueSize = 0;
monitoredItem.DiscardOldest = true;
- monitoredItem.Notification += new MonitoredItemNotificationEventHandler(Module.MonitoredItem_Notification);
+ monitoredItem.Notification += new MonitoredItemNotificationEventHandler(MonitoredItem_Notification);
subscription.AddItem(monitoredItem);
subscription.ApplyChanges();
}
else
{
- Trace("Opc.Ua.Publisher.Module: ERROR: Could not find endpoint URL " + nodeLookup.EndPointURL.ToString() + " in active server sessions, NodeID " + nodeLookup.NodeID.Identifier.ToString() + " NOT published!");
- Trace("Opc.Ua.Publisher.Module: To fix this, please update your publishednodes.json file with the updated endpoint URL!");
+ Trace("ERROR: Could not find endpoint URL " + nodeLookup.EndPointURL.ToString() + " in active server sessions, NodeID " + nodeLookup.NodeID.Identifier.ToString() + " NOT published!");
+ Trace("To fix this, please update your publishednodes.json file with the updated endpoint URL!");
}
}
@@ -425,7 +325,7 @@ namespace Opc.Ua.Publisher
string applicationURI = monitoredItem.Subscription.Session.Endpoint.Server.ApplicationUri;
encoder.WriteString("ApplicationUri", applicationURI);
encoder.WriteString("DisplayName", monitoredItem.DisplayName);
-
+
// write NodeId as ns=x;i=y
NodeId nodeId = monitoredItem.ResolvedNodeId;
encoder.WriteString("NodeId", new NodeId(nodeId.Identifier, nodeId.NamespaceIndex).ToString());
@@ -435,31 +335,25 @@ namespace Opc.Ua.Publisher
encoder.WriteDataValue("Value", value);
string json = encoder.CloseAndReturnText();
-
- // publish
- var properties = new Dictionary();
- properties.Add("content-type", "application/opcua+uajson");
- properties.Add("deviceName", m_deviceName);
+ var eventMessage = new Microsoft.Azure.Devices.Client.Message(Encoding.UTF8.GetBytes(json));
- if (m_accessKey != null)
- {
- properties.Add("source", "mapping");
- properties.Add("deviceKey", m_accessKey);
- }
+ // publish
+ eventMessage.Properties.Add("content-type", "application/opcua+uajson");
+ eventMessage.Properties.Add("deviceName", m_applicationName);
try
{
- Publish(new Message(json, properties));
+ m_deviceClient.SendEventAsync(eventMessage).Wait();
}
catch (Exception ex)
{
- Trace("Opc.Ua.Publisher.Module: Failed to publish message, dropping...");
+ Trace("Failed to publish message, dropping...");
Trace(ex.ToString());
}
}
catch (Exception exception)
{
- Trace("Opc.Ua.Publisher.Module: Error processing monitored item notification: " + exception.ToString());
+ Trace("Error processing monitored item notification: " + exception.ToString());
}
}
@@ -500,8 +394,8 @@ namespace Opc.Ua.Publisher
}
catch (Exception e)
{
- Trace("Opc.Ua.Publisher.Module: Could not fetch endpoints from url: " + discoveryUrl.ToString());
- Trace("Opc.Ua.Publisher.Module: Reason = " + e.Message);
+ Trace("Could not fetch endpoints from url: " + discoveryUrl.ToString());
+ Trace("Reason = " + e.Message);
throw e;
}
}
@@ -554,11 +448,11 @@ namespace Opc.Ua.Publisher
///
/// Standard certificate validation callback
///
- private void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
+ private static void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
{
if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted)
{
- Trace("Opc.Ua.Publisher.Module: Certificate \""
+ Trace("Certificate \""
+ e.Certificate.Subject
+ "\" not trusted. If you want to trust this certificate, please copy it from the \""
+ m_configuration.SecurityConfiguration.RejectedCertificateStore.StorePath + "/certs"
@@ -567,5 +461,6 @@ namespace Opc.Ua.Publisher
+ "\" folder. A restart of the gateway is NOT required.");
}
}
+
}
}
diff --git a/src/Properties/launchSettings.json b/src/Properties/launchSettings.json
new file mode 100644
index 0000000..c722648
--- /dev/null
+++ b/src/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Opc.Ua.Publisher": {
+ "commandName": "Project",
+ "commandLineArgs": "myApp"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Opc.Ua.Publisher.Module/PublishedNodesCollection.cs b/src/PublishedNodesCollection.cs
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/PublishedNodesCollection.cs
rename to src/PublishedNodesCollection.cs
diff --git a/src/Opc.Ua.Publisher.Module/Publisher.Classes.cs b/src/Publisher.Classes.cs
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/Publisher.Classes.cs
rename to src/Publisher.Classes.cs
diff --git a/src/Opc.Ua.Publisher.Module/Publisher.Constants.cs b/src/Publisher.Constants.cs
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/Publisher.Constants.cs
rename to src/Publisher.Constants.cs
diff --git a/src/Opc.Ua.Publisher.Module/Publisher.DataTypes.cs b/src/Publisher.DataTypes.cs
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/Publisher.DataTypes.cs
rename to src/Publisher.DataTypes.cs
diff --git a/src/Opc.Ua.Publisher.Module/Publisher.PredefinedNodes.uanodes b/src/Publisher.PredefinedNodes.uanodes
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/Publisher.PredefinedNodes.uanodes
rename to src/Publisher.PredefinedNodes.uanodes
diff --git a/src/Opc.Ua.Publisher.Module/PublisherModel.xml b/src/PublisherModel.xml
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/PublisherModel.xml
rename to src/PublisherModel.xml
diff --git a/src/Opc.Ua.Publisher.Module/PublisherServer.cs b/src/PublisherServer.cs
similarity index 100%
rename from src/Opc.Ua.Publisher.Module/PublisherServer.cs
rename to src/PublisherServer.cs
diff --git a/src/Opc.Ua.Publisher.Module/PublisherState.cs b/src/PublisherState.cs
similarity index 71%
rename from src/Opc.Ua.Publisher.Module/PublisherState.cs
rename to src/PublisherState.cs
index c6e5635..ca58947 100644
--- a/src/Opc.Ua.Publisher.Module/PublisherState.cs
+++ b/src/PublisherState.cs
@@ -1,5 +1,6 @@
using IoTHubCredentialTools;
+using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;
using Opc.Ua;
using Opc.Ua.Client;
@@ -33,7 +34,7 @@ namespace Publisher
{
if (inputArguments[0] == null || inputArguments[1] == null)
{
- Module.Trace("PublishNodeMethod: Invalid Arguments!");
+ Program.Trace("PublishNodeMethod: Invalid Arguments!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!");
}
@@ -41,7 +42,7 @@ namespace Publisher
string uri = inputArguments[1] as string;
if (string.IsNullOrEmpty(nodeID) || string.IsNullOrEmpty(uri))
{
- Module.Trace("PublishNodeMethod: Arguments are not valid strings!");
+ Program.Trace("PublishNodeMethod: Arguments are not valid strings!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!");
}
@@ -53,20 +54,20 @@ namespace Publisher
}
catch (UriFormatException)
{
- Module.Trace("PublishNodeMethod: Invalid endpoint URL!");
+ Program.Trace("PublishNodeMethod: Invalid endpoint URL!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!");
}
// create session, if it doesn't exist already and complete asynchonourly (do to thread dependencies in the UA stack)
- if (!Module.m_endpointUrls.Contains(lookup.EndPointURL))
+ if (!Program.m_endpointUrls.Contains(lookup.EndPointURL))
{
try
{
Task.Run(() =>
{
- Module.Trace("PublishNodeMethod: Session not found, creating one for " + lookup.EndPointURL);
- Module.EndpointConnect(lookup.EndPointURL).Wait();
- Module.Trace("PublishNodeMethod: Session created.");
+ Program.Trace("PublishNodeMethod: Session not found, creating one for " + lookup.EndPointURL);
+ Program.EndpointConnect(lookup.EndPointURL).Wait();
+ Program.Trace("PublishNodeMethod: Session created.");
return DoPublish(lookup);
});
@@ -75,7 +76,7 @@ namespace Publisher
}
catch (Exception ex)
{
- Module.Trace("PublishNodeMethod: Exception: " + ex.ToString());
+ Program.Trace("PublishNodeMethod: Exception: " + ex.ToString());
return ServiceResult.Create(ex, StatusCodes.BadUnexpectedError, "Unexpected error publishing node: " + ex.Message);
}
}
@@ -95,7 +96,7 @@ namespace Publisher
{
// find the right session using our lookup
Session matchingSession = null;
- foreach (Session session in Module.m_sessions)
+ foreach (Session session in Program.m_sessions)
{
char[] trimChars = { '/', ' ' };
if (session.Endpoint.EndpointUrl.TrimEnd(trimChars).StartsWith(lookup.EndPointURL.ToString().TrimEnd(trimChars), StringComparison.OrdinalIgnoreCase))
@@ -108,10 +109,10 @@ namespace Publisher
if (matchingSession == null)
{
- Module.Trace("PublishNodeMethod: No matching session found for " + lookup.EndPointURL.ToString());
+ Program.Trace("PublishNodeMethod: No matching session found for " + lookup.EndPointURL.ToString());
return ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for published node not found!");
}
- Module.Trace("PublishNodeMethod: Session found.");
+ Program.Trace("PublishNodeMethod: Session found.");
// check if the node has already been published
@@ -119,20 +120,20 @@ namespace Publisher
{
if (item.StartNodeId == lookup.NodeID)
{
- Module.Trace("PublishNodeMethod: Node ID has already been published " + lookup.NodeID.ToString());
+ Program.Trace("PublishNodeMethod: Node ID has already been published " + lookup.NodeID.ToString());
return ServiceResult.Create(StatusCodes.BadNodeIdExists, "Node has already been published!");
}
}
// subscribe to the node
- Module.CreateMonitoredItem(lookup);
- Module.Trace("PublishNodeMethod: Monitored item created.");
+ Program.CreateMonitoredItem(lookup);
+ Program.Trace("PublishNodeMethod: Monitored item created.");
// update our data
- Module.m_nodesLookups.Add(lookup);
- if (!Module.m_endpointUrls.Contains(lookup.EndPointURL))
+ Program.m_nodesLookups.Add(lookup);
+ if (!Program.m_endpointUrls.Contains(lookup.EndPointURL))
{
- Module.m_endpointUrls.Add(lookup.EndPointURL);
+ Program.m_endpointUrls.Add(lookup.EndPointURL);
}
//serialize Program.m_nodesLookups to disk
@@ -141,14 +142,14 @@ namespace Publisher
{
publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP");
}
- File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Module.m_nodesLookups));
+ File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Program.m_nodesLookups));
- Module.Trace("PublishNodeMethod: Successful publish: " + lookup.ToString());
+ Program.Trace("PublishNodeMethod: Successful publish: " + lookup.ToString());
return ServiceResult.Good;
}
catch (Exception ex)
{
- Module.Trace("PublishNodeMethod: Exception: " + ex.ToString());
+ Program.Trace("PublishNodeMethod: Exception: " + ex.ToString());
return ServiceResult.Create(ex, StatusCodes.BadUnexpectedError, "Unexpected error publishing node: " + ex.Message);
}
}
@@ -160,7 +161,7 @@ namespace Publisher
{
if (inputArguments[0] == null || inputArguments[1] == null)
{
- Module.Trace("UnPublishNodeMethod: Invalid arguments!");
+ Program.Trace("UnPublishNodeMethod: Invalid arguments!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments!");
}
@@ -168,7 +169,7 @@ namespace Publisher
string uri = inputArguments[1] as string;
if (string.IsNullOrEmpty(nodeID) || string.IsNullOrEmpty(uri))
{
- Module.Trace("UnPublishNodeMethod: Arguments are not valid strings!");
+ Program.Trace("UnPublishNodeMethod: Arguments are not valid strings!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide all arguments as strings!");
}
@@ -180,13 +181,13 @@ namespace Publisher
}
catch (UriFormatException)
{
- Module.Trace("UnPublishNodeMethod: Invalid endpoint URL!");
+ Program.Trace("UnPublishNodeMethod: Invalid endpoint URL!");
return ServiceResult.Create(StatusCodes.BadArgumentsMissing, "Please provide a valid OPC UA endpoint URL as second argument!");
}
// find the right session using our lookup
Session matchingSession = null;
- foreach (Session session in Module.m_sessions)
+ foreach (Session session in Program.m_sessions)
{
char[] trimChars = { '/', ' ' };
if (session.Endpoint.EndpointUrl.TrimEnd(trimChars).Equals(lookup.EndPointURL.ToString().TrimEnd(trimChars), StringComparison.OrdinalIgnoreCase))
@@ -198,7 +199,7 @@ namespace Publisher
if (matchingSession == null)
{
- Module.Trace("UnPublishNodeMethod: Session for published node not found: " + lookup.EndPointURL.ToString());
+ Program.Trace("UnPublishNodeMethod: Session for published node not found: " + lookup.EndPointURL.ToString());
return ServiceResult.Create(StatusCodes.BadSessionIdInvalid, "Session for published node not found!");
}
@@ -208,11 +209,11 @@ namespace Publisher
if (item.StartNodeId == lookup.NodeID)
{
matchingSession.DefaultSubscription.RemoveItem(item);
- Module.Trace("UnPublishNodeMethod: Successful unpublish: " + lookup.NodeID.ToString());
+ Program.Trace("UnPublishNodeMethod: Successful unpublish: " + lookup.NodeID.ToString());
// update our data on success only
// we keep the session to the server, as there may be other nodes still published on it
- Module.m_nodesLookups.Remove(lookup);
+ Program.m_nodesLookups.Remove(lookup);
//serialize Program.m_nodesLookups to disk
string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json";
@@ -220,13 +221,13 @@ namespace Publisher
{
publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP");
}
- File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Module.m_nodesLookups));
+ File.WriteAllText(publishedNodesFilePath, JsonConvert.SerializeObject(Program.m_nodesLookups));
return ServiceResult.Good;
}
}
-
- Module.Trace("UnPublishNodeMethod: Monitored item for node ID not found " + lookup.NodeID.ToString());
+
+ Program.Trace("UnPublishNodeMethod: Monitored item for node ID not found " + lookup.NodeID.ToString());
return ServiceResult.Create(StatusCodes.BadNodeIdInvalid, "Monitored item for node ID not found!");
}
@@ -235,8 +236,8 @@ namespace Publisher
///
private ServiceResult GetListOfPublishedNodesMethod(ISystemContext context, MethodState method, IList