From bc619259b87937d0f2d237dd98db3d83f0341815 Mon Sep 17 00:00:00 2001 From: Peter Butzhammer Date: Fri, 10 May 2024 22:05:54 +0200 Subject: [PATCH] Extend in-game docu --- Sharp7.Monitor/CustomHelpProvider.cs | 79 +++++++++++++++++++ Sharp7.Monitor/CustomStyles.cs | 2 +- Sharp7.Monitor/Program.cs | 14 +++- Sharp7.Monitor/Properties/launchSettings.json | 9 ++- Sharp7.Monitor/ReadPlcCommand.cs | 8 +- Sharp7.Monitor/VariableRecord.cs | 4 +- 6 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 Sharp7.Monitor/CustomHelpProvider.cs diff --git a/Sharp7.Monitor/CustomHelpProvider.cs b/Sharp7.Monitor/CustomHelpProvider.cs new file mode 100644 index 0000000..9acb9ac --- /dev/null +++ b/Sharp7.Monitor/CustomHelpProvider.cs @@ -0,0 +1,79 @@ +using Spectre.Console; +using Spectre.Console.Cli; +using Spectre.Console.Cli.Help; +using Spectre.Console.Rendering; + +namespace Sharp7.Monitor; + +internal class CustomHelpProvider(ICommandAppSettings settings) : HelpProvider(settings) +{ + private readonly ICommandAppSettings settings = settings; + + public override IEnumerable GetFooter(ICommandModel model, ICommandInfo? command) + { + var helpStyles = settings.HelpProviderStyles?.Options; + + var variableGrid = GetVariableExamples(helpStyles); + + return + [ + .. base.GetFooter(model, command), + + new Text("VARIABLE EXAMPLES:", helpStyles?.Header ?? Style.Plain), Text.NewLine, + new Text("For a detailed format description see https://github.com/evopro-ag/Sharp7Reactive."), Text.NewLine, + Text.NewLine, + variableGrid, + Text.NewLine + ]; + } + + public override IEnumerable GetOptions(ICommandModel model, ICommandInfo? command) => + [ + ..base.GetOptions(model, command), + Text.NewLine, + new Text("You can find details on rack and slot at https://github.com/fbarresi/Sharp7/wiki/Connection#rack-and-slot."), Text.NewLine, + new Text("If you are using S7 1200 or 1500, you must explicitly allow RFC1006. See https://github.com/fbarresi/Sharp7#s7-12001500-notes."), Text.NewLine, + Text.NewLine + ]; + + private static IRenderable GetVariableExamples(OptionStyle? helpStyles) + { + IReadOnlyList variableTypes = + [ + new VariableType("bit", "single bit as boolean", "[grey]db3[/].[lightgoldenrod2_1]bit[/][grey]10[/].2"), + new VariableType("byte", "single byte", "[grey]db3[/].[lightgoldenrod2_1]byte[/][grey]10[/]"), + new VariableType("", "byte array", "[grey]db3[/].[lightgoldenrod2_1]byte[/][grey]10[/].5"), + new VariableType("int", "16 bit signed integer", "[grey]db3[/].[lightgoldenrod2_1]int[/][grey]10[/]"), + new VariableType("uint", "16 bit unsigned integer", "[grey]db3[/].[lightgoldenrod2_1]uint[/][grey]10[/]"), + new VariableType("dint", "32 bit signed integer", "[grey]db3[/].[lightgoldenrod2_1]dint[/][grey]10[/]"), + new VariableType("udint", "32 bit unsigned integer", "[grey]db3[/].[lightgoldenrod2_1]udint[/][grey]10[/]"), + new VariableType("lint", "64 bit signed integer", "[grey]db3[/].[lightgoldenrod2_1]lint[/][grey]10[/]"), + new VariableType("ulint", "64 bit unsigned integer", "[grey]db3[/].[lightgoldenrod2_1]ulint[/][grey]10[/]"), + new VariableType("real", "32 bit float", "[grey]db3[/].[lightgoldenrod2_1]real[/][grey]10[/]"), + new VariableType("lreal", "64 bit float", "[grey]db3[/].[lightgoldenrod2_1]lreal[/][grey]10[/]"), + new VariableType("string", "ASCII text string", "[grey]db3[/].[lightgoldenrod2_1]string[/][grey]10[/].16"), + new VariableType("wstring", "UTF-16 text string", "[grey]db3[/].[lightgoldenrod2_1]wstring[/][grey]10[/].16"), + ]; + + var grid = new Grid(); + grid.AddColumn(new GridColumn {Padding = new Padding(4, 4), NoWrap = true}); + grid.AddColumn(new GridColumn {Padding = new Padding(0, 0, 4, 0)}); + grid.AddColumn(new GridColumn {Padding = new Padding(0)}); + + grid.AddRow( + new Text("Identifier", helpStyles?.DefaultValueHeader ?? Style.Plain), + new Text("Description", helpStyles?.DefaultValueHeader ?? Style.Plain), + new Text("Example", helpStyles?.DefaultValueHeader ?? Style.Plain) + ); + + foreach (var variableType in variableTypes) + grid.AddRow( + new Text(variableType.Identifier), + new Text(variableType.Description), + new Markup(variableType.Example) + ); + return grid; + } + + internal record VariableType(string Identifier, string Description, string Example); +} diff --git a/Sharp7.Monitor/CustomStyles.cs b/Sharp7.Monitor/CustomStyles.cs index ba0a184..f1c0f7a 100644 --- a/Sharp7.Monitor/CustomStyles.cs +++ b/Sharp7.Monitor/CustomStyles.cs @@ -7,7 +7,7 @@ public static class CustomStyles public static Style Default { get; } = new(background:Color.Black); public static Style Error { get; } = Default.Foreground(Color.Red); - public static Style Hex { get; } = Default.Foreground(Color.Blue); + public static Style Hex { get; } = Default.Foreground(Color.LightGoldenrod2_1); public static Style Note { get; } = Default.Foreground(Color.DarkSlateGray1); public static Style TableBorder { get; } = Default.Foreground(Color.DarkGreen); } diff --git a/Sharp7.Monitor/Program.cs b/Sharp7.Monitor/Program.cs index 85bff90..744a53a 100644 --- a/Sharp7.Monitor/Program.cs +++ b/Sharp7.Monitor/Program.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Resources; using System.Text; using Spectre.Console.Cli; @@ -25,9 +26,18 @@ public static async Task Main(string[] args) var app = new CommandApp() .WithData(cts.Token) - .WithDescription("This program connects to a PLC and reads the variables specified as command line arguments."); + .WithDescription("This program connects to a Siemens S7 PLC using RFC1006 and reads the variables specified."); - app.Configure(config => { config.SetApplicationName("s7mon.exe"); }); + + app.Configure(config => + { + config.AddExample("192.0.0.10 db100.int12"); + config.AddExample("192.0.0.10 --cpu 2 --rack 1 db100.int12"); + + config.SetHelpProvider(new CustomHelpProvider(config.Settings)); + + config.SetApplicationName(OperatingSystem.IsWindows() ? "s7mon.exe" : "s7mon"); + }); return await app.RunAsync(args); } diff --git a/Sharp7.Monitor/Properties/launchSettings.json b/Sharp7.Monitor/Properties/launchSettings.json index 5bd1a19..d6f8d24 100644 --- a/Sharp7.Monitor/Properties/launchSettings.json +++ b/Sharp7.Monitor/Properties/launchSettings.json @@ -1,8 +1,13 @@ -{ +{ "profiles": { "Sharp7.Monitor": { "commandName": "Project", "commandLineArgs": "10.30.110.62 DB2050.Bit0.1 DB2050.Byte1 DB2050.Byte2.4 DB2050.Int6 DB2050.UInt8 DB2050.DInt10 DB2050.UDInt14 DB2050.LInt18 DB2050.ULInt26 DB2050.Real34 DB2050.LReal38 DB2050.String50.20 DB2050.WString80.20 DB2050.Byte130.20 " + }, + + "no args": { + "commandName": "Project", + "commandLineArgs": "" } } -} \ No newline at end of file +} diff --git a/Sharp7.Monitor/ReadPlcCommand.cs b/Sharp7.Monitor/ReadPlcCommand.cs index 85a3c34..dbcd2e9 100644 --- a/Sharp7.Monitor/ReadPlcCommand.cs +++ b/Sharp7.Monitor/ReadPlcCommand.cs @@ -49,7 +49,7 @@ private static IRenderable FormatCellData(object value) _ => new Text(value.ToString() ?? "", CustomStyles.Default) }; - Markup FormatNo() => new($"[blue]0x{value:X2}[/] {value}", CustomStyles.Default); + Markup FormatNo() => new($"[lightgoldenrod2_1]0x{value:X2}[/] {value}", CustomStyles.Default); } private static async Task RunProgram(Settings settings, CancellationToken token) @@ -124,16 +124,16 @@ public sealed class Settings : CommandSettings 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.")] + [Description("Variables to read from S7, like Db200.Int4")] 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")] + [Description("CPU MPI address of S7 instance")] [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")] + [Description("Rack number of S7 instance")] [DefaultValue(0)] public int RackNumber { get; init; } diff --git a/Sharp7.Monitor/VariableRecord.cs b/Sharp7.Monitor/VariableRecord.cs index fbfeba5..d1ac2e7 100644 --- a/Sharp7.Monitor/VariableRecord.cs +++ b/Sharp7.Monitor/VariableRecord.cs @@ -5,7 +5,7 @@ namespace Sharp7.Monitor; public class VariableRecord { private object value = new(); - private int valueUpdated; + private volatile int valueUpdated; public required string Address { get; init; } public required int RowIdx { get; init; } @@ -52,4 +52,4 @@ public bool HasUpdate([NotNullWhen(true)] out object? newValue) return false; } } -} \ No newline at end of file +}