/// <summary> /// Run server until exit /// </summary> private static async Task RunServerAsync(IEnumerable <int> ports) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) { var tcs = new TaskCompletionSource <bool>(); AssemblyLoadContext.Default.Unloading += _ => tcs.TrySetResult(true); using (var server = new ServerConsoleHost(new ServerFactory(logger.Logger), logger.Logger) { AutoAccept = true }) { await server.StartAsync(ports); #if DEBUG if (!Console.IsInputRedirected) { Console.WriteLine("Press any key to exit..."); Console.TreatControlCAsInput = true; await Task.WhenAny(tcs.Task, Task.Run(() => Console.ReadKey())); return; } #endif await tcs.Task; logger.Logger.Information("Exiting."); } } }
/// <summary> /// Test discovery /// </summary> private static async Task TestOpcUaDiscoveryServiceAsync(string addressRanges, bool stress) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig())) using (var scanner = new DiscoveryServices(client, new ConsoleEmitter(), logger.Logger)) { var rand = new Random(); while (true) { var configuration = new DiscoveryConfigModel { IdleTimeBetweenScans = TimeSpan.FromMilliseconds(1), AddressRangesToScan = addressRanges }; await scanner.ConfigureAsync(DiscoveryMode.Scan, configuration); await scanner.ScanAsync(); await Task.Delay(!stress?TimeSpan.FromMinutes(10) : TimeSpan.FromMilliseconds(rand.Next(0, 120000))); logger.Logger.Information("Stopping discovery!"); await scanner.ConfigureAsync(DiscoveryMode.Off, null); await scanner.ScanAsync(); if (!stress) { break; } } } }
/// <summary> /// Test model archiver /// </summary> private static async Task TestOpcUaModelArchiveAsync(EndpointModel endpoint) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) { var storage = new ZipArchiveStorage(); var fileName = "tmp.zip"; using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig())) using (var server = new ServerWrapper(endpoint, logger)) { var sw = Stopwatch.StartNew(); using (var archive = await storage.OpenAsync(fileName, FileMode.Create, FileAccess.Write)) using (var archiver = new AddressSpaceArchiver(client, endpoint, archive, logger.Logger)) { await archiver.ArchiveAsync(CancellationToken.None); } var elapsed = sw.Elapsed; using (var file = File.Open(fileName, FileMode.OpenOrCreate)) { Console.WriteLine($"Encode as to {fileName} took " + $"{elapsed}, and produced {file.Length} bytes."); } } } }
/// <summary> /// Test model browse encoder to file /// </summary> private static async Task TestOpcUaModelExportToFileAsync(EndpointModel endpoint) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) { // Run both encodings twice to prime server and get realistic timings the // second time around var runs = new Dictionary <string, string> { ["json1.zip"] = ContentMimeType.UaJson, // ["bin1.zip"] = ContentEncodings.MimeTypeUaBinary, ["json2.zip"] = ContentMimeType.UaJson, // ["bin2.zip"] = ContentEncodings.MimeTypeUaBinary, ["json1.gzip"] = ContentMimeType.UaJson, // ["bin1.gzip"] = ContentEncodings.MimeTypeUaBinary, ["json2.gzip"] = ContentMimeType.UaJson, // ["bin2.gzip"] = ContentEncodings.MimeTypeUaBinary }; using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig())) using (var server = new ServerWrapper(endpoint, logger)) { foreach (var run in runs) { var zip = Path.GetExtension(run.Key) == ".zip"; Console.WriteLine($"Writing {run.Key}..."); var sw = Stopwatch.StartNew(); using (var stream = new FileStream(run.Key, FileMode.Create)) { using (var zipped = zip ? new DeflateStream(stream, CompressionLevel.Optimal) : (Stream) new GZipStream(stream, CompressionLevel.Optimal)) using (var browser = new BrowseStreamEncoder(client, endpoint, zipped, run.Value, null, logger.Logger, null)) { await browser.EncodeAsync(CancellationToken.None); } } var elapsed = sw.Elapsed; using (var file = File.Open(run.Key, FileMode.OpenOrCreate)) { Console.WriteLine($"Encode as {run.Value} to {run.Key} took " + $"{elapsed}, and produced {file.Length} bytes."); } } } } }
/// <summary> /// Test model export and import /// </summary> private static async Task TestOpcUaModelWriterAsync(EndpointModel endpoint) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) { var filename = "model.zip"; using (var server = new ServerWrapper(endpoint, logger)) { using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig())) { Console.WriteLine($"Reading into {filename}..."); using (var stream = new FileStream(filename, FileMode.Create)) { using (var zipped = new DeflateStream(stream, CompressionLevel.Optimal)) using (var browser = new BrowseStreamEncoder(client, endpoint, zipped, ContentMimeType.UaJson, null, logger.Logger, null)) { await browser.EncodeAsync(CancellationToken.None); } } } } GC.Collect(); GC.WaitForPendingFinalizers(); var serializer = new NewtonSoftJsonSerializer(); IDatabaseServer database = new MemoryDatabase(logger.Logger, serializer); for (var i = 0; ; i++) { Console.WriteLine($"{i}: Writing from {filename}..."); var sw = Stopwatch.StartNew(); using (var file = File.Open(filename, FileMode.OpenOrCreate)) { using (var unzipped = new DeflateStream(file, CompressionMode.Decompress)) { // TODO // var writer = new SourceStreamImporter(new ItemContainerFactory(database), // new VariantEncoderFactory(), logger.Logger); // await writer.ImportAsync(unzipped, Path.GetFullPath(filename + i), // ContentMimeType.UaJson, null, CancellationToken.None); } } var elapsed = sw.Elapsed; Console.WriteLine($"{i}: Writing took {elapsed}."); } } }
/// <summary> /// Test client /// </summary> private static async Task TestOpcUaServerClientAsync(EndpointModel endpoint) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig())) using (var server = new ServerWrapper(endpoint, logger)) { await client.ExecuteServiceAsync(endpoint, null, session => { Console.WriteLine("Browse the OPC UA server namespace."); var w = Stopwatch.StartNew(); var stack = new Stack <Tuple <string, ReferenceDescription> >(); session.Browse(null, null, ObjectIds.RootFolder, 0u, Opc.Ua.BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, 0, out var continuationPoint, out var references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); references.Reverse(); foreach (var rd in references) { stack.Push(Tuple.Create("", rd)); } while (stack.Count > 0) { var browsed = stack.Pop(); session.Browse(null, null, ExpandedNodeId.ToNodeId(browsed.Item2.NodeId, session.NamespaceUris), 0u, Opc.Ua.BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, 0, out continuationPoint, out references); references.Reverse(); foreach (var rd in references) { stack.Push(Tuple.Create(browsed.Item1 + " ", rd)); } Console.WriteLine($"{browsed.Item1}{(references.Count == 0 ? "-" : "+")} " + $"{browsed.Item2.DisplayName}, {browsed.Item2.BrowseName}, {browsed.Item2.NodeClass}"); } Console.WriteLine($" .... took {w.ElapsedMilliseconds} ms..."); return(Task.FromResult(true)); });
/// <summary> /// Test model browse encoder /// </summary> private static async Task TestOpcUaModelExportServiceAsync(EndpointModel endpoint) { using (var logger = StackLogger.Create(ConsoleLogger.Create())) using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig())) using (var server = new ServerWrapper(endpoint, logger)) using (var stream = Console.OpenStandardOutput()) using (var writer = new StreamWriter(stream)) using (var json = new JsonTextWriter(writer) { AutoCompleteOnClose = true, Formatting = Formatting.Indented, DateFormatHandling = DateFormatHandling.IsoDateFormat }) using (var encoder = new JsonEncoderEx(json, null, JsonEncoderEx.JsonEncoding.Array) { IgnoreDefaultValues = true, UseAdvancedEncoding = true }) using (var browser = new BrowseStreamEncoder(client, endpoint, encoder, null, logger.Logger, null)) { await browser.EncodeAsync(CancellationToken.None); } }