From bf4550655e3009044d13f7cc91ef37d405073a6e Mon Sep 17 00:00:00 2001 From: Michael Croes Date: Wed, 11 Jul 2018 10:21:49 +0200 Subject: [PATCH] Add support for creating DataItem from string (#149) * Refactor PLCAddress - Change fields into properties - Apply PascalCase naming to all properties - Make Parse public static with out parameters * Support creating DataItem from string * Rename PlcAddress.Address to StartByte --- S7.Net/PLCAddress.cs | 197 ++++++++++++++++++++++++++++++++++++++ S7.Net/PLCHelpers.cs | 161 ------------------------------- S7.Net/PlcAsynchronous.cs | 4 +- S7.Net/PlcSynchronous.cs | 4 +- S7.Net/Types/DataItem.cs | 41 +++++++- 5 files changed, 241 insertions(+), 166 deletions(-) create mode 100644 S7.Net/PLCAddress.cs diff --git a/S7.Net/PLCAddress.cs b/S7.Net/PLCAddress.cs new file mode 100644 index 0000000..e78015f --- /dev/null +++ b/S7.Net/PLCAddress.cs @@ -0,0 +1,197 @@ +namespace S7.Net +{ + internal class PLCAddress + { + private DataType dataType; + private int dbNumber; + private int startByte; + private int bitNumber; + private VarType varType; + + public DataType DataType + { + get => dataType; + set => dataType = value; + } + + public int DbNumber + { + get => dbNumber; + set => dbNumber = value; + } + + public int StartByte + { + get => startByte; + set => startByte = value; + } + + public int BitNumber + { + get => bitNumber; + set => bitNumber = value; + } + + public VarType VarType + { + get => varType; + set => varType = value; + } + + public PLCAddress(string address) + { + Parse(address, out dataType, out dbNumber, out varType, out startByte, out bitNumber); + } + + public static void Parse(string input, out DataType dataType, out int dbNumber, out VarType varType, out int address, out int bitNumber) + { + bitNumber = -1; + dbNumber = 0; + + switch (input.Substring(0, 2)) + { + case "DB": + string[] strings = input.Split(new char[] { '.' }); + if (strings.Length < 2) + throw new InvalidAddressException("To few periods for DB address"); + + dataType = DataType.DataBlock; + dbNumber = int.Parse(strings[0].Substring(2)); + address = int.Parse(strings[1].Substring(3)); + + string dbType = strings[1].Substring(0, 3); + switch (dbType) + { + case "DBB": + varType = VarType.Byte; + return; + case "DBW": + varType = VarType.Word; + return; + case "DBD": + varType = VarType.DWord; + return; + case "DBX": + bitNumber = int.Parse(strings[2]); + if (bitNumber > 7) + throw new InvalidAddressException("Bit can only be 0-7"); + varType = VarType.Bit; + return; + default: + throw new InvalidAddressException(); + } + case "EB": + // Input byte + dataType = DataType.Input; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.Byte; + return; + case "EW": + // Input word + dataType = DataType.Input; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.Word; + return; + case "ED": + // Input double-word + dataType = DataType.Input; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.DWord; + return; + case "AB": + // Output byte + dataType = DataType.Output; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.Byte; + return; + case "AW": + // Output word + dataType = DataType.Output; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.Word; + return; + case "AD": + // Output double-word + dataType = DataType.Output; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.DWord; + return; + case "MB": + // Memory byte + dataType = DataType.Memory; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.Byte; + return; + case "MW": + // Memory word + dataType = DataType.Memory; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.Word; + return; + case "MD": + // Memory double-word + dataType = DataType.Memory; + dbNumber = 0; + address = int.Parse(input.Substring(2)); + varType = VarType.DWord; + return; + default: + switch (input.Substring(0, 1)) + { + case "E": + case "I": + // Input + dataType = DataType.Input; + varType = VarType.Bit; + break; + case "A": + case "O": + // Output + dataType = DataType.Output; + varType = VarType.Bit; + break; + case "M": + // Memory + dataType = DataType.Memory; + varType = VarType.Byte; + break; + case "T": + // Timer + dataType = DataType.Timer; + dbNumber = 0; + address = int.Parse(input.Substring(1)); + varType = VarType.Timer; + return; + case "Z": + case "C": + // Counter + dataType = DataType.Timer; + dbNumber = 0; + address = int.Parse(input.Substring(1)); + varType = VarType.Counter; + return; + default: + throw new InvalidAddressException(string.Format("{0} is not a valid address", input.Substring(0, 1))); + } + + string txt2 = input.Substring(1); + if (txt2.IndexOf(".") == -1) + throw new InvalidAddressException("To few periods for DB address"); + + address = int.Parse(txt2.Substring(0, txt2.IndexOf("."))); + bitNumber = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1)); + if (bitNumber > 7) + throw new InvalidAddressException("Bit can only be 0-7"); + return; + } + } + } +} \ No newline at end of file diff --git a/S7.Net/PLCHelpers.cs b/S7.Net/PLCHelpers.cs index 6f772a7..30aaaf0 100644 --- a/S7.Net/PLCHelpers.cs +++ b/S7.Net/PLCHelpers.cs @@ -5,167 +5,6 @@ using System.Linq; namespace S7.Net { - - internal class PLCAddress - { - public DataType dataType; - public int DBNumber; - public int Address; - public int BitNumber; - public VarType varType; - - public PLCAddress(string address) - { - ParseString(address); - } - - private void ParseString(string address) - { - BitNumber = -1; - switch (address.Substring(0, 2)) - { - case "DB": - string[] strings = address.Split(new char[] { '.' }); - if (strings.Length < 2) - throw new InvalidAddressException("To few periods for DB address"); - - dataType = DataType.DataBlock; - DBNumber = int.Parse(strings[0].Substring(2)); - Address = int.Parse(strings[1].Substring(3)); - - string dbType = strings[1].Substring(0, 3); - switch (dbType) - { - case "DBB": - varType = VarType.Byte; - return; - case "DBW": - varType = VarType.Word; - return; - case "DBD": - varType = VarType.DWord; - return; - case "DBX": - BitNumber = int.Parse(strings[2]); - if (BitNumber > 7) - throw new InvalidAddressException("Bit can only be 0-7"); - varType = VarType.Bit; - return; - default: - throw new InvalidAddressException(); - } - case "EB": - // Input byte - dataType = DataType.Input; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.Byte; - return; - case "EW": - // Input word - dataType = DataType.Input; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.Word; - return; - case "ED": - // Input double-word - dataType = DataType.Input; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.DWord; - return; - case "AB": - // Output byte - dataType = DataType.Output; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.Byte; - return; - case "AW": - // Output word - dataType = DataType.Output; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.Word; - return; - case "AD": - // Output double-word - dataType = DataType.Output; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.DWord; - return; - case "MB": - // Memory byte - dataType = DataType.Memory; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.Byte; - return; - case "MW": - // Memory word - dataType = DataType.Memory; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.Word; - return; - case "MD": - // Memory double-word - dataType = DataType.Memory; - DBNumber = 0; - Address = int.Parse(address.Substring(2)); - varType = VarType.DWord; - return; - default: - switch (address.Substring(0, 1)) - { - case "E": - case "I": - // Input - dataType = DataType.Input; - break; - case "A": - case "O": - // Output - dataType = DataType.Output; - break; - case "M": - // Memory - dataType = DataType.Memory; - break; - case "T": - // Timer - dataType = DataType.Timer; - DBNumber = 0; - Address = int.Parse(address.Substring(1)); - varType = VarType.Timer; - return; - case "Z": - case "C": - // Counter - dataType = DataType.Timer; - DBNumber = 0; - Address = int.Parse(address.Substring(1)); - varType = VarType.Counter; - return; - default: - throw new InvalidAddressException(string.Format("{0} is not a valid address", address.Substring(0, 1))); - } - - string txt2 = address.Substring(1); - if (txt2.IndexOf(".") == -1) - throw new InvalidAddressException("To few periods for DB address"); - - Address = int.Parse(txt2.Substring(0, txt2.IndexOf("."))); - BitNumber = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1)); - if (BitNumber > 7) - throw new InvalidAddressException("Bit can only be 0-7"); - return; - } - } - } - public partial class Plc { /// diff --git a/S7.Net/PlcAsynchronous.cs b/S7.Net/PlcAsynchronous.cs index cde83b8..38cb7c6 100644 --- a/S7.Net/PlcAsynchronous.cs +++ b/S7.Net/PlcAsynchronous.cs @@ -99,7 +99,7 @@ namespace S7.Net public async Task ReadAsync(string variable) { var adr = new PLCAddress(variable); - return await ReadAsync(adr.dataType, adr.DBNumber, adr.Address, adr.varType, 1, (byte)adr.BitNumber); + return await ReadAsync(adr.DataType, adr.DbNumber, adr.StartByte, adr.VarType, 1, (byte)adr.BitNumber); } /// @@ -345,7 +345,7 @@ namespace S7.Net public async Task WriteAsync(string variable, object value) { var adr = new PLCAddress(variable); - await WriteAsync(adr.dataType, adr.DBNumber, adr.Address, value, adr.BitNumber); + await WriteAsync(adr.DataType, adr.DbNumber, adr.StartByte, value, adr.BitNumber); } /// diff --git a/S7.Net/PlcSynchronous.cs b/S7.Net/PlcSynchronous.cs index 35847a5..dd7030c 100644 --- a/S7.Net/PlcSynchronous.cs +++ b/S7.Net/PlcSynchronous.cs @@ -119,7 +119,7 @@ namespace S7.Net public object Read(string variable) { var adr = new PLCAddress(variable); - return Read(adr.dataType, adr.DBNumber, adr.Address, adr.varType, 1, (byte)adr.BitNumber); + return Read(adr.DataType, adr.DbNumber, adr.StartByte, adr.VarType, 1, (byte)adr.BitNumber); } /// @@ -309,7 +309,7 @@ namespace S7.Net public void Write(string variable, object value) { var adr = new PLCAddress(variable); - Write(adr.dataType, adr.DBNumber, adr.Address, value, adr.BitNumber); + Write(adr.DataType, adr.DbNumber, adr.StartByte, value, adr.BitNumber); } /// diff --git a/S7.Net/Types/DataItem.cs b/S7.Net/Types/DataItem.cs index 5f48586..c40a604 100644 --- a/S7.Net/Types/DataItem.cs +++ b/S7.Net/Types/DataItem.cs @@ -1,4 +1,6 @@ -namespace S7.Net.Types +using System; + +namespace S7.Net.Types { /// /// Create an instance of a memory block that can be read by using ReadMultipleVars @@ -48,5 +50,42 @@ VarType = VarType.Byte; Count = 1; } + + /// + /// Create an instance of from the supplied address. + /// + /// The address to create the DataItem for. + /// A new instance with properties parsed from . + /// The property is not parsed from the address. + public static DataItem FromAddress(string address) + { + PLCAddress.Parse(address, out var dataType, out var dbNumber, out var varType, out var startByte, + out var bitNumber); + + return new DataItem + { + DataType = dataType, + DB = dbNumber, + VarType = varType, + StartByteAdr = startByte, + BitAdr = (byte) bitNumber + }; + } + + /// + /// Create an instance of from the supplied address and value. + /// + /// The address to create the DataItem for. + /// The value to be applied to the DataItem. + /// A new instance with properties parsed from and the supplied value set. + public static DataItem FromAddressAndValue(string address, T value) + { + var dataItem = FromAddress(address); + dataItem.Value = value; + + if (typeof(T).IsArray) dataItem.Count = ((Array) dataItem.Value).Length; + + return dataItem; + } } }