Improve formating
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user