Only update console, when content changes

This commit is contained in:
Peter Butzhammer
2024-04-28 20:59:34 +02:00
parent cd70cc4714
commit def185ec6c
5 changed files with 150 additions and 96 deletions

View File

@@ -1,5 +1,7 @@
using Spectre.Console;
namespace Sharp7.Monitor;
public static class CustomStyles
{
public static Style Error { get; } = new Style(foreground: Color.Red);

View File

@@ -1,15 +1,15 @@
using System.Collections;
using System.ComponentModel;
using System.ComponentModel;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using JetBrains.Annotations;
using Sharp7.Read;
using Sharp7.Rx;
using Sharp7.Rx.Enums;
using Spectre.Console;
using Spectre.Console.Cli;
using Spectre.Console.Rendering;
namespace Sharp7.Monitor;
internal sealed class ReadPlcCommand : AsyncCommand<ReadPlcCommand.Settings>
{
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
@@ -27,9 +27,9 @@ internal sealed class ReadPlcCommand : AsyncCommand<ReadPlcCommand.Settings>
return 0;
}
private static IRenderable FormatCellData(VariableRecord record)
private static IRenderable FormatCellData(object value)
{
return record.Value switch
return value switch
{
IRenderable renderable => renderable,
Exception ex => new Text(ex.Message, CustomStyles.Error),
@@ -42,10 +42,10 @@ internal sealed class ReadPlcCommand : AsyncCommand<ReadPlcCommand.Settings>
long => FormatNo(),
ulong => FormatNo(),
_ => new Text(record.Value.ToString() ?? "")
_ => new Text(value.ToString() ?? "")
};
Markup FormatNo() => new($"[blue]0x{record.Value:X2}[/] {record.Value}");
Markup FormatNo() => new($"[blue]0x{value:X2}[/] {value}");
}
private static async Task RunProgram(Settings settings, CancellationToken token)
@@ -99,9 +99,10 @@ internal sealed class ReadPlcCommand : AsyncCommand<ReadPlcCommand.Settings>
while (!token.IsCancellationRequested)
{
foreach (var record in variableContainer.VariableRecords)
if (record.HasUpdate(out var value))
table.Rows.Update(
record.RowIdx, 1,
FormatCellData(record)
FormatCellData(value)
);
ctx.Refresh();

View File

@@ -1,4 +1,4 @@
namespace Sharp7.Read;
namespace Sharp7.Monitor;
public static class StringHelper
{

View File

@@ -3,6 +3,8 @@ using Sharp7.Rx.Enums;
using Sharp7.Rx.Interfaces;
using Spectre.Console;
namespace Sharp7.Monitor;
public class VariableContainer : IDisposable
{
private readonly IDisposable subscriptions;

View File

@@ -1,6 +1,55 @@
public class VariableRecord
using System.Diagnostics.CodeAnalysis;
namespace Sharp7.Monitor;
public class VariableRecord
{
private object value = new();
private int valueUpdated;
public required string Address { get; init; }
public required int RowIdx { get; init; }
public object Value { get; set; }
public object Value
{
get => value;
set
{
if (!IsEquivalent(this.value, value))
{
this.value = value;
valueUpdated = 1;
}
}
}
private bool IsEquivalent(object oldValue, object newValue)
{
// Special treatmant for byte arrays
if (oldValue is byte[] oldArray && newValue is byte[] newArray)
{
if (oldArray.Length != newArray.Length) return false;
for (var i = 0; i < oldArray.Length; i++)
if (oldArray[i] != newArray[i]) return false;
return true;
}
// all other types read from PLC have value compare semantics.
return oldValue == newValue;
}
public bool HasUpdate([NotNullWhen(true)] out object? newValue)
{
if (Interlocked.Exchange(ref valueUpdated, 0) == 1)
{
newValue = value;
return true;
}
else
{
newValue = null;
return false;
}
}
}