|
|
|
@@ -63,33 +63,54 @@ public sealed class WriteCommand : TwinCATTagCommandBase
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
await driver.ShutdownAsync(CancellationToken.None);
|
|
|
|
|
FlushLogging();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Parse <c>--value</c> per <see cref="TwinCATDataType"/>, invariant culture.</summary>
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parse <c>--value</c> per <see cref="TwinCATDataType"/>, invariant culture. Wraps
|
|
|
|
|
/// <see cref="FormatException"/> and <see cref="OverflowException"/> in a
|
|
|
|
|
/// <see cref="CliFx.Exceptions.CommandException"/> so the operator sees a clean one-line
|
|
|
|
|
/// error instead of a raw stack trace (Driver.TwinCAT.Cli-008).
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="raw">The raw string value to parse.</param>
|
|
|
|
|
/// <param name="type">The target TwinCAT data type.</param>
|
|
|
|
|
internal static object ParseValue(string raw, TwinCATDataType type) => type switch
|
|
|
|
|
internal static object ParseValue(string raw, TwinCATDataType type)
|
|
|
|
|
{
|
|
|
|
|
TwinCATDataType.Bool => ParseBool(raw),
|
|
|
|
|
TwinCATDataType.SInt => sbyte.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.USInt => byte.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.Int => short.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.UInt => ushort.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.DInt => int.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.UDInt => uint.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.LInt => long.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.ULInt => ulong.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.Real => float.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.LReal => double.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.String or TwinCATDataType.WString => raw,
|
|
|
|
|
// IEC 61131-3 time/date types are stored as UDINT on the wire — accept a numeric raw
|
|
|
|
|
// value + let the caller handle the encoding semantics.
|
|
|
|
|
TwinCATDataType.Time or TwinCATDataType.Date
|
|
|
|
|
or TwinCATDataType.DateTime or TwinCATDataType.TimeOfDay
|
|
|
|
|
=> uint.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
_ => throw new CliFx.Exceptions.CommandException($"Unsupported DataType '{type}' for write."),
|
|
|
|
|
};
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return type switch
|
|
|
|
|
{
|
|
|
|
|
TwinCATDataType.Bool => ParseBool(raw),
|
|
|
|
|
TwinCATDataType.SInt => sbyte.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.USInt => byte.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.Int => short.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.UInt => ushort.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.DInt => int.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.UDInt => uint.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.LInt => long.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.ULInt => ulong.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.Real => float.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.LReal => double.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
TwinCATDataType.String or TwinCATDataType.WString => raw,
|
|
|
|
|
// IEC 61131-3 time/date types are stored as UDINT on the wire — accept a numeric raw
|
|
|
|
|
// value + let the caller handle the encoding semantics.
|
|
|
|
|
TwinCATDataType.Time or TwinCATDataType.Date
|
|
|
|
|
or TwinCATDataType.DateTime or TwinCATDataType.TimeOfDay
|
|
|
|
|
=> uint.Parse(raw, CultureInfo.InvariantCulture),
|
|
|
|
|
_ => throw new CliFx.Exceptions.CommandException($"Unsupported DataType '{type}' for write."),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
catch (CliFx.Exceptions.CommandException)
|
|
|
|
|
{
|
|
|
|
|
throw; // already a clean user-facing error (Bool parse, Structure, unsupported type)
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex) when (ex is FormatException or OverflowException)
|
|
|
|
|
{
|
|
|
|
|
throw new CliFx.Exceptions.CommandException(
|
|
|
|
|
$"Cannot parse '{raw}' as {type}: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool ParseBool(string raw) => raw.Trim().ToLowerInvariant() switch
|
|
|
|
|
{
|
|
|
|
|