Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add S7 options to get DB 'actual values' and expand arrays #196

Merged
merged 7 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -89,6 +90,41 @@ public string FullBlockAddressInDbFormat
}
}

internal List<string> GetStartValuesArray(object startValues)
{
if (startValues == null)
{
return new List<string>();
}

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<string>();

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<TiaAndSTep7DataBlockRow> _GetExpandedChlidren(S7DataBlockExpandOptions myExpOpt)
{
TiaAndSTep7DataBlockRow retVal = (TiaAndSTep7DataBlockRow)this.DeepCopy();
Expand All @@ -108,6 +144,8 @@ internal List<TiaAndSTep7DataBlockRow> _GetExpandedChlidren(S7DataBlockExpandOpt
{
List<TiaAndSTep7DataBlockRow> arrAsList = new List<TiaAndSTep7DataBlockRow>();

var startValues = GetStartValuesArray(StartValue);

var lastCnt = (ArrayStop.Last() - ArrayStart.Last()) + 1;

int[] arrAk = ArrayStart.ToArray();
Expand All @@ -129,6 +167,14 @@ internal List<TiaAndSTep7DataBlockRow> _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--)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,14 +423,14 @@ private TmpBlock GetBlockBytes(string blkName)
return GetBlockBytes(blkInfo);
}

public S7DataRow GetInterface(string blkName)
public S7DataRow GetInterface(string blkName, S7ConvertingOptions myConvOpt)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you a here a overload without the Converting Options? So it is a non breaking change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep!

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<string> tmpPar = new List<string>();
return Parameter.GetInterfaceOrDBFromStep7ProjectString(myTmpBlk.blkinterface, ref tmpPar, blkInfo.BlockType, false, this, null, myConvOpt);
}

{
var blkInfo = GetProjectBlockInfoFromBlockName(blkName);
if (blkInfo == null)
return null;
TmpBlock myTmpBlk = GetBlockBytes(blkInfo);
List<string> tmpPar = new List<string>();
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);
}

/// <summary>
Expand Down Expand Up @@ -547,10 +547,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))
Expand All @@ -561,7 +561,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<string> tmp = new List<string>();
Expand Down Expand Up @@ -604,7 +604,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)
{
Expand Down
4 changes: 2 additions & 2 deletions LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/CallConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? (I don't know what PE was... and what is P for...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, at least that's how it looks in my software:
image

wrt = (b3 * 0x100 + b4) >> 3;
break;
case 0x81:
Expand Down
96 changes: 91 additions & 5 deletions LibNoDaveConnectionLibrary/PLCs/S7_xxx/MC7/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -167,7 +168,7 @@ internal static bool IsInterfaceCompatible(IDataRow Block1, IDataRow Block2)
/// <param name="myBlk">The Block where the Parsed Step7 code belongs to</param>
/// <param name="actualValues">the current values of the DB, if it is an DB</param>
/// <returns></returns>
internal static S7DataRow GetInterfaceOrDBFromStep7ProjectString(string txt, ref List<String> ParaList, PLCBlockType blkTP, bool isInstanceDB, BlocksOfflineFolder myFld, S7Block myBlk, byte[] actualValues = null)
internal static S7DataRow GetInterfaceOrDBFromStep7ProjectString(string txt, ref List<String> 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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
9 changes: 5 additions & 4 deletions ToolBoxLibUnitTests/TestDataBlockReading.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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");
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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();
}
Expand Down