using CliFx.Attributes; using CliFx.Infrastructure; using ZB.MOM.WW.OtOpcUa.Driver.Cli.Common; namespace ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli.Commands; /// /// Read one TwinCAT symbol by path. Structure writes/reads are out of scope — fan the /// member list into individual reads if you need them. /// [Command("read", Description = "Read a single TwinCAT symbol.")] public sealed class ReadCommand : TwinCATCommandBase { [CommandOption("symbol", 's', Description = "Symbol path. Program scope: 'MAIN.bStart'. Global: 'GVL.Counter'. " + "Nested UDT member: 'Motor1.Status.Running'. Array element: 'Recipe[3]'.", IsRequired = true)] public string SymbolPath { get; init; } = default!; [CommandOption("type", 't', Description = "Bool / SInt / USInt / Int / UInt / DInt / UDInt / LInt / ULInt / Real / LReal / " + "String / WString / Time / Date / DateTime / TimeOfDay (default DInt).")] public TwinCATDataType DataType { get; init; } = TwinCATDataType.DInt; public override async ValueTask ExecuteAsync(IConsole console) { ConfigureLogging(); var ct = console.RegisterCancellationHandler(); var tagName = SynthesiseTagName(SymbolPath, DataType); var tag = new TwinCATTagDefinition( Name: tagName, DeviceHostAddress: Gateway, SymbolPath: SymbolPath, DataType: DataType, Writable: false); var options = BuildOptions([tag]); await using var driver = new TwinCATDriver(options, DriverInstanceId); try { await driver.InitializeAsync("{}", ct); var snapshot = await driver.ReadAsync([tagName], ct); await console.Output.WriteLineAsync(SnapshotFormatter.Format(SymbolPath, snapshot[0])); } finally { await driver.ShutdownAsync(CancellationToken.None); } } internal static string SynthesiseTagName(string symbolPath, TwinCATDataType type) => $"{symbolPath}:{type}"; }