From 9b0749baae86bcd6b5ed619a0fe5fc136be16ce1 Mon Sep 17 00:00:00 2001 From: Peter Butzhammer Date: Tue, 6 Feb 2024 13:39:55 +0100 Subject: [PATCH] Cache S7 variable names --- Sharp7.Rx/CacheVariableNameParser.cs | 20 ++++++++++++++++++++ Sharp7.Rx/Interfaces/IS7Connector.cs | 2 +- Sharp7.Rx/S7VariableNameParser.cs | 2 +- Sharp7.Rx/Sharp7Connector.cs | 22 ++++++++++------------ Sharp7.Rx/Sharp7Plc.cs | 15 ++------------- 5 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 Sharp7.Rx/CacheVariableNameParser.cs diff --git a/Sharp7.Rx/CacheVariableNameParser.cs b/Sharp7.Rx/CacheVariableNameParser.cs new file mode 100644 index 0000000..ddd258b --- /dev/null +++ b/Sharp7.Rx/CacheVariableNameParser.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Concurrent; +using Sharp7.Rx.Interfaces; + +namespace Sharp7.Rx +{ + internal class CacheVariableNameParser : IS7VariableNameParser + { + private static readonly ConcurrentDictionary addressCache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + + private readonly IS7VariableNameParser inner; + + public CacheVariableNameParser(IS7VariableNameParser inner) + { + this.inner = inner; + } + + public S7VariableAddress Parse(string input) => addressCache.GetOrAdd(input, inner.Parse); + } +} \ No newline at end of file diff --git a/Sharp7.Rx/Interfaces/IS7Connector.cs b/Sharp7.Rx/Interfaces/IS7Connector.cs index 74767a0..1515901 100644 --- a/Sharp7.Rx/Interfaces/IS7Connector.cs +++ b/Sharp7.Rx/Interfaces/IS7Connector.cs @@ -21,6 +21,6 @@ namespace Sharp7.Rx.Interfaces Task WriteBit(Operand operand, ushort startByteAddress, byte bitAdress, bool value, ushort dbNr, CancellationToken token); Task WriteBytes(Operand operand, ushort startByteAdress, byte[] data, ushort dBNr, CancellationToken token); ILogger Logger { get; } - Task> ExecuteMultiVarRequest(IEnumerable variableNames); + Task> ExecuteMultiVarRequest(IReadOnlyList variableNames); } } \ No newline at end of file diff --git a/Sharp7.Rx/S7VariableNameParser.cs b/Sharp7.Rx/S7VariableNameParser.cs index b65f4c7..c898537 100644 --- a/Sharp7.Rx/S7VariableNameParser.cs +++ b/Sharp7.Rx/S7VariableNameParser.cs @@ -12,7 +12,7 @@ namespace Sharp7.Rx { private static readonly Regex regex = new Regex(@"^(?db{1})(?\d{1,4})\.?(?dbx|x|s|string|b|dbb|d|int|dbw|w|dint|dul|dulint|dulong|){1}(?\d+)(\.(?\d+))?$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant); - private static readonly IReadOnlyDictionary types = new Dictionary(StringComparer.InvariantCultureIgnoreCase) + private static readonly IReadOnlyDictionary types = new Dictionary(StringComparer.OrdinalIgnoreCase) { {"x", DbType.Bit}, {"dbx", DbType.Bit}, diff --git a/Sharp7.Rx/Sharp7Connector.cs b/Sharp7.Rx/Sharp7Connector.cs index 89e7921..b87c324 100644 --- a/Sharp7.Rx/Sharp7Connector.cs +++ b/Sharp7.Rx/Sharp7Connector.cs @@ -21,7 +21,6 @@ namespace Sharp7.Rx { private readonly IS7VariableNameParser variableNameParser; private readonly BehaviorSubject connectionStateSubject = new BehaviorSubject(Enums.ConnectionState.Initial); - private ConcurrentDictionary s7VariableAddresses = new ConcurrentDictionary(); private readonly CompositeDisposable disposables = new CompositeDisposable(); private readonly LimitedConcurrencyLevelTaskScheduler scheduler = new LimitedConcurrencyLevelTaskScheduler(maxDegreeOfParallelism:1); @@ -34,16 +33,15 @@ namespace Sharp7.Rx private bool disposed; public ILogger Logger { get; set; } - public async Task> ExecuteMultiVarRequest(IEnumerable variableNames) + public async Task> ExecuteMultiVarRequest(IReadOnlyList variableNames) { - var enumerable = variableNames as string[] ?? variableNames.ToArray(); - - if (enumerable.IsEmpty()) + if (variableNames.IsEmpty()) return new Dictionary(); var s7MultiVar = new S7MultiVar(sharp7); - var buffers = enumerable.Select(key => new {VariableName = key, Address = s7VariableAddresses.GetOrAdd(key, s => variableNameParser.Parse(s))}) + var buffers = variableNames + .Select(key => new {VariableName = key, Address = variableNameParser.Parse(key)}) .Select(x => { var buffer = new byte[x.Address.Length]; @@ -67,10 +65,10 @@ namespace Sharp7.Rx public Sharp7Connector(PlcConnectionSettings settings, IS7VariableNameParser variableNameParser) { this.variableNameParser = variableNameParser; - this.ipAddress = settings.IpAddress; - this.cpuSlotNr = settings.CpuMpiAddress; - this.port = settings.Port; - this.rackNr = settings.RackNumber; + ipAddress = settings.IpAddress; + cpuSlotNr = settings.CpuMpiAddress; + port = settings.Port; + rackNr = settings.RackNumber; ReconnectDelay = TimeSpan.FromSeconds(5); } @@ -120,7 +118,7 @@ namespace Sharp7.Rx try { sharp7 = new S7Client(); - sharp7.PLCPort = this.port; + sharp7.PLCPort = port; var subscription = ConnectionState @@ -223,7 +221,7 @@ namespace Sharp7.Rx if (result != 0) { await EvaluateErrorCode(result); - var errorText = this.sharp7.ErrorText(result); + var errorText = sharp7.ErrorText(result); throw new InvalidOperationException($"Error reading {operand}{dBNr}:{startByteAddress}->{bytesToRead} ({errorText})"); } diff --git a/Sharp7.Rx/Sharp7Plc.cs b/Sharp7.Rx/Sharp7Plc.cs index 3273a40..3f733cb 100644 --- a/Sharp7.Rx/Sharp7Plc.cs +++ b/Sharp7.Rx/Sharp7Plc.cs @@ -20,11 +20,7 @@ namespace Sharp7.Rx { public class Sharp7Plc : IPlc { - private readonly string ipAddress; - private readonly int rackNumber; - private readonly int cpuMpiAddress; - private readonly int port; - private readonly IS7VariableNameParser varaibleNameParser; + private readonly IS7VariableNameParser varaibleNameParser = new CacheVariableNameParser(new S7VariableNameParser()); private bool disposed; private ISubject disposingSubject = new Subject(); private IS7Connector s7Connector; @@ -37,14 +33,7 @@ namespace Sharp7.Rx public Sharp7Plc(string ipAddress, int rackNumber, int cpuMpiAddress, int port = 102) { - this.ipAddress = ipAddress; - this.rackNumber = rackNumber; - this.cpuMpiAddress = cpuMpiAddress; - this.port = port; - plcConnectionSettings = new PlcConnectionSettings(){IpAddress = ipAddress, RackNumber = rackNumber, CpuMpiAddress = cpuMpiAddress, Port = port}; - - varaibleNameParser = new S7VariableNameParser(); } public IObservable ConnectionState { get; private set; } @@ -403,7 +392,7 @@ namespace Sharp7.Rx var stopWatch = Stopwatch.StartNew(); foreach (var partsOfMultiVarRequest in multiVariableSubscriptions.ExistingKeys.Buffer(MultiVarRequestMaxItems)) { - var multiVarRequest = await connector.ExecuteMultiVarRequest(partsOfMultiVarRequest); + var multiVarRequest = await connector.ExecuteMultiVarRequest(partsOfMultiVarRequest as IReadOnlyList??partsOfMultiVarRequest.ToList()); foreach (var pair in multiVarRequest) {