diff --git a/LibNoDaveConnectionLibrary/DataTypes/AWL/Step7V5/S7ConvertingOptions.cs b/LibNoDaveConnectionLibrary/DataTypes/AWL/Step7V5/S7ConvertingOptions.cs index 54c4ac3e..b1baf765 100644 --- a/LibNoDaveConnectionLibrary/DataTypes/AWL/Step7V5/S7ConvertingOptions.cs +++ b/LibNoDaveConnectionLibrary/DataTypes/AWL/Step7V5/S7ConvertingOptions.cs @@ -53,12 +53,16 @@ public S7ConvertingOptions(MnemonicLanguage Mnemonic) this.UseInFCStoredFCsForCalls = true; //todo implement the reading of them in the step7 project this.UseComments = true; this.UseFBDeclarationForInstanceDB = true; //Default to Simatic Mamager Behavior + this.UseDBActualValues = false; + this.ExpandArrays = false; } public bool UseComments { get; set; } public MnemonicLanguage Mnemonic { get; set; } public bool CombineDBOpenAndDBAccess { get; set; } public bool ReplaceDBAccessesWithSymbolNames { get; set; } + public bool UseDBActualValues { get; set; } + public bool ExpandArrays { get; set; } public bool ReplaceLokalDataAddressesWithSymbolNames { get; set; } public bool ReplaceDIAccessesWithSymbolNames { get; set; } diff --git a/LibNoDaveConnectionLibrary/DataTypes/Blocks/TiaAndSTep7DataBlockRow.cs b/LibNoDaveConnectionLibrary/DataTypes/Blocks/TiaAndSTep7DataBlockRow.cs index 8e4a1681..77aad475 100644 --- a/LibNoDaveConnectionLibrary/DataTypes/Blocks/TiaAndSTep7DataBlockRow.cs +++ b/LibNoDaveConnectionLibrary/DataTypes/Blocks/TiaAndSTep7DataBlockRow.cs @@ -34,6 +34,7 @@ You should have received a copy of the GNU Library General Public License using DotNetSiemensPLCToolBoxLibrary.DataTypes.Projectfolders.Step7V5; using DotNetSiemensPLCToolBoxLibrary.PLCs.S7_xxx.MC7; using DotNetSiemensPLCToolBoxLibrary.General; +using System.Text.RegularExpressions; namespace DotNetSiemensPLCToolBoxLibrary.DataTypes.Blocks @@ -89,6 +90,41 @@ public string FullBlockAddressInDbFormat } } + internal List GetStartValuesArray(object startValues) + { + if (startValues == null) + { + return new List(); + } + + var strStartValues = startValues.ToString(); + + // matches on shortened pattern like "2(3),2(3)" + var shortPattern = @"(\d+)\(([^)]+)\)"; + var matches = Regex.Matches(strStartValues, shortPattern); + + if (matches.Count == 0) + { + // assumes "1,2,3,4,5" format + return strStartValues.Split(',').ToList(); + } + + var ret = new List(); + + foreach (Match match in matches) + { + var count = int.Parse(match.Groups[1].Value); + var value = match.Groups[2].Value; + + for (int i = 0; i < count; i++) + { + ret.Add(value); + } + } + + return ret; + } + internal List _GetExpandedChlidren(S7DataBlockExpandOptions myExpOpt) { TiaAndSTep7DataBlockRow retVal = (TiaAndSTep7DataBlockRow)this.DeepCopy(); @@ -108,6 +144,8 @@ internal List _GetExpandedChlidren(S7DataBlockExpandOpt { List arrAsList = new List(); + var startValues = GetStartValuesArray(StartValue); + var lastCnt = (ArrayStop.Last() - ArrayStart.Last()) + 1; int[] arrAk = ArrayStart.ToArray(); @@ -129,6 +167,14 @@ internal List _GetExpandedChlidren(S7DataBlockExpandOpt tmp.WasArray = retVal.IsArray; tmp.IsArray = false; tmp.WasNextHigherIndex = frst; // arrAk[ArrayStart.Count - 1] == ArrayStart[ArrayStart.Count - 1]; + if (i < startValues.Count) + { + tmp.StartValue = startValues[i]; + } + else + { + tmp.StartValue = Helper.DefaultValueForType(DataType); + } arrAsList.Add(tmp); for (int n = arrAk.Length - 1; n >= 0; n--) diff --git a/LibNoDaveConnectionLibrary/DataTypes/Projectfolders/Step7V5/BlocksOfflineFolder.cs b/LibNoDaveConnectionLibrary/DataTypes/Projectfolders/Step7V5/BlocksOfflineFolder.cs index 3d0e61e9..7c795fc0 100644 --- a/LibNoDaveConnectionLibrary/DataTypes/Projectfolders/Step7V5/BlocksOfflineFolder.cs +++ b/LibNoDaveConnectionLibrary/DataTypes/Projectfolders/Step7V5/BlocksOfflineFolder.cs @@ -424,13 +424,20 @@ private TmpBlock GetBlockBytes(string blkName) } public S7DataRow GetInterface(string blkName) + { + var myConvOpt = new S7ConvertingOptions(Project.ProjectLanguage); + + return GetInterface(blkName, myConvOpt); + } + + public S7DataRow GetInterface(string blkName, S7ConvertingOptions myConvOpt) { var blkInfo = GetProjectBlockInfoFromBlockName(blkName); if (blkInfo == null) return null; TmpBlock myTmpBlk = GetBlockBytes(blkInfo); List tmpPar = new List(); - return Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref tmpPar, blkInfo.BlockType, false, this, null); + return Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref tmpPar, blkInfo.BlockType, false, this, null, myConvOpt); } /// @@ -547,10 +554,10 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt) { S7DataRow InterfaceFB = Parameter.GetInterfaceOrDBFromStep7ProjectString(InstFB.blkinterface, ref tmpPar, - PLCBlockType.FB, false, this, null); + PLCBlockType.FB, false, this, null, myConvOpt); S7DataRow InterfaceDB = Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref tmpPar, - PLCBlockType.DB, false, this, null); + PLCBlockType.DB, false, this, null, myConvOpt); //Only use the FB interface Declaration if they are compatible if (Parameter.IsInterfaceCompatible(InterfaceFB, InterfaceDB)) @@ -561,7 +568,7 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt) if (myTmpBlk.mc7code != null) retVal.CodeSize = myTmpBlk.mc7code.Length; - retVal.StructureFromString = Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref tmpList, blkInfo.BlockType, false, this, retVal, myTmpBlk.mc7code); + retVal.StructureFromString = Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref tmpList, blkInfo.BlockType, false, this, retVal, myConvOpt, myTmpBlk.mc7code); if (myTmpBlk.blkinterfaceInMC5 != null) { //List tmp = new List(); @@ -604,7 +611,7 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt) retVal.Author = myTmpBlk.username; retVal.Version = myTmpBlk.version; - retVal.Parameter = Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref ParaList, blkInfo.BlockType, false, this, retVal); + retVal.Parameter = Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref ParaList, blkInfo.BlockType, false, this, retVal, myConvOpt); if (myTmpBlk.blockdescription != null) { diff --git a/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/CallConverter.cs b/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/CallConverter.cs index 38e4671a..cdeec341 100644 --- a/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/CallConverter.cs +++ b/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/CallConverter.cs @@ -174,7 +174,7 @@ public static void ConvertUCToCall(S7FunctionBlock myFct, S7ProgrammFolder myFld else if (row.Command == Mnemonic.opBLD[(int)myOpt.Mnemonic] && (row.Parameter == "2" || row.Parameter == "8")) { //Block Interface auslesen (von FC oder vom Programm) - S7DataRow para = myblkFld.GetInterface(callRow.Parameter); + S7DataRow para = myblkFld.GetInterface(callRow.Parameter, myOpt); newRow = new S7FunctionBlockRow(); newRow.Command = Mnemonic.opCALL[(int)myOpt.Mnemonic]; @@ -545,7 +545,7 @@ public static void ConvertUCToCall(S7FunctionBlock myFct, S7ProgrammFolder myFld else if (row.Command == Mnemonic.opBLD[(int)myOpt.Mnemonic] && (row.Parameter == "4" || row.Parameter == "17" || row.Parameter == "15" || row.Parameter == "10")) { //Block Interface auslesen (von FC oder vom Programm) - S7DataRow para = myblkFld.GetInterface(callRow.Parameter); + S7DataRow para = myblkFld.GetInterface(callRow.Parameter, myOpt); newRow = new S7FunctionBlockRow(); newRow.Parent = callRow.Parent; diff --git a/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Helper.cs b/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Helper.cs index e94edd88..88cd45d4 100644 --- a/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Helper.cs +++ b/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Helper.cs @@ -945,7 +945,7 @@ public static string GetFCPointer(byte b1, byte b2, byte b3, byte b4) switch (b1) { case 0x80: - anf = "P#PE "; + anf = "P#P "; wrt = (b3 * 0x100 + b4) >> 3; break; case 0x81: diff --git a/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Parameter.cs b/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Parameter.cs index 510fa38a..35687fbd 100644 --- a/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Parameter.cs +++ b/LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Parameter.cs @@ -33,6 +33,7 @@ You should have received a copy of the GNU Library General Public License using DotNetSiemensPLCToolBoxLibrary.DataTypes.Blocks.Step7V5; using DotNetSiemensPLCToolBoxLibrary.DataTypes.Projectfolders.Step7V5; using DotNetSiemensPLCToolBoxLibrary.DataTypes.Blocks; +using DotNetSiemensPLCToolBoxLibrary.DataTypes.AWL.Step7V5; namespace DotNetSiemensPLCToolBoxLibrary.PLCs.S7_xxx.MC7 { @@ -167,7 +168,7 @@ internal static bool IsInterfaceCompatible(IDataRow Block1, IDataRow Block2) /// The Block where the Parsed Step7 code belongs to /// the current values of the DB, if it is an DB /// - internal static S7DataRow GetInterfaceOrDBFromStep7ProjectString(string txt, ref List ParaList, PLCBlockType blkTP, bool isInstanceDB, BlocksOfflineFolder myFld, S7Block myBlk, byte[] actualValues = null) + internal static S7DataRow GetInterfaceOrDBFromStep7ProjectString(string txt, ref List ParaList, PLCBlockType blkTP, bool isInstanceDB, BlocksOfflineFolder myFld, S7Block myBlk, S7ConvertingOptions myConvOpt, byte[] actualValues = null) { S7DataRow parameterRoot = new S7DataRow("ROOTNODE", S7DataRowType.STRUCT, myBlk); S7DataRow parameterRootWithoutTemp = new S7DataRow("ROOTNODE", S7DataRowType.STRUCT, myBlk); @@ -550,6 +551,13 @@ internal static S7DataRow GetInterfaceOrDBFromStep7ProjectString(string txt, ref // addRW.Value = GetVarTypeVal((byte)addRW.DataType, actualValues, ref Valpos); //} + if (myConvOpt.ExpandArrays && blkTP == PLCBlockType.DB && addRW.IsArray) + { + var arrayMembers = addRW._GetExpandedChlidren(new S7DataBlockExpandOptions()); + + addRW.AddRange(arrayMembers); + } + akDataRow.Add(addRW); ParaList.Add(tmpName); @@ -580,15 +588,16 @@ internal static S7DataRow GetInterfaceOrDBFromStep7ProjectString(string txt, ref } } } + if (blkTP != PLCBlockType.DB && blkTP != PLCBlockType.UDT && tempAdded == false) { parameterRoot.Add(parameterTEMP); } - if (actualValues != null) + // Only get actual values for DBs + if (myConvOpt.UseDBActualValues && blkTP == PLCBlockType.DB && actualValues != null) { - int vPos = 0, bPos = 0; - //FillActualValuesInDataBlock(parameterRoot, actualValues, ref vPos, ref bPos); + FillActualValuesInDataBlock(parameterRoot, actualValues); } return parameterRoot; @@ -1119,9 +1128,86 @@ internal static object GetVarCurrentValue(S7DataRowType dataType, byte[] data, B Result = Helper.GetS7String(valpos.ByteAddress, -1, data); } break; + case S7DataRowType.TIMER: + { + Result = "T " + libnodave.getU16from(data, valpos.ByteAddress); + } + break; + case S7DataRowType.COUNTER: + { + Result = "Z " + libnodave.getU16from(data, valpos.ByteAddress); + } + break; + case S7DataRowType.POINTER: + { + var dbNumber = libnodave.getU16from(data, valpos.ByteAddress); + + var pointer = Helper.GetFCPointer( + data[valpos.ByteAddress + 2], + data[valpos.ByteAddress + 3], + data[valpos.ByteAddress + 4], + data[valpos.ByteAddress + 5]); + + if (dbNumber != 0) + { + pointer = pointer.Insert(2, "DB" + dbNumber + "."); + } + + Result = pointer; + } + break; + case S7DataRowType.ANY: + { + var pointerDataType = (S7DataRowType)data[valpos.ByteAddress + 1]; + + var repeatFactor = libnodave.getU16from(data, valpos.ByteAddress + 2); + + var dbNumber = libnodave.getU16from(data, valpos.ByteAddress + 4); + + var pointer = Helper.GetFCPointer( + data[valpos.ByteAddress + 6], + data[valpos.ByteAddress + 7], + data[valpos.ByteAddress + 8], + data[valpos.ByteAddress + 9]); + + if (dbNumber != 0) + { + pointer = pointer.Insert(2, "DB" + dbNumber + "."); + } + + pointer += " " + pointerDataType + " " + repeatFactor; + + Result = pointer; + } + break; case S7DataRowType.SFB: //unclear, needs to be checked { // 'SFB??'; - Result = "SFB??"; + Result = null; + } + break; + case S7DataRowType.BLOCK_FB: + { + Result = "FB " + libnodave.getU16from(data, valpos.ByteAddress); + } + break; + case S7DataRowType.BLOCK_DB: + { + Result = "DB " + libnodave.getU16from(data, valpos.ByteAddress); + } + break; + case S7DataRowType.BLOCK_FC: + { + Result = "FC " + libnodave.getU16from(data, valpos.ByteAddress); + } + break; + case S7DataRowType.BLOCK_SDB: + { + Result = "SDB " + libnodave.getU16from(data, valpos.ByteAddress); + } + break; + case S7DataRowType.UDT: + { + Result = "UDT " + libnodave.getU16from(data, valpos.ByteAddress); } break; default: diff --git a/ToolBoxLibUnitTests/TestDataBlockReading.cs b/ToolBoxLibUnitTests/TestDataBlockReading.cs index 5b1d153c..f8049a2d 100644 --- a/ToolBoxLibUnitTests/TestDataBlockReading.cs +++ b/ToolBoxLibUnitTests/TestDataBlockReading.cs @@ -2,6 +2,7 @@ using DotNetSiemensPLCToolBoxLibrary.DataTypes; using DotNetSiemensPLCToolBoxLibrary.DataTypes.Blocks.Step7V5; using DotNetSiemensPLCToolBoxLibrary.DataTypes.Projectfolders.Step7V5; +using DotNetSiemensPLCToolBoxLibrary.DataTypes.AWL.Step7V5; using NUnit.Framework; namespace ToolBoxLibUnitTests @@ -23,7 +24,7 @@ public void TestDB1() PLCBlockType .DB, false, - fld, blk); + fld, blk, new S7ConvertingOptions()); Assert.AreEqual(test.Children[0].Name, "DB_VAR"); Assert.AreEqual(test.Children[1].Name, "aa"); Assert.AreEqual(test.Children[2].Name, "bb"); @@ -47,7 +48,7 @@ public void TestDB2() PLCBlockType .DB, false, - fld, blk); + fld, blk, new S7ConvertingOptions()); Assert.AreEqual(test.Children[0].Name, "Fachkoordinate"); Assert.AreEqual(((S7DataRow)test.Children[0]).ArrayStart[0], 0); Assert.AreEqual(((S7DataRow)test.Children[0]).ArrayStart[1], 1); @@ -69,7 +70,7 @@ public void TestDB3() PLCBlockType .DB, false, - fld, blk); + fld, blk, new S7ConvertingOptions()); Assert.AreEqual(test.Children[0].Name, "X_KOORDINATE"); Assert.AreEqual(((S7DataRow)test.Children[0]).ArrayStart[0], 0); Assert.AreEqual(((S7DataRow)test.Children[0]).ArrayStart[1], 0); @@ -93,7 +94,7 @@ public void TestDB4() PLCBlockType .DB, false, - fld, blk); + fld, blk, new S7ConvertingOptions()); var rw = test.Children[0] as S7DataRow; var callStr = rw.GetCallingString(); }