public static void Main(string[] args) { try { if ((args.Length == 0) || string.IsNullOrEmpty(args[0]) || args[0].Equals("localhost", StringComparison.OrdinalIgnoreCase)) { m_applicationName = Utils.GetHostName(); } else { m_applicationName = args[0]; } Trace("Publisher is starting up..."); ModuleConfiguration moduleConfiguration = new ModuleConfiguration(m_applicationName); m_configuration = moduleConfiguration.Configuration; m_configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); // start our server interface try { Trace("Starting server on endpoint " + m_configuration.ServerConfiguration.BaseAddresses[0].ToString() + "..."); m_server.Start(m_configuration); Trace("Server started."); } catch (Exception ex) { Trace("Starting server failed with: " + ex.Message); } // check if we also received an owner connection string string ownerConnectionString = string.Empty; 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."); } // get a list of persisted endpoint URLs and create a session for each. try { // check if we have an env variable specifying the published nodes path, otherwise use current directory string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json"; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_PNFP"))) { publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP"); } Trace("Attemping to load nodes file from: " + publishedNodesFilePath); m_nodesLookups = JsonConvert.DeserializeObject <PublishedNodesCollection>(File.ReadAllText(publishedNodesFilePath)); Trace("Loaded " + m_nodesLookups.Count.ToString() + " nodes."); } catch (Exception ex) { Trace("Nodes file loading failed with: " + ex.Message); } foreach (NodeLookup nodeLookup in m_nodesLookups) { if (!m_endpointUrls.Contains(nodeLookup.EndPointURL)) { m_endpointUrls.Add(nodeLookup.EndPointURL); } } // connect to the other servers Trace("Attemping to connect to servers..."); try { List <Task> connectionAttempts = new List <Task>(); foreach (Uri endpointUrl in m_endpointUrls) { Trace("Connecting to server: " + endpointUrl); connectionAttempts.Add(EndpointConnect(endpointUrl)); } // Wait for all sessions to be connected Task.WaitAll(connectionAttempts.ToArray()); } catch (Exception ex) { Trace("Exception: " + ex.ToString() + "\r\n" + ex.InnerException != null ? ex.InnerException.ToString() : null); } // subscribe to preconfigured nodes Trace("Attemping to subscribe to published nodes..."); if (m_nodesLookups != null) { foreach (NodeLookup nodeLookup in m_nodesLookups) { try { CreateMonitoredItem(nodeLookup); } catch (Exception ex) { Trace("Unexpected error publishing node: " + ex.Message + "\r\nIgnoring node: " + nodeLookup.EndPointURL.AbsoluteUri + ", " + nodeLookup.NodeID.ToString()); } } } Task dequeueAndSendTask = null; var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; Trace("Creating task to send OPC UA messages in batches to IoT Hub..."); try { dequeueAndSendTask = Task.Run(() => DeQueueMessagesAsync(token), token); } catch (Exception ex) { Trace("Exception: " + ex.ToString()); } Trace("Publisher is running. Press enter to quit."); Console.ReadLine(); foreach (Session session in m_sessions) { session.Close(); } //Send cancellation token and wait for last IoT Hub message to be sent. try { tokenSource.Cancel(); dequeueAndSendTask.Wait(); } catch (Exception ex) { Trace("Exception: " + ex.ToString()); } if (m_deviceClient != null) { m_deviceClient.CloseAsync().Wait(); } } catch (Exception e) { Trace(e, "Unhandled exception in Publisher, exiting!"); } }
/// <summary> /// Create module, throws if configuration is bad /// </summary> public void Create(Broker broker, byte[] configuration) { Trace("Opc.Ua.Publisher.Module: Creating..."); m_broker = broker; string configString = Encoding.UTF8.GetString(configuration); // Deserialize from configuration string ModuleConfiguration moduleConfiguration = null; try { moduleConfiguration = JsonConvert.DeserializeObject <ModuleConfiguration>(configString); } catch (Exception ex) { Trace("Opc.Ua.Publisher.Module: Module config string " + configString + " could not be deserialized: " + ex.Message); throw; } m_configuration = moduleConfiguration.Configuration; m_configuration.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); // update log configuration, if available if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_LOGP"))) { m_configuration.TraceConfiguration.OutputFilePath = Environment.GetEnvironmentVariable("_GW_LOGP"); m_configuration.TraceConfiguration.ApplySettings(); } // get a list of persisted endpoint URLs and create a session for each. try { // check if we have an env variable specifying the published nodes path, otherwise use current directory string publishedNodesFilePath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "publishednodes.json"; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_GW_PNFP"))) { publishedNodesFilePath = Environment.GetEnvironmentVariable("_GW_PNFP"); } Trace("Opc.Ua.Publisher.Module: Attemping to load nodes file from: " + publishedNodesFilePath); m_nodesLookups = JsonConvert.DeserializeObject <PublishedNodesCollection>(File.ReadAllText(publishedNodesFilePath)); Trace("Opc.Ua.Publisher.Module: Loaded " + m_nodesLookups.Count.ToString() + " nodes."); } catch (Exception ex) { Trace("Opc.Ua.Publisher.Module: Nodes file loading failed with: " + ex.Message); } foreach (NodeLookup nodeLookup in m_nodesLookups) { if (!m_endpointUrls.Contains(nodeLookup.EndPointURL)) { m_endpointUrls.Add(nodeLookup.EndPointURL); } } // start the server try { Trace("Opc.Ua.Publisher.Module: Starting server on endpoint " + m_configuration.ServerConfiguration.BaseAddresses[0].ToString() + "..."); m_server.Start(m_configuration); Trace("Opc.Ua.Publisher.Module: Server started."); } catch (Exception ex) { Trace("Opc.Ua.Publisher.Module: 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..."); try { List <Task> connectionAttempts = new List <Task>(); foreach (Uri endpointUrl in m_endpointUrls) { Trace("Opc.Ua.Publisher.Module: Connecting to server: " + endpointUrl); connectionAttempts.Add(EndpointConnect(endpointUrl)); } // Wait for all sessions to be connected Task.WaitAll(connectionAttempts.ToArray()); } catch (Exception ex) { Trace("Opc.Ua.Publisher.Module: Exception: " + ex.ToString() + "\r\n" + ex.InnerException != null ? ex.InnerException.ToString() : null); } Trace("Opc.Ua.Publisher.Module: Created."); }