in src/Azure.IIoT.OpcUa.Publisher.Module/cli/Program.cs [522:668]
private static async Task DumpMessagesAsync(string messageMode, string? publishProfile,
string? publishInitProfile, ILoggerFactory loggerFactory, TimeSpan duration,
uint scaleunits, int errorRate, string? dumpMessagesOutput, string[] args, CancellationToken ct)
{
try
{
// Dump one message encoding at a time
var rootFolder = Path.Combine(dumpMessagesOutput ?? ".", "dump");
foreach (var messageProfile in MessagingProfile.Supported)
{
if (messageProfile.MessageEncoding.HasFlag(MessageEncoding.IsGzipCompressed))
{
// No need to dump gzip
continue;
}
if (messageMode != "all" &&
!messageProfile.MessagingMode.ToString().Equals(
messageMode, StringComparison.OrdinalIgnoreCase) &&
!messageProfile.MessageEncoding.ToString().Equals(
messageMode, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"Skipping {messageProfile}...");
continue;
}
var outputFolder = Path.Combine(rootFolder, messageProfile.MessagingMode.ToString(),
messageProfile.MessageEncoding.ToString());
if (Directory.Exists(outputFolder) && Directory.EnumerateFiles(outputFolder).Any())
{
continue;
}
Directory.CreateDirectory(outputFolder);
await DumpPublishingProfiles(outputFolder, messageProfile, publishProfile,
publishInitProfile).ConfigureAwait(false);
}
}
catch (OperationCanceledException) { }
// Dump message profile for all publishing profiles
async Task DumpPublishingProfiles(string rootFolder, MessagingProfile messageProfile,
string? profile, string? publishInitProfile)
{
if (publishInitProfile != null)
{
var outputFolder = Path.Combine(rootFolder, publishInitProfile);
await DumpMessagesForDuration(outputFolder, "Empty", messageProfile,
publishInitProfile, args).ConfigureAwait(false);
return;
}
foreach (var publishProfile in Directory.EnumerateFiles("./Profiles", "*.json"))
{
var publishProfileName = Path.GetFileNameWithoutExtension(publishProfile);
if (profile == null &&
(publishProfileName.StartsWith("Unified", StringComparison.OrdinalIgnoreCase) ||
publishProfileName.StartsWith("Empty", StringComparison.OrdinalIgnoreCase) ||
publishProfileName.StartsWith("NoNodes", StringComparison.OrdinalIgnoreCase)))
{
continue;
}
if (profile != null && !publishProfileName.Equals(profile, StringComparison.OrdinalIgnoreCase))
{
continue;
}
var logger = loggerFactory.CreateLogger(publishProfileName);
var outputFolder = Path.Combine(rootFolder, publishProfileName);
if (Directory.Exists(outputFolder) && Directory.EnumerateFiles(outputFolder).Any())
{
continue;
}
Directory.CreateDirectory(outputFolder);
await DumpMessagesForDuration(outputFolder, publishProfile, messageProfile,
null, args).ConfigureAwait(false);
}
}
async Task DumpMessagesForDuration(string outputFolder, string publishProfile,
MessagingProfile messageProfile, string? publishInitProfile, string[] args)
{
using var runtime = new CancellationTokenSource(duration);
try
{
using var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(
ct, runtime.Token);
var name = Path.GetFileNameWithoutExtension(publishProfile);
Console.Title = $"Dumping {messageProfile} for {name}...";
await RunAsync(loggerFactory, publishProfile, messageProfile,
outputFolder, scaleunits, errorRate, args, publishInitProfile, linkedToken.Token).ConfigureAwait(false);
}
catch (OperationCanceledException) when (runtime.IsCancellationRequested) { }
}
static async Task RunAsync(ILoggerFactory loggerFactory, string publishProfile,
MessagingProfile messageProfile, string outputFolder, uint scaleunits, int errorRate, string[] args,
string? publishInitProfile, CancellationToken ct)
{
// Start test server
using var server = new ServerWrapper(scaleunits, errorRate, loggerFactory, null);
var name = Path.GetFileNameWithoutExtension(publishProfile);
var endpointUrl = $"opc.tcp://localhost:{server.Port}/UA/SampleServer";
var publishedNodesFilePath = await LoadPnJsonAsync(server, name, endpointUrl,
ct).ConfigureAwait(false);
if (publishedNodesFilePath == null)
{
return;
}
var publishInitFile = await LoadInitFileAsync(name, endpointUrl, ct).ConfigureAwait(false);
//
// Check whether the profile overrides the messaging mode, then set it to the desired
// one regardless of whether it will work or not
//
var check = await File.ReadAllTextAsync(publishedNodesFilePath, ct).ConfigureAwait(false);
if (check.Contains("\"MessagingMode\":", StringComparison.InvariantCulture) &&
!check.Contains($"\"MessagingMode\": \"{messageProfile.MessagingMode}\"",
StringComparison.InvariantCulture))
{
check = ReplacePropertyValue(check, "MessagingMode", messageProfile.MessagingMode.ToString());
await File.WriteAllTextAsync(publishedNodesFilePath, check, ct).ConfigureAwait(false);
}
var arguments = new HashSet<string>
{
"-c",
"--ps",
$"--pf={publishedNodesFilePath}",
$"--me={messageProfile.MessageEncoding}",
$"--mm={messageProfile.MessagingMode}",
$"--ttt={name}/{{WriterGroup}}",
$"--mdt={name}/{{WriterGroup}}",
"-t=FileSystem",
$"-o={outputFolder}",
"--aa"
};
if (publishInitFile != null)
{
arguments.Add($"--pi={publishInitFile}");
}
args.ForEach(a => arguments.Add(a));
await Publisher.Module.Program.RunAsync([.. arguments], ct).ConfigureAwait(false);
}
}