From 09f4da54a9a7c875e09c1533d1a21d452722117a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= Date: Thu, 15 Jun 2023 20:04:38 +0200 Subject: [PATCH] Made registers use the IRegister interface - cleanup and refactoring - fully implemented auto prop register generator unit tests #4 - added plc test program c30 fpx-h - fixed bitarray setback - cleaned up examples and added new ones with addition of attributes for later additions --- Examples/ExampleScenarios.cs | 173 ++++++++ Examples/Program.cs | 280 ++++--------- Examples/ScenarioAttribute.cs | 15 + Examples/TestRegisters.cs | 7 +- Examples/TestRegistersEnumBitwise.cs | 106 +++++ MewtocolNet/Mewtocol/DynamicInterface.cs | 86 ++-- MewtocolNet/Mewtocol/IRegister.cs | 101 +++++ MewtocolNet/Mewtocol/MewtocolInterface.cs | 155 +++---- .../Mewtocol/MewtocolInterfaceRequests.cs | 10 +- .../RegisterCollectionBase.cs | 19 +- .../Mewtocol/Subregisters/BRegister.cs | 104 ++++- .../Mewtocol/Subregisters/NRegister.cs | 204 ++++++++- .../Mewtocol/Subregisters/NRegisterResult.cs | 4 +- MewtocolNet/Mewtocol/Subregisters/Register.cs | 388 ------------------ .../Mewtocol/Subregisters/SRegister.cs | 92 ++++- MewtocolNet/MewtocolNet.csproj | 7 +- MewtocolTests/AutomatedPropertyRegisters.cs | 306 ++++++++++++++ MewtocolTests/TestComProtocol.cs | 53 --- .../{TestClient.cs => TestLivePLC.cs} | 4 +- MewtocolTests/TestRegisterInterface.cs | 164 ++++++++ PLC_Test/test_c30_fpx_h.ini | Bin 0 -> 832 bytes PLC_Test/test_c30_fpx_h.pro | Bin 0 -> 262144 bytes PLC_Test/test_c30_fpx_h.xml | 11 + 23 files changed, 1478 insertions(+), 811 deletions(-) create mode 100644 Examples/ExampleScenarios.cs create mode 100644 Examples/ScenarioAttribute.cs create mode 100644 Examples/TestRegistersEnumBitwise.cs create mode 100644 MewtocolNet/Mewtocol/IRegister.cs delete mode 100644 MewtocolNet/Mewtocol/Subregisters/Register.cs create mode 100644 MewtocolTests/AutomatedPropertyRegisters.cs delete mode 100644 MewtocolTests/TestComProtocol.cs rename MewtocolTests/{TestClient.cs => TestLivePLC.cs} (96%) create mode 100644 MewtocolTests/TestRegisterInterface.cs create mode 100644 PLC_Test/test_c30_fpx_h.ini create mode 100644 PLC_Test/test_c30_fpx_h.pro create mode 100644 PLC_Test/test_c30_fpx_h.xml diff --git a/Examples/ExampleScenarios.cs b/Examples/ExampleScenarios.cs new file mode 100644 index 0000000..428d212 --- /dev/null +++ b/Examples/ExampleScenarios.cs @@ -0,0 +1,173 @@ +using MewtocolNet.Logging; +using MewtocolNet; +using System; +using System.Reflection; +using System.Threading.Tasks; +using System.Collections; + +namespace Examples; + +public class ExampleScenarios { + + public static bool MewtocolLoggerEnabled = false; + + public void SetupLogger () { + + //attaching the logger + Logger.LogLevel = LogLevel.Verbose; + Logger.OnNewLogMessage((date, msg) => { + if(MewtocolLoggerEnabled) + Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}"); + }); + + } + + [Scenario("Permament connection with poller")] + public async Task RunCyclicPollerAsync () { + + Console.WriteLine("Starting poller scenario"); + + int runTime = 10000; + int remainingTime = runTime; + + //setting up a new PLC interface and register collection + MewtocolInterface interf = new MewtocolInterface("192.168.115.210"); + TestRegisters registers = new TestRegisters(); + + //attaching the register collection and an automatic poller + interf.WithRegisterCollection(registers).WithPoller(); + + await interf.ConnectAsync(); + + _ = Task.Factory.StartNew(async () => { + + while (interf.IsConnected) { + + //flip the bool register each tick and wait for it to be registered + await interf.SetRegisterAsync(nameof(registers.TestBool1), !registers.TestBool1); + + Console.Title = $"Polling Paused: {interf.PollingPaused}, " + + $"Poller active: {interf.PollerActive}, " + + $"Speed UP: {interf.BytesPerSecondUpstream} B/s, " + + $"Speed DOWN: {interf.BytesPerSecondDownstream} B/s, " + + $"Poll delay: {interf.PollerDelayMs} ms, " + + $"Queued MSGs: {interf.QueuedMessages}"; + + Console.Clear(); + Console.WriteLine("Underlying registers on tick: \n"); + + foreach (var register in interf.Registers) { + + Console.WriteLine($"{register.GetCombinedName()} / {register.GetRegisterPLCName()} - Value: {register.GetValueString()}"); + + } + + Console.WriteLine($"{registers.TestBool1}"); + Console.WriteLine($"{registers.TestDuplicate}"); + + remainingTime -= 1000; + + Console.WriteLine($"\nStopping in: {remainingTime}ms"); + + await Task.Delay(1000); + + } + + }); + + await Task.Delay(runTime); + interf.Disconnect(); + + } + + [Scenario("Dispose and disconnect connection")] + public async Task RunDisposalAndDisconnectAsync () { + + //automatic disposal + using (var interf = new MewtocolInterface("192.168.115.210")) { + + await interf.ConnectAsync(); + + if (interf.IsConnected) { + + Console.WriteLine("Opened connection"); + + await Task.Delay(5000); + + } + + } + + Console.WriteLine("Disposed, closed connection"); + + //manual close + var interf2 = new MewtocolInterface("192.168.115.210"); + + await interf2.ConnectAsync(); + + if (interf2.IsConnected) { + + Console.WriteLine("Opened connection"); + + await Task.Delay(5000); + + } + + interf2.Disconnect(); + + Console.WriteLine("Disconnected, closed connection"); + + } + + [Scenario("Test auto enums and bitwise, needs the example program from MewtocolNet/PLC_Test")] + public async Task RunEnumsBitwiseAsync () { + + Console.WriteLine("Starting auto enums and bitwise"); + + //setting up a new PLC interface and register collection + MewtocolInterface interf = new MewtocolInterface("192.168.115.210"); + TestRegistersEnumBitwise registers = new TestRegistersEnumBitwise(); + + //attaching the register collection and an automatic poller + interf.WithRegisterCollection(registers).WithPoller(); + + registers.PropertyChanged += (s, e) => { + + Console.Clear(); + + var props = registers.GetType().GetProperties(); + + foreach (var prop in props) { + + var val = prop.GetValue(registers); + string printVal = val?.ToString() ?? "null"; + + if (val is BitArray bitarr) { + printVal = bitarr.ToBitString(); + } + + Console.Write($"{prop.Name} - "); + + if(printVal == "True") { + Console.ForegroundColor = ConsoleColor.Green; + } + + Console.Write($"{printVal}"); + + Console.ResetColor(); + + Console.WriteLine(); + + } + + }; + + await interf.ConnectAsync(); + + await interf.SetRegisterAsync(nameof(registers.StartCyclePLC), true); + + await Task.Delay(-1); + + } + +} diff --git a/Examples/Program.cs b/Examples/Program.cs index e7531f7..c3bd799 100644 --- a/Examples/Program.cs +++ b/Examples/Program.cs @@ -1,14 +1,15 @@ using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using System.Threading.Tasks; -using MewtocolNet; -using MewtocolNet.Logging; -using MewtocolNet.Registers; -using static System.Net.Mime.MediaTypeNames; namespace Examples; class Program { + static ExampleScenarios ExampleSzenarios = new ExampleScenarios(); + static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += (s,e) => { @@ -19,212 +20,81 @@ class Program { Console.WriteLine(e.Exception.ToString()); }; - Console.WriteLine("Enter your scenario number:\n" + - "1 = Permanent connection\n" + - "2 = Dispose connection"); + ExampleSzenarios.SetupLogger(); + + LoopInput(); + + } + + private static void LoopInput () { + + Console.WriteLine("All available scenarios\n"); + + var methods = ExampleSzenarios.GetType().GetMethods(); + var invokeableMethods = new List(); + + for (int i = 0, j = 0; i < methods.Length; i++) { + + MethodInfo method = methods[i]; + var foundAtt = method.GetCustomAttribute(typeof(ScenarioAttribute)); + + if(foundAtt != null && foundAtt is ScenarioAttribute att) { + + Console.WriteLine($"[{j + 1}] {method.Name}() - {att.Description}"); + invokeableMethods.Add(method); + + j++; + + } + + } + + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("\nEnter a number to excecute a example"); + Console.ResetColor(); + + Console.WriteLine("\nOther possible commands: \n\n" + + "'toggle logger' - toggle the built in mewtocol logger on/off\n" + + "'exit' - to close this program \n" + + "'clear' - to clear the output \n"); + + Console.Write("> "); var line = Console.ReadLine(); - if(line == "1") { - Scenario1(); + if (line == "toggle logger") { + + ExampleScenarios.MewtocolLoggerEnabled = !ExampleScenarios.MewtocolLoggerEnabled; + + Console.WriteLine(ExampleScenarios.MewtocolLoggerEnabled ? "Logger enabled" : "Logger disabled"); + + } else if (line == "exit") { + + Environment.Exit(0); + + } else if (line == "clear") { + + Console.Clear(); + + } else if (int.TryParse(line, out var lineNum)) { + + var index = Math.Clamp(lineNum - 1, 0, invokeableMethods.Count - 1); + + var task = (Task)invokeableMethods.ElementAt(index).Invoke(ExampleSzenarios, null); + + task.Wait(); + + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("The program ran to completition"); + Console.ResetColor(); + + } else { + + Console.WriteLine("Wrong input"); + } - if (line == "2") { - Scenario2(); - } - - Console.ReadLine(); - } - - private static bool isProgressReadout = false; - - static void Scenario1 () { - - Task.Factory.StartNew(async () => { - - //attaching the logger - Logger.LogLevel = LogLevel.Verbose; - Logger.OnNewLogMessage((date, msg) => { - Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}"); - }); - - //setting up a new PLC interface and register collection - MewtocolInterface interf = new MewtocolInterface("10.237.191.3"); - TestRegisters registers = new TestRegisters(); - - //attaching the register collection and an automatic poller - interf.WithRegisterCollection(registers).WithPoller(); - - _ = Task.Factory.StartNew(async () => { - while (true) { - if (isProgressReadout) continue; - Console.Title = $"Polling Paused: {interf.PollingPaused}, " + - $"Poller active: {interf.PollerActive}, " + - $"Speed UP: {interf.BytesPerSecondUpstream} B/s, " + - $"Speed DOWN: {interf.BytesPerSecondDownstream} B/s, " + - $"Poll delay: {interf.PollerDelayMs} ms, " + - $"Queued MSGs: {interf.QueuedMessages}"; - await Task.Delay(1000); - } - }); - - await interf.ConnectAsync(); - - //bool flip = false; - //while(true) { - - // if(!flip) { - // await interf.ConnectAsync(); - // } else { - // interf.Disconnect(); - // } - - // flip = !flip; - // await Task.Delay(5000); - - //} - - }); - - } - - static void AfterConnect (MewtocolInterface interf, TestRegisters registers) { - - //reading a value from the register collection - Console.WriteLine($"BitValue is: {registers.BitValue}"); - Console.WriteLine($"TestEnum is: {registers.TestEnum}"); - - _ = Task.Factory.StartNew(async () => { - - while(true) { - - isProgressReadout = true; - - await interf.ReadByteRange(1000, 2000, (p) => { - - var totSteps = 10; - var cSteps = totSteps * p; - - string progBar = ""; - for (int i = 0; i < totSteps; i++) { - - if(i < (int)cSteps) { - progBar += "⬛"; - } else { - progBar += "⬜"; - } - - } - - Console.Title = $"Prog read range: {(p * 100).ToString("N1")}% {progBar} Queued MSGs: {interf.QueuedMessages}"; - - }); - - isProgressReadout = false; - - await Task.Delay(3000); - - } - - }); - - //writing a value to the registers - _ = Task.Factory.StartNew(async () => { - - //set plc to run mode if not already - await interf.SetOperationMode(OPMode.Run); - - int startAdress = 10000; - int entryByteSize = 20 * 20; - - var bytes = await interf.ReadByteRange(startAdress, entryByteSize); - Console.WriteLine($"Bytes: {string.Join('-', bytes)}"); - - await Task.Delay(2000); - - await interf.SetRegisterAsync(nameof(registers.TestInt32), 100); - - //adds 10 each time the plc connects to the PLCs INT regíster - interf.SetRegister(nameof(registers.TestInt16), (short)(registers.TestInt16 + 10)); - //adds 1 each time the plc connects to the PLCs DINT regíster - interf.SetRegister(nameof(registers.TestInt32), (registers.TestInt32 + 1)); - //adds 11.11 each time the plc connects to the PLCs REAL regíster - interf.SetRegister(nameof(registers.TestFloat32), (float)(registers.TestFloat32 + 11.11)); - //writes 'Hello' to the PLCs string register - interf.SetRegister(nameof(registers.TestString2), "Hello"); - //set the current second to the PLCs TIME register - interf.SetRegister(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second)); - - //test pausing poller - - bool pollerPaused = false; - - while (true) { - - await Task.Delay(5000); - - pollerPaused = !pollerPaused; - - if (pollerPaused) { - Console.WriteLine("Pausing poller"); - await interf.PausePollingAsync(); - //interf.PollerDelayMs += 10; - Console.WriteLine("Paused poller"); - } else { - interf.ResumePolling(); - Console.WriteLine("Resumed poller"); - } - - } - - - }); - - } - - static void Scenario2 () { - - Logger.LogLevel = LogLevel.Critical; - Logger.OnNewLogMessage((date, msg) => { - Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}"); - }); - - Task.Factory.StartNew(async () => { - - //automatic endpoint - using (var interf = new MewtocolInterface("10.237.191.3")) { - - await interf.ConnectAsync(); - - if (interf.IsConnected) { - - await Task.Delay(5000); - - } - - interf.Disconnect(); - - } - - //manual endpoint - using (var interf = new MewtocolInterface("10.237.191.3")) { - - interf.HostEndpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("10.237.191.77"), 0); - - await interf.ConnectAsync(); - - if(interf.IsConnected) { - - await Task.Delay(5000); - - } - - interf.Disconnect(); - - } - - - }); + LoopInput(); } diff --git a/Examples/ScenarioAttribute.cs b/Examples/ScenarioAttribute.cs new file mode 100644 index 0000000..5a869c2 --- /dev/null +++ b/Examples/ScenarioAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace Examples; + +public class ScenarioAttribute : Attribute { + + public string Description { get; private set; } + + public ScenarioAttribute(string description) { + + Description = description; + + } + +} \ No newline at end of file diff --git a/Examples/TestRegisters.cs b/Examples/TestRegisters.cs index acfc887..dfa77cc 100644 --- a/Examples/TestRegisters.cs +++ b/Examples/TestRegisters.cs @@ -10,8 +10,13 @@ namespace Examples { [Register(1000, RegisterType.R)] public bool TestBool1 { get; private set; } + private int testDuplicate; + [Register(1000)] - public int TestDuplicate { get; private set; } + public int TestDuplicate { + get => testDuplicate; + set => AutoSetter(value, ref testDuplicate); + } //corresponds to a XD input of the PLC [Register(RegisterType.X, SpecialAddress.D)] diff --git a/Examples/TestRegistersEnumBitwise.cs b/Examples/TestRegistersEnumBitwise.cs new file mode 100644 index 0000000..2a24825 --- /dev/null +++ b/Examples/TestRegistersEnumBitwise.cs @@ -0,0 +1,106 @@ +using MewtocolNet; +using MewtocolNet.RegisterAttributes; +using System; +using System.Collections; + +namespace Examples { + + public class TestRegistersEnumBitwise : RegisterCollectionBase { + + private bool startCyclePLC; + + [Register(50, RegisterType.R)] + public bool StartCyclePLC { + get => startCyclePLC; + set => AutoSetter(value, ref startCyclePLC); + } + + //the enum you want to read out + public enum CurrentState { + + Undefined = 0, + State1 = 1, + State2 = 2, + //If you leave an enum empty it still works + //State3 = 3, + State4 = 4, + State5 = 5, + State6 = 6, + State7 = 7, + State8 = 8, + State9 = 9, + State10 = 10, + State11 = 11, + State12 = 12, + State13 = 13, + State14 = 14, + State15 = 15, + + } + + //automatically convert the short (PLC int) register to an enum + [Register(500)] + public CurrentState TestEnum16 { get; private set; } + + //also works for 32bit registers + [Register(501, BitCount.B32)] + public CurrentState TestEnum32 { get; private set; } + + //get the whole bit array from DT503 + + [Register(503)] + public BitArray TestBitRegister16 { get; private set; } + + //you can also extract single bits from DT503 + + [Register(503, 0, BitCount.B16)] + public bool BitValue0 { get; private set; } + + [Register(503, 1, BitCount.B16)] + public bool BitValue1 { get; private set; } + + [Register(503, 2, BitCount.B16)] + public bool BitValue2 { get; private set; } + + [Register(503, 3, BitCount.B16)] + public bool BitValue3 { get; private set; } + + [Register(503, 4, BitCount.B16)] + public bool BitValue4 { get; private set; } + + [Register(503, 5, BitCount.B16)] + public bool BitValue5 { get; private set; } + + [Register(503, 6, BitCount.B16)] + public bool BitValue6 { get; private set; } + + [Register(503, 7, BitCount.B16)] + public bool BitValue7 { get; private set; } + + [Register(503, 8, BitCount.B16)] + public bool BitValue8 { get; private set; } + + [Register(503, 9, BitCount.B16)] + public bool BitValue9 { get; private set; } + + [Register(503, 10, BitCount.B16)] + public bool BitValue10 { get; private set; } + + [Register(503, 11, BitCount.B16)] + public bool BitValue11 { get; private set; } + + [Register(503, 12, BitCount.B16)] + public bool BitValue12 { get; private set; } + + [Register(503, 13, BitCount.B16)] + public bool BitValue13 { get; private set; } + + [Register(503, 14, BitCount.B16)] + public bool BitValue14 { get; private set; } + + [Register(503, 15, BitCount.B16)] + public bool BitValue15 { get; private set; } + + } + +} diff --git a/MewtocolNet/Mewtocol/DynamicInterface.cs b/MewtocolNet/Mewtocol/DynamicInterface.cs index 0162b94..a4556a3 100644 --- a/MewtocolNet/Mewtocol/DynamicInterface.cs +++ b/MewtocolNet/Mewtocol/DynamicInterface.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -25,7 +26,7 @@ namespace MewtocolNet { public bool PollerActive => !pollerTaskStopped; internal event Action PolledCycle; - + internal volatile bool pollerTaskRunning; internal volatile bool pollerTaskStopped; internal volatile bool pollerIsPaused; @@ -214,7 +215,7 @@ namespace MewtocolNet { /// A naming definition for QOL, doesn't effect PLC and is optional public void AddRegister (int _address, RegisterType _type, string _name = null) { - Register toAdd = null; + IRegister toAdd = null; //as number registers if (_type == RegisterType.DT_short) { @@ -243,30 +244,29 @@ namespace MewtocolNet { internal void AddRegister (Type _colType, int _address, RegisterType _type, string _name = null) { - Register toAdd = null; + IRegister toAdd = null; //as number registers if (_type == RegisterType.DT_short) { - toAdd = new NRegister(_address, _name); + toAdd = new NRegister(_address, _name).WithCollectionType(_colType); } if (_type == RegisterType.DT_ushort) { - toAdd = new NRegister(_address, _name); + toAdd = new NRegister(_address, _name).WithCollectionType(_colType); } if (_type == RegisterType.DDT_int) { - toAdd = new NRegister(_address, _name); + toAdd = new NRegister(_address, _name).WithCollectionType(_colType); } if (_type == RegisterType.DDT_uint) { - toAdd = new NRegister(_address, _name); + toAdd = new NRegister(_address, _name).WithCollectionType(_colType); } if (_type == RegisterType.DDT_float) { - toAdd = new NRegister(_address, _name); + toAdd = new NRegister(_address, _name).WithCollectionType(_colType); } if (toAdd == null) { - toAdd = new BRegister(_address, _type, _name); + toAdd = new BRegister(_address, _type, _name).WithCollectionType(_colType); } - toAdd.collectionType = _colType; Registers.Add(toAdd); } @@ -328,7 +328,7 @@ namespace MewtocolNet { throw new NotSupportedException($"_lenght parameter only allowed for register of type string"); } - Register toAdd; + IRegister toAdd; if (regType == typeof(short)) { toAdd = new NRegister(_address, _name); @@ -359,7 +359,8 @@ namespace MewtocolNet { } - internal void AddRegister (Type _colType, int _address, int _length = 1, string _name = null, bool _isBitwise = false, Type _enumType = null) { + //Internal register adding for auto register collection building + internal void AddRegister (Type _colType, int _address, PropertyInfo boundProp, int _length = 1, bool _isBitwise = false, Type _enumType = null) { Type regType = typeof(T); @@ -367,45 +368,51 @@ namespace MewtocolNet { throw new NotSupportedException($"_lenght parameter only allowed for register of type string"); } - if (Registers.Any(x => x.MemoryAdress == _address) && _isBitwise) { + if (Registers.Any(x => x.MemoryAddress == _address) && _isBitwise) { return; } - Register reg = null; + IRegister reg = null; + + string propName = boundProp.Name; + + //rename the property name to prevent duplicate names in case of a bitwise prop + if(_isBitwise && regType == typeof(short)) + propName = $"Auto_Bitwise_DT{_address}"; + + if (_isBitwise && regType == typeof(int)) + propName = $"Auto_Bitwise_DDT{_address}"; if (regType == typeof(short)) { - reg = new NRegister(_address, _name, _isBitwise); + reg = new NRegister(_address, propName, _isBitwise, _enumType).WithCollectionType(_colType); } else if (regType == typeof(ushort)) { - reg = new NRegister(_address, _name); + reg = new NRegister(_address, propName).WithCollectionType(_colType); } else if (regType == typeof(int)) { - reg = new NRegister(_address, _name, _isBitwise, _enumType); + reg = new NRegister(_address, propName, _isBitwise, _enumType).WithCollectionType(_colType); } else if (regType == typeof(uint)) { - reg = new NRegister(_address, _name); + reg = new NRegister(_address, propName).WithCollectionType(_colType); } else if (regType == typeof(float)) { - reg = new NRegister(_address, _name); + reg = new NRegister(_address, propName).WithCollectionType(_colType); } else if (regType == typeof(string)) { - reg = new SRegister(_address, _length, _name); + reg = new SRegister(_address, _length, propName).WithCollectionType(_colType); } else if (regType == typeof(TimeSpan)) { - reg = new NRegister(_address, _name); + reg = new NRegister(_address, propName).WithCollectionType(_colType); } else if (regType == typeof(bool)) { - reg = new BRegister(_address, RegisterType.R, _name); + reg = new BRegister(_address, RegisterType.R, propName).WithCollectionType(_colType); } if (reg == null) { throw new NotSupportedException($"The type {regType} is not allowed for Registers \n" + $"Allowed are: short, ushort, int, uint, float and string"); - } else { - - - if (Registers.Any(x => x.GetRegisterPLCName() == reg.GetRegisterPLCName()) && !_isBitwise) { - throw new NotSupportedException($"Cannot add a register multiple times, " + - $"make sure that all register attributes or AddRegister assignments have different adresses."); - } - - reg.collectionType = _colType; - Registers.Add(reg); } + if (Registers.Any(x => x.GetRegisterPLCName() == reg.GetRegisterPLCName()) && !_isBitwise) { + throw new NotSupportedException($"Cannot add a register multiple times, " + + $"make sure that all register attributes or AddRegister assignments have different adresses."); + } + + Registers.Add(reg); + } #endregion @@ -416,7 +423,7 @@ namespace MewtocolNet { /// Gets a register that was added by its name /// /// - public Register GetRegister (string name) { + public IRegister GetRegister (string name) { return Registers.FirstOrDefault(x => x.Name == name); @@ -427,13 +434,18 @@ namespace MewtocolNet { /// /// The type of register /// A casted register or the default value - public T GetRegister (string name) where T : Register { + public T GetRegister (string name) where T : IRegister { try { + var reg = Registers.FirstOrDefault(x => x.Name == name); - return reg as T; + return (T)reg; + } catch (InvalidCastException) { + return default(T); + } + } #endregion @@ -443,7 +455,7 @@ namespace MewtocolNet { /// /// Gets a list of all added registers /// - public List GetAllRegisters () { + public List GetAllRegisters () { return Registers; @@ -453,7 +465,7 @@ namespace MewtocolNet { #region Event Invoking - internal void InvokeRegisterChanged (Register reg) { + internal void InvokeRegisterChanged (IRegister reg) { RegisterChanged?.Invoke(reg); diff --git a/MewtocolNet/Mewtocol/IRegister.cs b/MewtocolNet/Mewtocol/IRegister.cs new file mode 100644 index 0000000..524bf15 --- /dev/null +++ b/MewtocolNet/Mewtocol/IRegister.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace MewtocolNet { + + /// + /// An interface for all register types + /// + public interface IRegister { + + /// + /// Gets called whenever the value was changed + /// + event Action ValueChanged; + + /// + /// The name of the register + /// + string Name { get; } + + /// + /// The current value of the register + /// + object Value { get; } + + /// + /// The plc memory address of the register + /// + int MemoryAddress { get; } + + /// + /// Indicates if the register is processed bitwise + /// + /// True if bitwise + bool IsUsedBitwise(); + + /// + /// Generates a string describing the starting memory address of the register + /// + string GetStartingMemoryArea(); + + /// + /// Gets the current value formatted as a readable string + /// + string GetValueString(); + + /// + /// Builds the identifier for the mewtocol query string + /// + /// + string BuildMewtocolQuery(); + + /// + /// Builds a register string that prepends the memory address fe. DDT or DT, X, Y etc + /// + string GetRegisterString(); + + /// + /// Builds a combined name for the attached property to uniquely identify the property register binding + /// + /// + string GetCombinedName(); + + /// + /// Gets the name of the class that contains the attached property + /// + /// + string GetContainerName(); + + /// + /// Builds a register name after the PLC convention
+ /// Example DDT100, XA, X6, Y1, DT3300 + ///
+ string GetRegisterPLCName(); + + /// + /// Clears the current value of the register and resets it to default + /// + void ClearValue(); + + /// + /// Triggers a notifychanged update event + /// + void TriggerNotifyChange(); + + /// + /// Gets the type of the class collection its attached property is in or null + /// + /// The class name or null if manually added + Type GetCollectionType(); + + /// + /// Builds a readable string with all important register informations + /// + string ToString(); + + } + +} diff --git a/MewtocolNet/Mewtocol/MewtocolInterface.cs b/MewtocolNet/Mewtocol/MewtocolInterface.cs index 3fcf273..9062077 100644 --- a/MewtocolNet/Mewtocol/MewtocolInterface.cs +++ b/MewtocolNet/Mewtocol/MewtocolInterface.cs @@ -15,8 +15,11 @@ using System.ComponentModel; using System.Net; using System.Threading; using MewtocolNet.Queue; +using System.Reflection; +using System.Timers; -namespace MewtocolNet { +namespace MewtocolNet +{ /// /// The PLC com interface class @@ -36,7 +39,7 @@ namespace MewtocolNet { /// /// Gets triggered when a registered data register changes its value /// - public event Action RegisterChanged; + public event Action RegisterChanged; /// /// Gets triggered when a property of the interface changes @@ -114,7 +117,7 @@ namespace MewtocolNet { /// /// The registered data registers of the PLC /// - public List Registers { get; set; } = new List(); + public List Registers { get; set; } = new List(); private string ip; private int port; @@ -209,7 +212,7 @@ namespace MewtocolNet { RegisterChanged += (o) => { - string address = $"{o.GetRegisterString()}{o.MemoryAdress}".PadRight(5, (char)32); + string address = $"{o.GetRegisterString()}{o.GetStartingMemoryArea()}".PadRight(5, (char)32); Logger.Log($"{address} " + $"{(o.Name != null ? $"({o.Name}) " : "")}" + @@ -442,40 +445,46 @@ namespace MewtocolNet { } if (prop.PropertyType == typeof(short)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop); } if (prop.PropertyType == typeof(ushort)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop); } if (prop.PropertyType == typeof(int)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop); } if (prop.PropertyType == typeof(uint)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop); } if (prop.PropertyType == typeof(float)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop); } if (prop.PropertyType == typeof(string)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, cAttribute.StringLength, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, cAttribute.StringLength); } if (prop.PropertyType.IsEnum) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName, _enumType: prop.PropertyType); + + if (cAttribute.BitCount == BitCount.B16) { + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, _enumType: prop.PropertyType); + } else { + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, _enumType: prop.PropertyType); + } + } //read number as bit array if (prop.PropertyType == typeof(BitArray)) { if (cAttribute.BitCount == BitCount.B16) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName, _isBitwise: true); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, _isBitwise: true); } else { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName, _isBitwise: true); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, _isBitwise: true); } } @@ -486,15 +495,15 @@ namespace MewtocolNet { //var bitwiseCount = Registers.Count(x => x.Value.isUsedBitwise); if (cAttribute.BitCount == BitCount.B16) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: $"Auto_Bitwise_DT{cAttribute.MemoryArea}", _isBitwise: true); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, _isBitwise: true); } else { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: $"Auto_Bitwise_DDT{cAttribute.MemoryArea}", _isBitwise: true); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop, _isBitwise: true); } } if (prop.PropertyType == typeof(TimeSpan)) { - AddRegister(collection.GetType(), cAttribute.MemoryArea, _name: propName); + AddRegister(collection.GetType(), cAttribute.MemoryArea, prop); } } @@ -505,43 +514,51 @@ namespace MewtocolNet { RegisterChanged += (reg) => { - //if the register is also used bitwise assign the boolean bit value to the according prop - if(reg.isUsedBitwise) { + //register is used bitwise + if(reg.IsUsedBitwise()) { for (int i = 0; i < props.Length; i++) { var prop = props[i]; var bitWiseFound = prop.GetCustomAttributes(true) - .FirstOrDefault(y => y.GetType() == typeof(RegisterAttribute) && ((RegisterAttribute)y).MemoryArea == reg.MemoryAdress); + .FirstOrDefault(y => y.GetType() == typeof(RegisterAttribute) && ((RegisterAttribute)y).MemoryArea == reg.MemoryAddress); + + if(bitWiseFound != null) { - if(bitWiseFound != null && reg is NRegister reg16) { var casted = (RegisterAttribute)bitWiseFound; var bitIndex = casted.AssignedBitIndex; - var bytes = BitConverter.GetBytes(reg16.Value); - BitArray bitAr = new BitArray(bytes); + BitArray bitAr = null; - if (bitIndex < bitAr.Length && bitIndex >= 0) { + if (reg is NRegister reg16) { + var bytes = BitConverter.GetBytes((short)reg16.Value); + bitAr = new BitArray(bytes); + } else if(reg is NRegister reg32) { + var bytes = BitConverter.GetBytes((int)reg32.Value); + bitAr = new BitArray(bytes); + } + + if (bitAr != null && bitIndex < bitAr.Length && bitIndex >= 0) { + + //set the specific bit index if needed prop.SetValue(collection, bitAr[bitIndex]); collection.TriggerPropertyChanged(prop.Name); - } - - } else if (bitWiseFound != null && reg is NRegister reg32) { - var casted = (RegisterAttribute)bitWiseFound; - var bitIndex = casted.AssignedBitIndex; - var bytes = BitConverter.GetBytes(reg32.Value); - BitArray bitAr = new BitArray(bytes); - prop.SetValue(collection, bitAr[bitIndex]); - collection.TriggerPropertyChanged(prop.Name); + } else if (bitAr != null) { + + //set the specific bit array if needed + prop.SetValue(collection, bitAr); + collection.TriggerPropertyChanged(prop.Name); + + } } } } - - + + //updating normal properties var foundToUpdate = props.FirstOrDefault(x => x.Name == reg.Name); if (foundToUpdate != null) { @@ -557,67 +574,25 @@ namespace MewtocolNet { //check if bit parse mode if (registerAttr.AssignedBitIndex == -1) { - //setting back booleans - if (foundToUpdate.PropertyType == typeof(bool)) { - foundToUpdate.SetValue(collection, ((BRegister)reg).Value); - } + HashSet NumericTypes = new HashSet { + typeof(bool), + typeof(short), + typeof(ushort), + typeof(int), + typeof(uint), + typeof(float), + typeof(TimeSpan), + typeof(string) + }; - //setting back numbers + var regValue = ((IRegister)reg).Value; - if (foundToUpdate.PropertyType == typeof(short)) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); - } - - if (foundToUpdate.PropertyType == typeof(ushort)) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); - } - - if (foundToUpdate.PropertyType == typeof(int)) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); - } - - if (foundToUpdate.PropertyType == typeof(uint)) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); - } - - if (foundToUpdate.PropertyType == typeof(float)) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); + if (NumericTypes.Any(x => foundToUpdate.PropertyType == x)) { + foundToUpdate.SetValue(collection, regValue); } if (foundToUpdate.PropertyType.IsEnum) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); - } - - if (foundToUpdate.PropertyType == typeof(TimeSpan)) { - foundToUpdate.SetValue(collection, ((NRegister)reg).Value); - } - - //setting back strings - - if (foundToUpdate.PropertyType == typeof(string)) { - foundToUpdate.SetValue(collection, ((SRegister)reg).Value); - } - - } - - - if (foundToUpdate.PropertyType == typeof(BitArray)) { - - //setting back bit registers - if (reg is NRegister shortReg) { - - var bytes = BitConverter.GetBytes(shortReg.Value); - BitArray bitAr = new BitArray(bytes); - foundToUpdate.SetValue(collection, bitAr); - - } - - if (reg is NRegister intReg) { - - var bytes = BitConverter.GetBytes(intReg.Value); - BitArray bitAr = new BitArray(bytes); - foundToUpdate.SetValue(collection, bitAr); - + foundToUpdate.SetValue(collection, regValue); } } diff --git a/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs b/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs index 9c69906..375fb73 100644 --- a/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs +++ b/MewtocolNet/Mewtocol/MewtocolInterfaceRequests.cs @@ -166,7 +166,7 @@ namespace MewtocolNet { /// The register to read public async Task ReadBoolRegister (BRegister _toRead) { - string requeststring = $"%{GetStationNumber()}#RCS{_toRead.BuildMewtocolIdent()}"; + string requeststring = $"%{GetStationNumber()}#RCS{_toRead.BuildMewtocolQuery()}"; var result = await SendCommandAsync(requeststring); if(!result.Success) { @@ -198,7 +198,7 @@ namespace MewtocolNet { /// The success state of the write operation public async Task WriteBoolRegister (BRegister _toWrite, bool value) { - string requeststring = $"%{GetStationNumber()}#WCS{_toWrite.BuildMewtocolIdent()}{(value ? "1" : "0")}"; + string requeststring = $"%{GetStationNumber()}#WCS{_toWrite.BuildMewtocolQuery()}{(value ? "1" : "0")}"; var result = await SendCommandAsync(requeststring); @@ -220,7 +220,7 @@ namespace MewtocolNet { Type numType = typeof(T); - string requeststring = $"%{GetStationNumber()}#RD{_toRead.BuildMewtocolIdent()}"; + string requeststring = $"%{GetStationNumber()}#RD{_toRead.BuildMewtocolQuery()}"; var result = await SendCommandAsync(requeststring); var failedResult = new NRegisterResult { @@ -335,7 +335,7 @@ namespace MewtocolNet { toWriteVal = null; } - string requeststring = $"%{GetStationNumber()}#WD{_toWrite.BuildMewtocolIdent()}{toWriteVal.ToHexString()}"; + string requeststring = $"%{GetStationNumber()}#WD{_toWrite.BuildMewtocolQuery()}{toWriteVal.ToHexString()}"; var result = await SendCommandAsync(requeststring); @@ -362,7 +362,7 @@ namespace MewtocolNet { /// public async Task ReadStringRegister (SRegister _toRead, int _stationNumber = 1) { - string requeststring = $"%{GetStationNumber()}#RD{_toRead.BuildMewtocolIdent()}"; + string requeststring = $"%{GetStationNumber()}#RD{_toRead.BuildMewtocolQuery()}"; var result = await SendCommandAsync(requeststring); if (result.Success) _toRead.SetValueFromPLC(result.Response.ParseDTString()); diff --git a/MewtocolNet/Mewtocol/RegisterAttributes/RegisterCollectionBase.cs b/MewtocolNet/Mewtocol/RegisterAttributes/RegisterCollectionBase.cs index 1a1a829..955a846 100644 --- a/MewtocolNet/Mewtocol/RegisterAttributes/RegisterCollectionBase.cs +++ b/MewtocolNet/Mewtocol/RegisterAttributes/RegisterCollectionBase.cs @@ -8,7 +8,8 @@ using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; -namespace MewtocolNet.RegisterAttributes { +namespace MewtocolNet.RegisterAttributes +{ /// /// A register collection base with full auto read and notification support built in @@ -34,6 +35,22 @@ namespace MewtocolNet.RegisterAttributes { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + /// + /// Use this on the setter method of a property to enable automatic property register writing + /// + public static void AutoSetter (object value, ref T privateField) { + + if(value is IRegister reg) { + + privateField = (T)reg.Value; + return; + + } + + privateField = (T)value; + + } + /// /// Gets called when the register collection base was linked to its parent mewtocol interface /// diff --git a/MewtocolNet/Mewtocol/Subregisters/BRegister.cs b/MewtocolNet/Mewtocol/Subregisters/BRegister.cs index d304890..92cb068 100644 --- a/MewtocolNet/Mewtocol/Subregisters/BRegister.cs +++ b/MewtocolNet/Mewtocol/Subregisters/BRegister.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Text; using MewtocolNet; @@ -7,17 +8,47 @@ namespace MewtocolNet.Registers { /// /// Defines a register containing a boolean /// - public class BRegister : Register { + public class BRegister : IRegister, INotifyPropertyChanged { + + /// + /// Gets called whenever the value was changed + /// + public event Action ValueChanged; + + /// + /// Triggers when a property on the register changes + /// + public event PropertyChangedEventHandler PropertyChanged; internal RegisterType RegType { get; private set; } - internal SpecialAddress SpecialAddress { get; private set; } - internal bool LastValue; + internal SpecialAddress SpecialAddress { get; private set; } + + internal Type collectionType; + + /// + /// The type of collection the register is in or null of added manually + /// + public Type CollectionType => collectionType; + + internal bool lastValue; /// /// The value of the register /// - public bool Value => LastValue; + public object Value => lastValue; + + internal string name; + /// + /// The register name or null of not defined + /// + public string Name => name; + + internal int memoryAdress; + /// + /// The registers memory adress if not a special register + /// + public int MemoryAddress => memoryAdress; /// /// Defines a register containing a number @@ -27,7 +58,11 @@ namespace MewtocolNet.Registers { /// Name of the register public BRegister (int _address, RegisterType _type = RegisterType.R, string _name = null) { - if (_address > 99999) throw new NotSupportedException("Memory adresses cant be greater than 99999"); + if (_address > 99999) throw new NotSupportedException("Memory addresses cant be greater than 99999"); + + if (_type != RegisterType.X && _type != RegisterType.Y && _type != RegisterType.R) + throw new NotSupportedException("The register type cant be numeric, use X, Y or R"); + memoryAdress = _address; name = _name; @@ -44,7 +79,10 @@ namespace MewtocolNet.Registers { public BRegister (SpecialAddress _address, RegisterType _type = RegisterType.R, string _name = null) { if (_address == SpecialAddress.None) - throw new NotSupportedException("Special adress cant be none"); + throw new NotSupportedException("Special address cant be none"); + + if (_type != RegisterType.X && _type != RegisterType.Y && _type != RegisterType.R) + throw new NotSupportedException("The register type cant be numeric, use X, Y or R"); SpecialAddress = _address; name = _name; @@ -53,15 +91,22 @@ namespace MewtocolNet.Registers { } + internal BRegister WithCollectionType(Type colType) { + + collectionType = colType; + return this; + + } + /// /// Builds the register area name /// - public override string BuildMewtocolIdent () { + public string BuildMewtocolQuery () { //build area code from register type StringBuilder asciistring = new StringBuilder(RegType.ToString()); if(SpecialAddress == SpecialAddress.None) { - asciistring.Append(MemoryAdress.ToString().PadLeft(4, '0')); + asciistring.Append(MemoryAddress.ToString().PadLeft(4, '0')); } else { asciistring.Append(SpecialAddress.ToString().PadLeft(4, '0')); } @@ -71,11 +116,52 @@ namespace MewtocolNet.Registers { } internal void SetValueFromPLC (bool val) { - LastValue = val; + + lastValue = val; TriggerChangedEvnt(this); TriggerNotifyChange(); + } + public string GetStartingMemoryArea() { + + if (SpecialAddress != SpecialAddress.None) + return SpecialAddress.ToString(); + + return MemoryAddress.ToString(); + + } + + public bool IsUsedBitwise() => false; + + public Type GetCollectionType() => CollectionType; + + public string GetValueString() => Value.ToString(); + + public void ClearValue() => SetValueFromPLC(false); + + public string GetRegisterString() => RegType.ToString(); + + public string GetCombinedName() => $"{(CollectionType != null ? $"{CollectionType.Name}." : "")}{Name ?? "Unnamed"}"; + + public string GetContainerName() => $"{(CollectionType != null ? $"{CollectionType.Name}" : "")}"; + + public string GetRegisterPLCName() { + + if (SpecialAddress != SpecialAddress.None) { + return $"{GetRegisterString()}{SpecialAddress}"; + } + + return $"{GetRegisterString()}{MemoryAddress}"; + + } + + internal void TriggerChangedEvnt(object changed) => ValueChanged?.Invoke(changed); + + public void TriggerNotifyChange() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); + + public override string ToString() => $"{GetRegisterPLCName()} - Value: {GetValueString()}"; + } } diff --git a/MewtocolNet/Mewtocol/Subregisters/NRegister.cs b/MewtocolNet/Mewtocol/Subregisters/NRegister.cs index 760d9c1..79cf631 100644 --- a/MewtocolNet/Mewtocol/Subregisters/NRegister.cs +++ b/MewtocolNet/Mewtocol/Subregisters/NRegister.cs @@ -1,18 +1,63 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Text; namespace MewtocolNet.Registers { + /// /// Defines a register containing a number /// /// The type of the numeric value - public class NRegister : Register { + public class NRegister : IRegister { - internal T LastValue; + /// + /// Gets called whenever the value was changed + /// + public event Action ValueChanged; + + /// + /// Triggers when a property on the register changes + /// + public event PropertyChangedEventHandler PropertyChanged; + + internal Type collectionType; + + /// + /// The type of collection the register is in or null of added manually + /// + public Type CollectionType => collectionType; + + internal T lastValue; /// /// The value of the register /// - public T Value => LastValue; + public object Value => lastValue; + + internal string name; + /// + /// The register name or null of not defined + /// + public string Name => name; + + internal int memoryAdress; + /// + /// The registers memory adress if not a special register + /// + public int MemoryAddress => memoryAdress; + + internal int memoryLength; + /// + /// The rgisters memory length + /// + public int MemoryLength => memoryLength; + + internal bool isUsedBitwise { get; set; } + + internal Type enumType { get; set; } /// /// Defines a register containing a number @@ -23,6 +68,7 @@ namespace MewtocolNet.Registers { if (_adress > 99999) throw new NotSupportedException("Memory adresses cant be greater than 99999"); + memoryAdress = _adress; name = _name; Type numType = typeof(T); @@ -71,15 +117,159 @@ namespace MewtocolNet.Registers { } + internal NRegister WithCollectionType (Type colType) { + + collectionType = colType; + return this; + + } + internal void SetValueFromPLC (object val) { - LastValue = (T)val; + + lastValue = (T)val; TriggerChangedEvnt(this); TriggerNotifyChange(); + } + public string GetStartingMemoryArea () => this.MemoryAddress.ToString(); + + public Type GetCollectionType() => CollectionType; + + public bool IsUsedBitwise() => isUsedBitwise; + + public string GetValueString() { + + //is number or bitwise + if(enumType == null) { + + return $"{Value}{(isUsedBitwise ? $" [{GetBitwise().ToBitString()}]" : "")}"; + + } + + //is enum + var dict = new Dictionary(); + + foreach (var name in Enum.GetNames(enumType)) { + + int enumKey = (int)Enum.Parse(enumType, name); + if (!dict.ContainsKey(enumKey)) { + dict.Add(enumKey, name); + } + + } + + if (enumType != null && Value is short shortVal) { + + if (dict.ContainsKey(shortVal)) { + + return $"{Value} ({dict[shortVal]})"; + + } else { + + return $"{Value} (Missing Enum)"; + + } + + } + + if (enumType != null && Value is int intVal) { + + if (dict.ContainsKey(intVal)) { + + return $"{Value} ({dict[intVal]})"; + + } else { + + return $"{Value} (Missing Enum)"; + + } + + } + + return Value.ToString(); + + } + + /// + /// Gets the register bitwise if its a 16 or 32 bit int + /// + /// A bitarray + public BitArray GetBitwise() { + + if (this is NRegister shortReg) { + + var bytes = BitConverter.GetBytes((short)Value); + BitArray bitAr = new BitArray(bytes); + return bitAr; + + } + + if (this is NRegister intReg) { + + var bytes = BitConverter.GetBytes((int)Value); + BitArray bitAr = new BitArray(bytes); + return bitAr; + + } + + return null; + + } + + public string BuildMewtocolQuery() { + + StringBuilder asciistring = new StringBuilder("D"); + asciistring.Append(MemoryAddress.ToString().PadLeft(5, '0')); + asciistring.Append((MemoryAddress + MemoryLength).ToString().PadLeft(5, '0')); + return asciistring.ToString(); + + } + + public string GetRegisterString() { + + if(Value is short) { + return "DT"; + } + + if (Value is ushort) { + return "DT"; + } + + if (Value is int) { + return "DDT"; + } + + if (Value is uint) { + return "DDT"; + } + + if (Value is float) { + return "DDT"; + } + + if (Value is TimeSpan) { + return "DDT"; + } + + throw new NotSupportedException("Numeric type is not supported"); + + } + + public string GetCombinedName() => $"{(CollectionType != null ? $"{CollectionType.Name}." : "")}{Name ?? "Unnamed"}"; + + public string GetContainerName() => $"{(CollectionType != null ? $"{CollectionType.Name}" : "")}"; + + public string GetRegisterPLCName() => $"{GetRegisterString()}{MemoryAddress}"; + + public void ClearValue() => SetValueFromPLC(default(T)); + + internal void TriggerChangedEvnt(object changed) => ValueChanged?.Invoke(changed); + + public void TriggerNotifyChange() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); + + public override string ToString() => $"{GetRegisterPLCName()} - Value: {GetValueString()}"; + } - - - } diff --git a/MewtocolNet/Mewtocol/Subregisters/NRegisterResult.cs b/MewtocolNet/Mewtocol/Subregisters/NRegisterResult.cs index 2296042..74f7214 100644 --- a/MewtocolNet/Mewtocol/Subregisters/NRegisterResult.cs +++ b/MewtocolNet/Mewtocol/Subregisters/NRegisterResult.cs @@ -21,12 +21,14 @@ namespace MewtocolNet.Registers { /// Trys to get the value of there is one /// public bool TryGetValue (out T value) { + if(Result.Success) { - value = Register.Value; + value = (T)Register.Value; return true; } value = default(T); return false; + } } diff --git a/MewtocolNet/Mewtocol/Subregisters/Register.cs b/MewtocolNet/Mewtocol/Subregisters/Register.cs deleted file mode 100644 index eea7ff1..0000000 --- a/MewtocolNet/Mewtocol/Subregisters/Register.cs +++ /dev/null @@ -1,388 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace MewtocolNet.Registers { - - /// - /// A class describing a register - /// - public abstract class Register : INotifyPropertyChanged { - - /// - /// Gets called whenever the value was changed - /// - public event Action ValueChanged; - /// - /// Triggers when a property on the register changes - /// - public event PropertyChangedEventHandler PropertyChanged; - - internal Type collectionType; - /// - /// The type of collection the register is in or null of added manually - /// - public Type CollectionType => collectionType; - - internal string name; - /// - /// The register name or null of not defined - /// - public string Name => name; - - internal int memoryAdress; - /// - /// The registers memory adress if not a special register - /// - public int MemoryAdress => memoryAdress; - - internal int memoryLength; - /// - /// The rgisters memory length - /// - public int MemoryLength => memoryLength; - - /// - /// The value of the register auto converted to a string - /// - public string StringValue => GetValueString(); - - /// - /// The name the register would have in the PLC - /// - public string RegisterPLCName => GetRegisterPLCName(); - - /// - /// The combined name with the holding register class type infront - /// - public string CombinedName => GetCombinedName(); - - /// - /// The name of the class that contains this register or empty if it was added manually - /// - public string ContainerName => GetContainerName(); - - internal bool isUsedBitwise { get; set; } - internal Type enumType { get; set; } - - internal Register () { - ValueChanged += (obj) => { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StringValue))); - }; - } - - /// - /// Builds the register area name - /// - public virtual string BuildMewtocolIdent() { - - StringBuilder asciistring = new StringBuilder("D"); - asciistring.Append(MemoryAdress.ToString().PadLeft(5, '0')); - asciistring.Append((MemoryAdress + MemoryLength).ToString().PadLeft(5, '0')); - return asciistring.ToString(); - - } - internal void TriggerChangedEvnt(object changed) { - ValueChanged?.Invoke(changed); - } - - internal void TriggerNotifyChange () { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); - } - - internal void ClearValue () { - - if (enumType != null && this is NRegister intEnumReg) { - intEnumReg.SetValueFromPLC((int)0); - } - if (this is NRegister shortReg) { - shortReg.SetValueFromPLC((short)0); - } - if (this is NRegister ushortReg) { - ushortReg.SetValueFromPLC((ushort)0); - } - if (this is NRegister intReg) { - intReg.SetValueFromPLC((int)0); - } - if (this is NRegister uintReg) { - uintReg.SetValueFromPLC((uint)0); - } - if (this is NRegister floatReg) { - floatReg.SetValueFromPLC((float)0); - } - if (this is NRegister tsReg) { - tsReg.SetValueFromPLC(TimeSpan.Zero); - } - if (this is BRegister boolReg) { - boolReg.SetValueFromPLC(false); - } - if (this is SRegister stringReg) { - stringReg.SetValueFromPLC(null); - } - - } - - /// - /// Gets the starting memory are either numeric or A,B,C,D etc for special areas like inputs - /// - /// - public string GetStartingMemoryArea () { - - if (this is BRegister bReg && bReg.SpecialAddress != SpecialAddress.None) { - return bReg.SpecialAddress.ToString(); - } - - return this.MemoryAdress.ToString(); - - } - - /// - /// Gets the current value in the adress as a string - /// - /// - public string GetValueString () { - - if (enumType != null && this is NRegister intEnumReg) { - - var dict = new Dictionary(); - - foreach (var name in Enum.GetNames(enumType)) { - int enumKey = (int)Enum.Parse(enumType, name); - if(!dict.ContainsKey(enumKey)) { - dict.Add(enumKey, name); - } - } - - if(dict.ContainsKey(intEnumReg.Value)) { - return $"{intEnumReg.Value} ({dict[intEnumReg.Value]})"; - } else { - return $"{intEnumReg.Value} (Missing Enum)"; - } - - } - if (this is NRegister shortReg) { - return $"{shortReg.Value}{(isUsedBitwise ? $" [{shortReg.GetBitwise().ToBitString()}]" : "")}"; - } - if (this is NRegister ushortReg) { - return ushortReg.Value.ToString(); - } - if (this is NRegister intReg) { - return $"{intReg.Value}{(isUsedBitwise ? $" [{intReg.GetBitwise().ToBitString()}]" : "")}"; - } - if (this is NRegister uintReg) { - return uintReg.Value.ToString(); - } - if (this is NRegister floatReg) { - return floatReg.Value.ToString(); - } - if (this is NRegister tsReg) { - return tsReg.Value.ToString(); - } - if (this is BRegister boolReg) { - return boolReg.Value.ToString(); - } - if (this is SRegister stringReg) { - return stringReg.Value ?? ""; - } - - return "Type of the register is not supported."; - - } - - /// - /// Gets the register bitwise if its a 16 or 32 bit int - /// - /// A bitarray - public BitArray GetBitwise () { - - if (this is NRegister shortReg) { - - var bytes = BitConverter.GetBytes(shortReg.Value); - BitArray bitAr = new BitArray(bytes); - return bitAr; - - } - - if (this is NRegister intReg) { - - var bytes = BitConverter.GetBytes(intReg.Value); - BitArray bitAr = new BitArray(bytes); - return bitAr; - - } - - return null; - - } - - /// - /// Gets the register dataarea string DT for 16bit and DDT for 32 bit types - /// - public string GetRegisterString () { - - if (this is NRegister shortReg) { - return "DT"; - } - if (this is NRegister ushortReg) { - return "DT"; - } - if (this is NRegister intReg) { - return "DDT"; - } - if (this is NRegister uintReg) { - return "DDT"; - } - if (this is NRegister floatReg) { - return "DDT"; - } - if (this is NRegister tsReg) { - return "DDT"; - } - if (this is BRegister boolReg) { - return boolReg.RegType.ToString(); - } - if (this is SRegister stringReg) { - return "DT"; - - } - - return "Type of the register is not supported."; - - } - - /// - /// Builds a register from a given register string like DT100 / XA / Y1 - /// - /// The input string to parse - /// A built register - public static Register FromString (string regString, string name = null) { - - var match = Regex.Match(regString, @"(X|Y|R)([A-F]|[0-9_.-]{1,5})"); - - if (match != null && match.Success) { - - var typeGroup = match.Groups[1].Value; - var areaGroup = match.Groups[2].Value; - - bool isBool = false; - var parsedRegType = RegisterType.R; - if (new string[] { "X", "Y", "R" }.Contains(typeGroup)) { - switch (typeGroup) { - case "X": - parsedRegType = RegisterType.X; - isBool = true; - break; - case "Y": - parsedRegType = RegisterType.Y; - isBool = true; - break; - case "R": - parsedRegType = RegisterType.R; - isBool = true; - break; - } - } - - if(!isBool) { - throw new NotSupportedException($"Register with value {regString} is not of type bool"); - } - - if (int.TryParse(areaGroup, out var parsedNum) && isBool) { - - return new BRegister(parsedNum, parsedRegType, name); - - } else if(Enum.TryParse(areaGroup, out var parsedSpecial) && isBool) { - - return new BRegister(parsedSpecial, parsedRegType, name); - - } - } - - throw new NotSupportedException($"Register with value {regString} is not supported"); - - } - - public static NRegister FromString (string regString, string name = null) { - - var match = Regex.Match(regString, @"(DT|DDT)([0-9_.-]{1,5})"); - - if (match != null && match.Success) { - - var typeGroup = match.Groups[1].Value; - var areaGroup = match.Groups[2].Value; - - bool isTypeDoubleSize = false; - bool isSupportedNumericFormat = false; - - if(typeGroup == "") - - switch (typeGroup) { - case "DT": - isSupportedNumericFormat = true; - break; - case "DDT": - isTypeDoubleSize = true; - isSupportedNumericFormat = true; - break; - } - - if(typeof(T).IsDoubleNumericRegisterType() != isTypeDoubleSize) { - throw new NotSupportedException($"Input register type was {typeGroup}, the cast type was not of the same size"); - } - - if (int.TryParse(areaGroup, out var parsedNum) && typeof(T).IsNumericSupportedType() && isSupportedNumericFormat ) { - - return new NRegister(parsedNum, name); - - } - - } - - throw new NotSupportedException($"Register with value {regString} is not supported"); - - } - - public static SRegister FromString (string regString, int reserved, string name = null) { - - var match = Regex.Match(regString, @"(DT)([0-9_.-]{1,5})"); - - if (match != null && match.Success) { - - - } - - throw new NotSupportedException($"Register with value {regString} is not supported"); - - } - - internal string GetCombinedName () { - - return $"{(CollectionType != null ? $"{CollectionType.Name}." : "")}{Name ?? "Unnamed"}"; - - } - - internal string GetContainerName () { - - return $"{(CollectionType != null ? $"{CollectionType.Name}" : "")}"; - - } - - internal string GetRegisterPLCName () { - - if (this is BRegister bReg && bReg.SpecialAddress != SpecialAddress.None) { - return $"{GetRegisterString()}{bReg.SpecialAddress}"; - } - - return $"{GetRegisterString()}{MemoryAdress}"; - - } - - } - -} diff --git a/MewtocolNet/Mewtocol/Subregisters/SRegister.cs b/MewtocolNet/Mewtocol/Subregisters/SRegister.cs index 164ae91..49c0d6e 100644 --- a/MewtocolNet/Mewtocol/Subregisters/SRegister.cs +++ b/MewtocolNet/Mewtocol/Subregisters/SRegister.cs @@ -1,18 +1,54 @@ using System; +using System.ComponentModel; using System.Text; namespace MewtocolNet.Registers { /// /// Defines a register containing a string /// - public class SRegister : Register { - - private string lastVal = ""; + public class SRegister : IRegister { /// - /// The current value of the register + /// Gets called whenever the value was changed /// - public string Value => lastVal; + public event Action ValueChanged; + + /// + /// Triggers when a property on the register changes + /// + public event PropertyChangedEventHandler PropertyChanged; + + internal Type collectionType; + + /// + /// The type of collection the register is in or null of added manually + /// + public Type CollectionType => collectionType; + + internal string lastValue; + + /// + /// The value of the register + /// + public object Value => lastValue; + + internal string name; + /// + /// The register name or null of not defined + /// + public string Name => name; + + internal int memoryAdress; + /// + /// The registers memory adress if not a special register + /// + public int MemoryAddress => memoryAdress; + + internal int memoryLength; + /// + /// The registers memory length + /// + public int MemoryLength => memoryLength; internal short ReservedSize { get; set; } @@ -35,15 +71,22 @@ namespace MewtocolNet.Registers { memoryLength = (int)Math.Round(wordsize + 1); } + internal SRegister WithCollectionType(Type colType) { + + collectionType = colType; + return this; + + } + /// /// Builds the register identifier for the mewotocol protocol /// - public override string BuildMewtocolIdent() { + public string BuildMewtocolQuery() { StringBuilder asciistring = new StringBuilder("D"); - asciistring.Append(MemoryAdress.ToString().PadLeft(5, '0')); - asciistring.Append((MemoryAdress + MemoryLength).ToString().PadLeft(5, '0')); + asciistring.Append(MemoryAddress.ToString().PadLeft(5, '0')); + asciistring.Append((MemoryAddress + MemoryLength).ToString().PadLeft(5, '0')); return asciistring.ToString(); } @@ -55,18 +98,45 @@ namespace MewtocolNet.Registers { StringBuilder asciistring = new StringBuilder("D"); - asciistring.Append(MemoryAdress.ToString().PadLeft(5, '0')); - asciistring.Append((MemoryAdress + overwriteWordLength - 1).ToString().PadLeft(5, '0')); + asciistring.Append(MemoryAddress.ToString().PadLeft(5, '0')); + asciistring.Append((MemoryAddress + overwriteWordLength - 1).ToString().PadLeft(5, '0')); return asciistring.ToString(); } + public Type GetCollectionType() => CollectionType; + + public bool IsUsedBitwise() => false; + internal void SetValueFromPLC (string val) { - lastVal = val; + + lastValue = val; + TriggerChangedEvnt(this); TriggerNotifyChange(); + } + public string GetStartingMemoryArea() => this.MemoryAddress.ToString(); + + public string GetValueString() => Value?.ToString() ?? ""; + + public string GetRegisterString() => "DT"; + + public string GetCombinedName() => $"{(CollectionType != null ? $"{CollectionType.Name}." : "")}{Name ?? "Unnamed"}"; + + public string GetContainerName() => $"{(CollectionType != null ? $"{CollectionType.Name}" : "")}"; + + public string GetRegisterPLCName() => $"{GetRegisterString()}{MemoryAddress}"; + + public void ClearValue() => SetValueFromPLC(null); + + internal void TriggerChangedEvnt(object changed) => ValueChanged?.Invoke(changed); + + public void TriggerNotifyChange() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); + + public override string ToString () => $"{GetRegisterPLCName()} - Value: {GetValueString()}"; + } } diff --git a/MewtocolNet/MewtocolNet.csproj b/MewtocolNet/MewtocolNet.csproj index d0a3792..c226a79 100644 --- a/MewtocolNet/MewtocolNet.csproj +++ b/MewtocolNet/MewtocolNet.csproj @@ -2,7 +2,7 @@ netstandard2.0 Mewtocol.NET - 0.6.2 + 0.7.0 Felix Weiss Womed true @@ -18,4 +18,9 @@ ..\Builds\MewtocolNet.xml ..\Builds + + + <_Parameter1>MewtocolTests + + diff --git a/MewtocolTests/AutomatedPropertyRegisters.cs b/MewtocolTests/AutomatedPropertyRegisters.cs new file mode 100644 index 0000000..30e902d --- /dev/null +++ b/MewtocolTests/AutomatedPropertyRegisters.cs @@ -0,0 +1,306 @@ +using Xunit; + +using MewtocolNet; +using MewtocolNet.Registers; +using System.Diagnostics; +using Xunit.Abstractions; +using System.Collections; +using MewtocolNet.RegisterAttributes; +using Microsoft.Win32; + +namespace MewtocolTests { + + public class AutomatedPropertyRegisters { + + private readonly ITestOutputHelper output; + + public AutomatedPropertyRegisters(ITestOutputHelper output) { + this.output = output; + } + + public class TestRegisterCollection : RegisterCollectionBase { + + //corresponds to a R100 boolean register in the PLC + [Register(1000, RegisterType.R)] + public bool TestBool1 { get; private set; } + + //corresponds to a XD input of the PLC + [Register(RegisterType.X, SpecialAddress.D)] + public bool TestBoolInputXD { get; private set; } + + //corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4]) + //[Register(1101, 4)] + //public string TestString1 { get; private set; } + + //corresponds to a DT7000 16 bit int register in the PLC + [Register(899)] + public short TestInt16 { get; private set; } + + [Register(342)] + public ushort TestUInt16 { get; private set; } + + //corresponds to a DTD7001 - DTD7002 32 bit int register in the PLC + [Register(7001)] + public int TestInt32 { get; private set; } + + [Register(765)] + public uint TestUInt32 { get; private set; } + + //corresponds to a DTD7001 - DTD7002 32 bit float register in the PLC (REAL) + [Register(7003)] + public float TestFloat32 { get; private set; } + + //corresponds to a DT7005 - DT7009 string register in the PLC with (STRING[5]) + [Register(7005, 5)] + public string TestString2 { get; private set; } + + //corresponds to a DT7010 as a 16bit word/int and parses the word as single bits + [Register(7010)] + public BitArray TestBitRegister { get; private set; } + + [Register(8010, BitCount.B32)] + public BitArray TestBitRegister32 { get; private set; } + + //corresponds to a DT1204 as a 16bit word/int takes the bit at index 9 and writes it back as a boolean + [Register(1204, 9, BitCount.B16)] + public bool BitValue { get; private set; } + + [Register(1204, 5, BitCount.B16)] + public bool FillTest { get; private set; } + + //corresponds to a DT7012 - DT7013 as a 32bit time value that gets parsed as a timespan (TIME) + //the smallest value to communicate to the PLC is 10ms + [Register(7012)] + public TimeSpan TestTime { get; private set; } + + public enum CurrentState { + Undefined = 0, + State1 = 1, + State2 = 2, + //State3 = 3, + State4 = 4, + State5 = 5, + StateBetween = 100, + State6 = 6, + State7 = 7, + } + + [Register(50)] + public CurrentState TestEnum16 { get; private set; } + + [Register(51, BitCount.B32)] + public CurrentState TestEnum32 { get; private set; } + + } + + private void TestBasicGeneration(IRegister reg, string propName, object expectValue, int expectAddr, string expectPlcName) { + + Assert.NotNull(reg); + Assert.Equal(propName, reg.Name); + Assert.Equal(expectValue, reg.Value); + + Assert.Equal(expectAddr, reg.MemoryAddress); + Assert.Equal(expectPlcName, reg.GetRegisterPLCName()); + + output.WriteLine(reg.ToString()); + + } + + //actual tests + + [Fact(DisplayName = "Boolean R generation")] + public void BooleanGen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestBool1)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestBool1), false, 1000, "R1000"); + + } + + [Fact(DisplayName = "Boolean input XD generation")] + public void BooleanInputGen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestBoolInputXD)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestBoolInputXD), false, 0, "XD"); + + } + + [Fact(DisplayName = "Int16 generation")] + public void Int16Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestInt16)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestInt16), (short)0, 899, "DT899"); + + } + + [Fact(DisplayName = "UInt16 generation")] + public void UInt16Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestUInt16)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestUInt16), (ushort)0, 342, "DT342"); + + } + + [Fact(DisplayName = "Int32 generation")] + public void Int32Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestInt32)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestInt32), (int)0, 7001, "DDT7001"); + + } + + [Fact(DisplayName = "UInt32 generation")] + public void UInt32Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestUInt32)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestUInt32), (uint)0, 765, "DDT765"); + + } + + [Fact(DisplayName = "Float32 generation")] + public void Float32Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestFloat32)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestFloat32), (float)0, 7003, "DDT7003"); + + } + + [Fact(DisplayName = "String generation")] + public void StringGen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestString2)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestString2), null!, 7005, "DT7005"); + + Assert.Equal(5, ((SRegister)register).ReservedSize); + Assert.Equal(4, ((SRegister)register).MemoryLength); + + } + + [Fact(DisplayName = "BitArray 16bit generation")] + public void BitArray16Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister($"Auto_Bitwise_DT7010"); + + //test generic properties + TestBasicGeneration(register, "Auto_Bitwise_DT7010", (short)0, 7010, "DT7010"); + + Assert.True(((NRegister)register).isUsedBitwise); + Assert.Equal(0, ((NRegister)register).MemoryLength); + + } + + [Fact(DisplayName = "BitArray 32bit generation")] + public void BitArray32Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister($"Auto_Bitwise_DDT8010"); + + //test generic properties + TestBasicGeneration(register, "Auto_Bitwise_DDT8010", (int)0, 8010, "DDT8010"); + + Assert.True(((NRegister)register).isUsedBitwise); + Assert.Equal(1, ((NRegister)register).MemoryLength); + + } + + [Fact(DisplayName = "BitArray single bool generation")] + public void BitArraySingleBool16Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister($"Auto_Bitwise_DT1204"); + + //test generic properties + TestBasicGeneration(register, "Auto_Bitwise_DT1204", (short)0, 1204, "DT1204"); + + Assert.True(((NRegister)register).isUsedBitwise); + + } + + [Fact(DisplayName = "TimeSpan generation")] + public void TimespanGen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestTime)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestTime), TimeSpan.Zero, 7012, "DDT7012"); + + } + + [Fact(DisplayName = "Enum16 generation")] + public void Enum16Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestEnum16)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestEnum16), (short)TestRegisterCollection.CurrentState.Undefined, 50, "DT50"); + + } + + [Fact(DisplayName = "Enum32 generation")] + public void Enum32Gen () { + + var interf = new MewtocolInterface("192.168.0.1"); + interf.WithRegisterCollection(new TestRegisterCollection()).WithPoller(); + + var register = interf.GetRegister(nameof(TestRegisterCollection.TestEnum32)); + + //test generic properties + TestBasicGeneration(register, nameof(TestRegisterCollection.TestEnum32), (int)TestRegisterCollection.CurrentState.Undefined, 51, "DDT51"); + + } + + } + +} \ No newline at end of file diff --git a/MewtocolTests/TestComProtocol.cs b/MewtocolTests/TestComProtocol.cs deleted file mode 100644 index ebe07c0..0000000 --- a/MewtocolTests/TestComProtocol.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Xunit; - -using MewtocolNet; -using MewtocolNet.Registers; -using System.Diagnostics; -using Xunit.Abstractions; -using System.Collections; - -namespace MewtocolTests { - - public class TestComProtocol { - - private readonly ITestOutputHelper output; - - public TestComProtocol (ITestOutputHelper output) { - this.output = output; - } - - [Fact(DisplayName = "Numeric register protocol identifiers")] - public void NumericRegisterMewtocolIdentifiers () { - - List registers = new List { - new NRegister(50), - new NRegister(50), - new NRegister(50), - new NRegister(50), - new NRegister(50), - }; - - List expcectedIdents = new List { - "D0005000050", //single word register - "D0005000050", //single word register - "D0005000051", //double word register - "D0005000051", //double word register - "D0005000051", //double word register - "D0005000051", //double word register - }; - - //test mewtocol idents - for (int i = 0; i < registers.Count; i++) { - - Register? reg = registers[i]; - string expect = expcectedIdents[i]; - - Assert.Equal(expect, reg.BuildMewtocolIdent()); - - } - - } - - } - -} \ No newline at end of file diff --git a/MewtocolTests/TestClient.cs b/MewtocolTests/TestLivePLC.cs similarity index 96% rename from MewtocolTests/TestClient.cs rename to MewtocolTests/TestLivePLC.cs index 3abdde4..eea5f52 100644 --- a/MewtocolTests/TestClient.cs +++ b/MewtocolTests/TestLivePLC.cs @@ -10,7 +10,7 @@ using Xunit.Abstractions; namespace MewtocolTests { - public class TestClient { + public class TestLivePLC { private readonly ITestOutputHelper output; @@ -37,7 +37,7 @@ namespace MewtocolTests { }; - public TestClient (ITestOutputHelper output) { + public TestLivePLC (ITestOutputHelper output) { this.output = output; diff --git a/MewtocolTests/TestRegisterInterface.cs b/MewtocolTests/TestRegisterInterface.cs new file mode 100644 index 0000000..f3acba8 --- /dev/null +++ b/MewtocolTests/TestRegisterInterface.cs @@ -0,0 +1,164 @@ +using Xunit; + +using MewtocolNet; +using MewtocolNet.Registers; +using Xunit.Abstractions; + +namespace MewtocolTests { + + public class TestRegisterInterface { + + private readonly ITestOutputHelper output; + + public TestRegisterInterface (ITestOutputHelper output) { + this.output = output; + } + + [Fact(DisplayName = "Numeric mewtocol query building")] + public void NumericRegisterMewtocolIdentifiers () { + + List registers = new List { + new NRegister(50, _name: null), + new NRegister(50, _name: null), + new NRegister(50, _name : null), + new NRegister(50, _name : null), + new NRegister(50, _name : null), + new NRegister(50, _name : null), + }; + + List expcectedIdents = new List { + "D0005000050", //single word register + "D0005000050", //single word register + "D0005000051", //double word register + "D0005000051", //double word register + "D0005000051", //double word register + "D0005000051", //double word register + }; + + //test mewtocol idents + for (int i = 0; i < registers.Count; i++) { + + IRegister? reg = registers[i]; + string expect = expcectedIdents[i]; + + Assert.Equal(expect, reg.BuildMewtocolQuery()); + + } + + } + + [Fact(DisplayName = "PLC register naming convention test")] + public void PLCRegisterIdentifiers () { + + List registers = new List { + //numeric ones + new NRegister(50, _name: null), + new NRegister(60, _name : null), + new NRegister(70, _name : null), + new NRegister(80, _name : null), + new NRegister(90, _name : null), + new NRegister(100, _name : null), + //boolean + new BRegister(100), + new BRegister(5, RegisterType.X), + new BRegister(SpecialAddress.A, RegisterType.X), + //string + new SRegister(999, 5), + }; + + List expcectedIdents = new List { + "DT50", + "DT60", + "DDT70", + "DDT80", + "DDT90", + "DDT100", + "R100", + "X5", + "XA", + "DT999" + }; + + //test mewtocol idents + for (int i = 0; i < registers.Count; i++) { + + IRegister? reg = registers[i]; + string expect = expcectedIdents[i]; + + Assert.Equal(expect, reg.GetRegisterPLCName()); + + } + + } + + [Fact(DisplayName = "Non allowed (Overflow address)")] + public void OverFlowRegisterAddress () { + + var ex = Assert.Throws(() => { + + new NRegister(100000, _name: null); + + }); + + output.WriteLine(ex.Message.ToString()); + + var ex1 = Assert.Throws(() => { + + new BRegister(100000); + + }); + + output.WriteLine(ex1.Message.ToString()); + + var ex2 = Assert.Throws(() => { + + new SRegister(100000, 5); + + }); + + output.WriteLine(ex2.Message.ToString()); + + } + + [Fact(DisplayName = "Non allowed (Wrong data type)")] + public void WrongDataTypeRegister () { + + var ex = Assert.Throws(() => { + + new NRegister(100, _name: null); + + }); + + output.WriteLine(ex.Message.ToString()); + + } + + [Fact(DisplayName = "Non allowed (Wrong bool type address)")] + public void WrongDataTypeRegisterBool1 () { + + var ex = Assert.Throws(() => { + + new BRegister(100, RegisterType.DDT_int); + + }); + + output.WriteLine(ex.Message.ToString()); + + } + + [Fact(DisplayName = "Non allowed (Wrong bool special address)")] + public void WrongDataTypeRegisterBool2 () { + + var ex = Assert.Throws(() => { + + new BRegister(SpecialAddress.None, RegisterType.X); + + }); + + output.WriteLine(ex.Message.ToString()); + + } + + } + +} \ No newline at end of file diff --git a/PLC_Test/test_c30_fpx_h.ini b/PLC_Test/test_c30_fpx_h.ini new file mode 100644 index 0000000000000000000000000000000000000000..e810e5053b49cd35fcbb9a00a3778ff8e0125482 GIT binary patch literal 832 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

%$CpR7@D2g_=tFMTD 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

8h9Yx>3@z(emFS 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 literal 0 HcmV?d00001 diff --git a/PLC_Test/test_c30_fpx_h.xml b/PLC_Test/test_c30_fpx_h.xml new file mode 100644 index 0000000..4109899 --- /dev/null +++ b/PLC_Test/test_c30_fpx_h.xml @@ -0,0 +1,11 @@ + + + + + + + + +

+ +