1- using System ;
1+ using System ;
22using System . Collections . Generic ;
33using System . Data ;
44using System . Text ;
@@ -154,6 +154,7 @@ public class TmpBlock
154154 public string version ;
155155 public DateTime LastCodeChange ;
156156 public DateTime LastInterfaceChange ;
157+ public DateTime LastInterfaceChangeHistory ;
157158 public bool IsInstanceDB ;
158159 public bool IsSFB ;
159160 public int FBNumber ;
@@ -323,6 +324,8 @@ public TmpBlock GetBlockBytes(ProjectBlockInfo blkInfo)
323324 myTmpBlk . nwinfo = addinfo ;
324325 //This line contains Network Information, and after it the Position of the JumpMarks
325326
327+ // ssbpart contains the MC7 interface from the PLC
328+ myTmpBlk . blkinterfaceInMC5 = ssbpart ;
326329 myTmpBlk . LastCodeChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP1" ] ) ;
327330 myTmpBlk . LastInterfaceChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP2" ] ) ;
328331
@@ -335,10 +338,12 @@ public TmpBlock GetBlockBytes(ProjectBlockInfo blkInfo)
335338 }
336339 else if ( subblktype == 5 || subblktype == 3 || subblktype == 4 || subblktype == 7 || subblktype == 9 ) //FC, OB, FB, SFC, SFB
337340 {
338- //Interface in mc5code
341+ // Interface in plaintext
339342 if ( mc5code != null )
340- myTmpBlk . blkinterface =
341- Project . ProjectEncoding . GetString ( mc5code ) ;
343+ {
344+ myTmpBlk . blkinterface = Project . ProjectEncoding . GetString ( mc5code ) ;
345+ myTmpBlk . LastInterfaceChangeHistory = GetTimeStamp ( ( string ) row [ "TIMESTAMP2" ] ) ;
346+ }
342347 }
343348 else if ( subblktype == 19 || subblktype == 17 || subblktype == 18 || subblktype == 22 ||
344349 subblktype == 21 ) //FC, OB, FB, SFC, SFB
@@ -348,23 +353,30 @@ public TmpBlock GetBlockBytes(ProjectBlockInfo blkInfo)
348353 myTmpBlk . jumpmarks = addinfo ;
349354 //The Text of the Jump Marks, Before the Jumpmarks there is some Network Information, but don't know what!
350355 }
351-
352356 else if ( subblktype == 6 || subblktype == 1 ) //DB, UDT
353357 {
354358 //DB Structure in Plain Text (Structure and StartValues!)
355359 if ( mc5code != null )
356- myTmpBlk . blkinterface =
357- Project . ProjectEncoding . GetString ( mc5code ) ;
360+ {
361+ myTmpBlk . blkinterface = Project . ProjectEncoding . GetString ( mc5code ) ;
362+ myTmpBlk . LastInterfaceChangeHistory = GetTimeStamp ( ( string ) row [ "TIMESTAMP2" ] ) ;
363+ }
364+
365+ // DB blocks get their timestamps from the MC7 interface record (when subblktype == 10). UDT blocks can't be downloaded and don't have this same record.
366+ if ( blkInfo . BlockType == PLCBlockType . UDT )
367+ {
368+ myTmpBlk . LastCodeChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP1" ] ) ;
369+ myTmpBlk . LastInterfaceChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP2" ] ) ;
370+ }
371+
358372 //Maybe compiled DB Structure?
359373 myTmpBlk . addinfo = addinfo ;
360-
361- myTmpBlk . LastCodeChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP1" ] ) ;
362- myTmpBlk . LastInterfaceChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP2" ] ) ;
363374 }
364375 else if ( subblktype == 10 ) //DB
365376 {
366- //Need to check wich Information is stored here
377+ // mc7code contains the actual values of the DB from the PLC
367378 myTmpBlk . mc7code = mc5code ;
379+ // ssbpart contains the MC7 interface from the PLC
368380 myTmpBlk . blkinterfaceInMC5 = ssbpart ;
369381 myTmpBlk . LastCodeChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP1" ] ) ;
370382 myTmpBlk . LastInterfaceChange = GetTimeStamp ( ( string ) row [ "TIMESTAMP2" ] ) ;
@@ -552,6 +564,9 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt)
552564 List < string > tmpPar = new List < string > ( ) ;
553565 if ( InstFB != null )
554566 {
567+ // Set the InstanceDB's history time to the most recent change of the FB
568+ myTmpBlk . LastInterfaceChangeHistory = InstFB . LastInterfaceChange ;
569+
555570 S7DataRow InterfaceFB =
556571 Parameter . GetInterfaceOrDBFromStep7ProjectString ( InstFB . blkinterface , ref tmpPar ,
557572 PLCBlockType . FB , false , this , null , myConvOpt ) ;
@@ -568,21 +583,19 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt)
568583 if ( myTmpBlk . mc7code != null )
569584 retVal . CodeSize = myTmpBlk . mc7code . Length ;
570585
586+ retVal . LastCodeChange = myTmpBlk . LastCodeChange ;
587+ retVal . LastInterfaceChange = myTmpBlk . LastInterfaceChange ;
588+ retVal . LastInterfaceChangeHistory = myTmpBlk . LastInterfaceChangeHistory ;
589+
590+ retVal . StructureFromMC7 = GetInterfaceStructureFromMC7 ( blkInfo , myTmpBlk , retVal , ref tmpList ) ;
571591 retVal . StructureFromString = Parameter . GetInterfaceOrDBFromStep7ProjectString ( myTmpBlk . blkinterface , ref tmpList , blkInfo . BlockType , false , this , retVal , myConvOpt , myTmpBlk . mc7code ) ;
572- if ( myTmpBlk . blkinterfaceInMC5 != null )
573- {
574- //List<string> tmp = new List<string>();
575- //retVal.StructureFromMC7 = Parameter.GetInterface(myTmpBlk.blkinterfaceInMC5, myTmpBlk.mc7code, ref tmp, blkInfo.BlockType, myTmpBlk.IsInstanceDB, retVal);
576- }
592+
577593 retVal . BlockNumber = plcblkifo . BlockNumber ;
578594 retVal . Name = plcblkifo . Name ;
579595 retVal . Family = ( ( S7ProjectBlockInfo ) plcblkifo ) . Family ;
580596 retVal . BlockType = blkInfo . BlockType ;
581597 retVal . Attributes = step7Attributes ;
582598
583- retVal . LastCodeChange = myTmpBlk . LastCodeChange ;
584- retVal . LastInterfaceChange = myTmpBlk . LastInterfaceChange ;
585-
586599 retVal . ParentFolder = this ;
587600 retVal . usedS7ConvertingOptions = myConvOpt ;
588601 retVal . CheckSum = myTmpBlk . CheckSum ;
@@ -599,6 +612,7 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt)
599612
600613 retVal . LastCodeChange = myTmpBlk . LastCodeChange ;
601614 retVal . LastInterfaceChange = myTmpBlk . LastInterfaceChange ;
615+ retVal . LastInterfaceChangeHistory = myTmpBlk . LastInterfaceChangeHistory ;
602616
603617 retVal . BlockNumber = plcblkifo . BlockNumber ;
604618 retVal . Name = plcblkifo . Name ;
@@ -611,7 +625,14 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt)
611625 retVal . Author = myTmpBlk . username ;
612626 retVal . Version = myTmpBlk . version ;
613627
614- retVal . Parameter = Parameter . GetInterfaceOrDBFromStep7ProjectString ( myTmpBlk . blkinterface , ref ParaList , blkInfo . BlockType , false , this , retVal , myConvOpt ) ;
628+ if ( myConvOpt . CheckForInterfaceTimestampConflicts && retVal . HasInterfaceTimestampConflict )
629+ {
630+ retVal . Parameter = GetInterfaceStructureFromMC7 ( blkInfo , myTmpBlk , retVal , ref ParaList ) ;
631+ }
632+ else
633+ {
634+ retVal . Parameter = Parameter . GetInterfaceOrDBFromStep7ProjectString ( myTmpBlk . blkinterface , ref ParaList , blkInfo . BlockType , false , this , retVal , myConvOpt ) ;
635+ }
615636
616637 if ( myTmpBlk . blockdescription != null )
617638 {
@@ -805,7 +826,46 @@ public Block GetBlock(ProjectBlockInfo blkInfo, S7ConvertingOptions myConvOpt)
805826 }
806827 }
807828 return null ;
808- }
829+ }
830+
831+ /// <summary>
832+ /// Converts the MC7 code of the block interface to S7DataRow
833+ /// </summary>
834+ public S7DataRow GetInterfaceStructureFromMC7 ( ProjectBlockInfo blkInfo , TmpBlock myTmpBlk , S7Block block , ref List < string > paramList )
835+ {
836+ if ( myTmpBlk . blkinterfaceInMC5 == null || myTmpBlk . blkinterfaceInMC5 . Length == 0 )
837+ {
838+ return null ;
839+ }
840+
841+ try
842+ {
843+ // Not sure what bytes 0-2 in the header are for
844+ // Bytes 3-4 are the interface length (not including header)
845+ var interfaceLen = BitConverter . ToUInt16 ( myTmpBlk . blkinterfaceInMC5 , 3 ) ;
846+ var headerPlusInterfaceLen = 7 + interfaceLen ;
847+ var interfaceBytes = new byte [ headerPlusInterfaceLen ] ;
848+ Array . Copy ( myTmpBlk . blkinterfaceInMC5 , 0 , interfaceBytes , 0 , headerPlusInterfaceLen ) ;
849+
850+ // Bytes 5-6 are the start values length
851+ var startValuesLen = BitConverter . ToUInt16 ( myTmpBlk . blkinterfaceInMC5 , 5 ) ;
852+ byte [ ] startValuesBytes = null ;
853+ if ( startValuesLen > 0 )
854+ {
855+ startValuesBytes = new byte [ startValuesLen ] ;
856+ Array . Copy ( myTmpBlk . blkinterfaceInMC5 , headerPlusInterfaceLen , startValuesBytes , 0 , startValuesLen ) ;
857+ }
858+
859+ // Only DB blocks have actual values
860+ var actualValuesBytes = blkInfo . BlockType == PLCBlockType . DB ? myTmpBlk . mc7code : null ;
861+
862+ return Parameter . GetInterface ( interfaceBytes , startValuesBytes , actualValuesBytes , ref paramList , blkInfo . BlockType , myTmpBlk . IsInstanceDB , block ) ;
863+ }
864+ catch
865+ {
866+ return null ;
867+ }
868+ }
809869
810870 /// <summary>
811871 /// With this Function you get the AWL Source of a Block, so that it can be imported into Step7
0 commit comments