Improve formating

This commit is contained in:
Peter Butzhammer
2024-04-28 20:47:20 +02:00
parent e358c03db0
commit cd70cc4714
2 changed files with 96 additions and 90 deletions

View File

@@ -4,4 +4,5 @@ public static class CustomStyles
{ {
public static Style Error { get; } = new Style(foreground: Color.Red); public static Style Error { get; } = new Style(foreground: Color.Red);
public static Style Note { get; } = new(foreground: Color.DarkSlateGray1); public static Style Note { get; } = new(foreground: Color.DarkSlateGray1);
public static Style? Hex { get; } = new(foreground: Color.Blue);
} }

View File

@@ -1,4 +1,5 @@
using System.ComponentModel; using System.Collections;
using System.ComponentModel;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Threading.Tasks; using System.Reactive.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -13,7 +14,7 @@ internal sealed class ReadPlcCommand : AsyncCommand<ReadPlcCommand.Settings>
{ {
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings) public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
{ {
var token = (CancellationToken) (context.Data ?? CancellationToken.None); var token = (CancellationToken)(context.Data ?? CancellationToken.None);
try try
{ {
@@ -28,114 +29,118 @@ internal sealed class ReadPlcCommand : AsyncCommand<ReadPlcCommand.Settings>
private static IRenderable FormatCellData(VariableRecord record) private static IRenderable FormatCellData(VariableRecord record)
{ {
if (record.Value is IRenderable renderable) return record.Value switch
return renderable;
if (record.Value is Exception ex)
return new Text(ex.Message, CustomStyles.Error);
if (record.Value is byte[] byteArray)
{ {
var text = string.Join(" ", byteArray.Select(b => $"0x{b:X2}")); IRenderable renderable => renderable,
return new Text(text); Exception ex => new Text(ex.Message, CustomStyles.Error),
} byte[] byteArray => new Text(string.Join(" ", byteArray.Select(b => $"0x{b:X2}")), CustomStyles.Hex),
byte => FormatNo(),
short =>FormatNo(),
ushort =>FormatNo(),
int =>FormatNo(),
uint =>FormatNo(),
long =>FormatNo(),
ulong =>FormatNo(),
return new Text(record.Value.ToString() ?? ""); _ => new Text(record.Value.ToString() ?? "")
};
Markup FormatNo() => new($"[blue]0x{record.Value:X2}[/] {record.Value}");
} }
private static async Task RunProgram(Settings settings, CancellationToken token) private static async Task RunProgram(Settings settings, CancellationToken token)
{ {
AnsiConsole.MarkupLine($"Connecting to plc [green]{settings.PlcIp}[/], CPU [green]{settings.CpuMpiAddress}[/], rack [green]{settings.RackNumber}[/]. "); AnsiConsole.MarkupLine($"Connecting to plc [green]{settings.PlcIp}[/], CPU [green]{settings.CpuMpiAddress}[/], rack [green]{settings.RackNumber}[/]. ");
AnsiConsole.MarkupLine("[gray]Press Ctrl + C to cancel.[/]"); AnsiConsole.MarkupLine("[gray]Press Ctrl + C to cancel.[/]");
using var plc = new Sharp7Plc(settings.PlcIp, settings.RackNumber, settings.CpuMpiAddress); using var plc = new Sharp7Plc(settings.PlcIp, settings.RackNumber, settings.CpuMpiAddress);
await plc.TriggerConnection(token); await plc.TriggerConnection(token);
// Connect // Connect
await AnsiConsole.Status() await AnsiConsole.Status()
.Spinner(Spinner.Known.BouncingBar) .Spinner(Spinner.Known.BouncingBar)
.StartAsync("Connecting...", async ctx => .StartAsync("Connecting...", async ctx =>
{
var lastState = ConnectionState.Initial;
ctx.Status(lastState.ToString());
while (!token.IsCancellationRequested)
{
var state = await plc.ConnectionState.FirstAsync(s => s != lastState).ToTask(token);
ctx.Status(state.ToString());
if (state == ConnectionState.Connected)
return;
}
});
token.ThrowIfCancellationRequested();
using var variableContainer = VariableContainer.Initialize(plc, settings.Variables);
// Create a table
var table = new Table
{ {
Border = TableBorder.Rounded, var lastState = ConnectionState.Initial;
BorderStyle = new Style(foreground: Color.DarkGreen) ctx.Status(lastState.ToString());
};
table.AddColumn("Variable"); while (!token.IsCancellationRequested)
table.AddColumn("Value");
foreach (var record in variableContainer.VariableRecords)
table.AddRow(record.Address, "[gray]init[/]");
await AnsiConsole.Live(table)
.StartAsync(async ctx =>
{ {
while (!token.IsCancellationRequested) var state = await plc.ConnectionState.FirstAsync(s => s != lastState).ToTask(token);
{ ctx.Status(state.ToString());
foreach (var record in variableContainer.VariableRecords)
table.Rows.Update(
record.RowIdx, 1,
FormatCellData(record)
);
ctx.Refresh(); if (state == ConnectionState.Connected)
return;
}
});
await Task.Delay(100, token); token.ThrowIfCancellationRequested();
}
});
}
[NoReorder]
public sealed class Settings : CommandSettings using var variableContainer = VariableContainer.Initialize(plc, settings.Variables);
// Create a table
var table = new Table
{ {
[Description("IP address of S7")] Border = TableBorder.Rounded,
[CommandArgument(0, "<IP address>")] BorderStyle = new Style(foreground: Color.DarkGreen)
public required string PlcIp { get; init; } };
[CommandArgument(1, "[variables]")] table.AddColumn("Variable");
[Description("Variables to read from S7, like Db200.Int4.\r\nFor format description see https://github.com/evopro-ag/Sharp7Reactive.")] table.AddColumn("Value");
public required string[] Variables { get; init; }
[CommandOption("-c|--cpu")] foreach (var record in variableContainer.VariableRecords)
[Description("CPU MPI address of S7 instance.\r\nSee https://github.com/fbarresi/Sharp7/wiki/Connection#rack-and-slot.\r\n")] table.AddRow(record.Address, "[gray]init[/]");
[DefaultValue(0)]
public int CpuMpiAddress { get; init; }
[CommandOption("-r|--rack")] await AnsiConsole.Live(table)
[Description("Rack number of S7 instance.\r\nSee https://github.com/fbarresi/Sharp7/wiki/Connection#rack-and-slot.\r\n")] .StartAsync(async ctx =>
[DefaultValue(0)]
public int RackNumber { get; init; }
public override ValidationResult Validate()
{ {
if (!StringHelper.IsValidIp4(PlcIp)) while (!token.IsCancellationRequested)
return ValidationResult.Error($"\"{PlcIp}\" is not a valid IP V4 address"); {
foreach (var record in variableContainer.VariableRecords)
table.Rows.Update(
record.RowIdx, 1,
FormatCellData(record)
);
if (Variables == null || Variables.Length == 0) ctx.Refresh();
return ValidationResult.Error("Please supply at least one variable to read");
return ValidationResult.Success(); await Task.Delay(100, token);
} }
});
}
[NoReorder]
public sealed class Settings : CommandSettings
{
[Description("IP address of S7")]
[CommandArgument(0, "<IP address>")]
public required string PlcIp { get; init; }
[CommandArgument(1, "[variables]")]
[Description("Variables to read from S7, like Db200.Int4.\r\nFor format description see https://github.com/evopro-ag/Sharp7Reactive.")]
public required string[] Variables { get; init; }
[CommandOption("-c|--cpu")]
[Description("CPU MPI address of S7 instance.\r\nSee https://github.com/fbarresi/Sharp7/wiki/Connection#rack-and-slot.\r\n")]
[DefaultValue(0)]
public int CpuMpiAddress { get; init; }
[CommandOption("-r|--rack")]
[Description("Rack number of S7 instance.\r\nSee https://github.com/fbarresi/Sharp7/wiki/Connection#rack-and-slot.\r\n")]
[DefaultValue(0)]
public int RackNumber { get; init; }
public override ValidationResult Validate()
{
if (!StringHelper.IsValidIp4(PlcIp))
return ValidationResult.Error($"\"{PlcIp}\" is not a valid IP V4 address");
if (Variables == null || Variables.Length == 0)
return ValidationResult.Error("Please supply at least one variable to read");
return ValidationResult.Success();
} }
} }
}