@@ -60,12 +60,14 @@ public void BuildFlatList()
6060 // Skip empty lists in any area like marker or timers.
6161 if ( node . Childs . Count > 0 )
6262 {
63- AddFlatSubnodes ( node , String . Empty , String . Empty ) ;
63+ uint OptOffset = 0 ;
64+ uint NonOptOffset = 0 ;
65+ AddFlatSubnodes ( node , String . Empty , String . Empty , OptOffset , NonOptOffset ) ;
6466 }
6567 }
6668 }
6769
68- private void AddFlatSubnodes ( Node node , string names , string accessIds )
70+ private void AddFlatSubnodes ( Node node , string names , string accessIds , uint OptOffset , uint NonOptOffset )
6971 {
7072 switch ( node . NodeType )
7173 {
@@ -97,16 +99,85 @@ private void AddFlatSubnodes(Node node, string names, string accessIds)
9799 {
98100 Name = names ,
99101 AccessSequence = accessIds ,
100- Softdatatype = node . Softdatatype
102+ Softdatatype = node . Softdatatype ,
101103 } ;
104+ // If an Array element of basic datatype, the Vte is here from the parent array base element and offsets not valid here.
105+ if ( node . NodeType == eNodeType . Array )
106+ {
107+ info . OptAddress = OptOffset ;
108+ info . NonOptAddress = NonOptOffset ;
109+ }
110+ else
111+ {
112+ info . OptAddress = OptOffset + node . Vte . OffsetInfoType . OptimizedAddress ;
113+ info . NonOptAddress = NonOptOffset + node . Vte . OffsetInfoType . NonoptimizedAddress ;
114+ }
115+ // Special case #1:
116+ // There is a strange behaviour when transmitting bitoffsets in not-optmized DBs.
117+ // If a bool is inside a struct, the offsetinformation is in the attributes (last 3 bits.
118+ // Bitoffsetinfo bit classic is false in this case.
119+ // Don't know if this a bug in Plcsim (where I tested with) or intentional.
120+ //
121+ // Special case #2:
122+ // System datatypes like IEC_COUNTER, etc. have Bools with Bitoffsets, even when they are locates in optimized DBs.
123+ // The bitoffset is then located in the Attributes and not in the bitoffset
124+ if ( node . Softdatatype == Softdatatype . S7COMMP_SOFTDATATYPE_BOOL )
125+ {
126+ info . OptBitoffset = node . Vte . GetAttributeBitoffset ( ) ;
127+ if ( node . Vte . GetBitoffsetinfoFlagClassic ( ) )
128+ {
129+ info . NonOptBitoffset = node . Vte . GetBitoffsetinfoNonoptimizedBitoffset ( ) ;
130+ }
131+ else
132+ {
133+ info . NonOptBitoffset = node . Vte . GetAttributeBitoffset ( ) ;
134+ }
135+ }
136+ else if ( node . Softdatatype == Softdatatype . S7COMMP_SOFTDATATYPE_BBOOL )
137+ {
138+ info . OptBitoffset = node . Vte . GetBitoffsetinfoOptimizedBitoffset ( ) ;
139+ }
140+ else
141+ {
142+ info . OptBitoffset = 0 ;
143+ info . NonOptBitoffset = 0 ;
144+ }
145+
102146 m_varInfoList . Add ( info ) ;
103147 }
104148 }
105149 else
106150 {
151+ // root node (the DB itself) has no VarTypeListElement, but we don't need it here.
152+ if ( node . Vte != null )
153+ {
154+ switch ( node . NodeType )
155+ {
156+ case eNodeType . Array :
157+ // This is an array element of basic datatype. Offset comes from fixed size multiplied by array index.
158+ OptOffset = node . Vte . OffsetInfoType . OptimizedAddress ;
159+ NonOptOffset = node . Vte . OffsetInfoType . NonoptimizedAddress ;
160+ break ;
161+ case eNodeType . StructArray :
162+ OptOffset += node . ArrayAdrOffsetOpt ;
163+ NonOptOffset += node . ArrayAdrOffsetNonOpt ;
164+ break ;
165+ default :
166+ OptOffset += node . Vte . OffsetInfoType . OptimizedAddress ;
167+ NonOptOffset += node . Vte . OffsetInfoType . NonoptimizedAddress ;
168+ break ;
169+ }
170+ }
107171 foreach ( var sub in node . Childs )
108172 {
109- AddFlatSubnodes ( sub , names , accessIds ) ;
173+ if ( sub . NodeType == eNodeType . Array )
174+ {
175+ AddFlatSubnodes ( sub , names , accessIds , OptOffset + sub . ArrayAdrOffsetOpt , NonOptOffset + sub . ArrayAdrOffsetNonOpt ) ;
176+ }
177+ else
178+ {
179+ AddFlatSubnodes ( sub , names , accessIds , OptOffset , NonOptOffset ) ;
180+ }
110181 }
111182 }
112183 }
@@ -135,6 +206,8 @@ private void AddSubNodes(ref Node node, PObject o)
135206 int [ ] MdimArrayLowerBounds ;
136207
137208 int element_index = 0 ;
209+ uint TComSize ;
210+
138211 // If there are no variables at all in an area, then this list does not exist (no error).
139212 if ( o . VartypeList != null )
140213 {
@@ -144,8 +217,10 @@ private void AddSubNodes(ref Node node, PObject o)
144217 {
145218 Name = o . VarnameList . Names [ element_index ] ,
146219 Softdatatype = vte . Softdatatype ,
147- AccessId = vte . LID
220+ AccessId = vte . LID ,
221+ Vte = vte ,
148222 } ;
223+
149224 node . Childs . Add ( subnode ) ;
150225 // Process arrays. TODO: Put the processing to separate methods, to shorten this method.
151226 if ( vte . OffsetInfoType . Is1Dim ( ) )
@@ -166,7 +241,8 @@ private void AddSubNodes(ref Node node, PObject o)
166241 NodeType = eNodeType . StructArray ,
167242 Name = "[" + ( i + ArrayLowerBounds ) + "]" ,
168243 Softdatatype = vte . Softdatatype ,
169- AccessId = i
244+ AccessId = i ,
245+ Vte = vte ,
170246 } ;
171247 subnode . Childs . Add ( arraynode ) ;
172248
@@ -177,6 +253,11 @@ private void AddSubNodes(ref Node node, PObject o)
177253 {
178254 if ( ob . RelationId == ioit2 . GetRelationId ( ) )
179255 {
256+ // Get the size of a struct element
257+ TComSize = ( ( ValueUDInt ) ob . GetAttribute ( Ids . TI_TComSize ) ) . GetValue ( ) ;
258+ arraynode . ArrayAdrOffsetOpt = i * TComSize ;
259+ arraynode . ArrayAdrOffsetNonOpt = i * TComSize ;
260+
180261 AddSubNodes ( ref arraynode , ob ) ;
181262 break ;
182263 }
@@ -189,8 +270,14 @@ private void AddSubNodes(ref Node node, PObject o)
189270 NodeType = eNodeType . Array ,
190271 Name = "[" + ( i + ArrayLowerBounds ) + "]" ,
191272 Softdatatype = vte . Softdatatype ,
192- AccessId = i
273+ AccessId = i ,
274+ Vte = vte ,
193275 } ;
276+ // Get the size of the basic datatype
277+ TComSize = GetSizeOfDatatype ( vte ) ;
278+ arraynode . ArrayAdrOffsetOpt = i * TComSize ;
279+ arraynode . ArrayAdrOffsetNonOpt = i * TComSize ;
280+
194281 subnode . Childs . Add ( arraynode ) ;
195282 }
196283 }
@@ -216,7 +303,7 @@ private void AddSubNodes(ref Node node, PObject o)
216303 }
217304
218305 string aname = "" ;
219- int n = 1 ;
306+ uint n = 1 ;
220307 uint id = 0 ;
221308 uint [ ] xx = new uint [ 6 ] { 0 , 0 , 0 , 0 , 0 , 0 } ;
222309 do
@@ -242,7 +329,8 @@ private void AddSubNodes(ref Node node, PObject o)
242329 NodeType = eNodeType . StructArray ,
243330 Name = aname ,
244331 Softdatatype = vte . Softdatatype ,
245- AccessId = id
332+ AccessId = id ,
333+ Vte = vte ,
246334 } ;
247335 subnode . Childs . Add ( arraynode ) ;
248336
@@ -253,6 +341,11 @@ private void AddSubNodes(ref Node node, PObject o)
253341 {
254342 if ( ob . RelationId == ioit2 . GetRelationId ( ) )
255343 {
344+ // Get the size of a struct element
345+ TComSize = ( ( ValueUDInt ) ob . GetAttribute ( Ids . TI_TComSize ) ) . GetValue ( ) ;
346+ arraynode . ArrayAdrOffsetOpt = ( n - 1 ) * TComSize ;
347+ arraynode . ArrayAdrOffsetNonOpt = ( n - 1 ) * TComSize ;
348+
256349 AddSubNodes ( ref arraynode , ob ) ;
257350 break ;
258351 }
@@ -265,8 +358,13 @@ private void AddSubNodes(ref Node node, PObject o)
265358 NodeType = eNodeType . Array ,
266359 Name = aname ,
267360 Softdatatype = vte . Softdatatype ,
268- AccessId = id
361+ AccessId = id ,
362+ Vte = vte ,
269363 } ;
364+ TComSize = GetSizeOfDatatype ( vte ) ;
365+ arraynode . ArrayAdrOffsetOpt = ( n - 1 ) * TComSize ;
366+ arraynode . ArrayAdrOffsetNonOpt = ( n - 1 ) * TComSize ;
367+
270368 subnode . Childs . Add ( arraynode ) ;
271369 }
272370 xx [ 0 ] ++ ;
@@ -312,6 +410,165 @@ private void AddSubNodes(ref Node node, PObject o)
312410 }
313411 }
314412
413+ private uint GetSizeOfDatatype ( PVartypeListElement vte )
414+ {
415+ // Returns the size of an element if stored as an array
416+ switch ( vte . Softdatatype )
417+ {
418+ case Softdatatype . S7COMMP_SOFTDATATYPE_BOOL :
419+ // TODO: Bit Bool?
420+ return 1 ;
421+ case Softdatatype . S7COMMP_SOFTDATATYPE_BYTE :
422+ return 1 ;
423+ case Softdatatype . S7COMMP_SOFTDATATYPE_CHAR :
424+ return 1 ;
425+ case Softdatatype . S7COMMP_SOFTDATATYPE_WORD :
426+ return 2 ;
427+ case Softdatatype . S7COMMP_SOFTDATATYPE_INT :
428+ return 2 ;
429+ case Softdatatype . S7COMMP_SOFTDATATYPE_DWORD :
430+ return 4 ;
431+ case Softdatatype . S7COMMP_SOFTDATATYPE_DINT :
432+ return 4 ;
433+ case Softdatatype . S7COMMP_SOFTDATATYPE_REAL :
434+ return 4 ;
435+ case Softdatatype . S7COMMP_SOFTDATATYPE_DATE :
436+ return 2 ;
437+ case Softdatatype . S7COMMP_SOFTDATATYPE_TIMEOFDAY :
438+ return 4 ;
439+ case Softdatatype . S7COMMP_SOFTDATATYPE_TIME :
440+ return 4 ;
441+ case Softdatatype . S7COMMP_SOFTDATATYPE_S5TIME :
442+ return 2 ;
443+ case Softdatatype . S7COMMP_SOFTDATATYPE_DATEANDTIME :
444+ return 8 ;
445+ case Softdatatype . S7COMMP_SOFTDATATYPE_STRING :
446+ case Softdatatype . S7COMMP_SOFTDATATYPE_WSTRING :
447+ // TODO:
448+ // If an array of String or WString, offsetinfo1 is the string length.
449+ // First though was, that offsetinfo2 is length including header of 2 bytes.
450+ // but with an Multidim Array [0..2, 0..1] of String[5] offsetinfo is 8, which is not
451+ // correct when you look at the data.
452+ // Tested only with Plcsim, which may be a bug in Plcsim?
453+ if ( vte . OffsetInfoType . Is1Dim ( ) )
454+ {
455+ return ( ( POffsetInfoType_Array1Dim ) ( vte . OffsetInfoType ) ) . UnspecifiedOffsetinfo1 + ( uint ) 2 ;
456+ }
457+ else
458+ {
459+ return ( ( POffsetInfoType_ArrayMDim ) ( vte . OffsetInfoType ) ) . UnspecifiedOffsetinfo1 + ( uint ) 2 ;
460+ }
461+ case Softdatatype . S7COMMP_SOFTDATATYPE_POINTER :
462+ return 6 ;
463+ case Softdatatype . S7COMMP_SOFTDATATYPE_ANY :
464+ return 10 ;
465+ case Softdatatype . S7COMMP_SOFTDATATYPE_BLOCKFB :
466+ return 2 ;
467+ case Softdatatype . S7COMMP_SOFTDATATYPE_BLOCKFC :
468+ return 2 ;
469+ case Softdatatype . S7COMMP_SOFTDATATYPE_COUNTER :
470+ return 2 ;
471+ case Softdatatype . S7COMMP_SOFTDATATYPE_TIMER :
472+ return 2 ;
473+ case Softdatatype . S7COMMP_SOFTDATATYPE_BBOOL :
474+ return 1 ; // Bool of size 1 byte here
475+ case Softdatatype . S7COMMP_SOFTDATATYPE_LREAL :
476+ return 8 ;
477+ case Softdatatype . S7COMMP_SOFTDATATYPE_ULINT :
478+ return 8 ;
479+ case Softdatatype . S7COMMP_SOFTDATATYPE_LINT :
480+ return 8 ;
481+ case Softdatatype . S7COMMP_SOFTDATATYPE_LWORD :
482+ return 8 ;
483+ case Softdatatype . S7COMMP_SOFTDATATYPE_USINT :
484+ return 1 ;
485+ case Softdatatype . S7COMMP_SOFTDATATYPE_UINT :
486+ return 2 ;
487+ case Softdatatype . S7COMMP_SOFTDATATYPE_UDINT :
488+ return 4 ;
489+ case Softdatatype . S7COMMP_SOFTDATATYPE_SINT :
490+ return 1 ;
491+ case Softdatatype . S7COMMP_SOFTDATATYPE_WCHAR :
492+ return 2 ;
493+ case Softdatatype . S7COMMP_SOFTDATATYPE_LTIME :
494+ return 8 ;
495+ case Softdatatype . S7COMMP_SOFTDATATYPE_LTOD :
496+ return 8 ;
497+ case Softdatatype . S7COMMP_SOFTDATATYPE_LDT :
498+ return 8 ;
499+ case Softdatatype . S7COMMP_SOFTDATATYPE_DTL :
500+ return 12 ; // In most cases as a struct of system type
501+ case Softdatatype . S7COMMP_SOFTDATATYPE_REMOTE :
502+ return 10 ;
503+ case Softdatatype . S7COMMP_SOFTDATATYPE_AOMIDENT :
504+ return 4 ;
505+ case Softdatatype . S7COMMP_SOFTDATATYPE_EVENTANY :
506+ return 4 ;
507+ case Softdatatype . S7COMMP_SOFTDATATYPE_EVENTATT :
508+ return 4 ;
509+ case Softdatatype . S7COMMP_SOFTDATATYPE_AOMAID :
510+ // TODO: Not possible to define this type
511+ return 0 ;
512+ case Softdatatype . S7COMMP_SOFTDATATYPE_AOMLINK :
513+ // TODO: Not possible to define this type
514+ return 0 ;
515+ case Softdatatype . S7COMMP_SOFTDATATYPE_EVENTHWINT :
516+ return 4 ;
517+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWANY :
518+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWIOSYSTEM :
519+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWDPMASTER :
520+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWDEVICE :
521+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWDPSLAVE :
522+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWIO :
523+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWMODULE :
524+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWSUBMODULE :
525+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWHSC :
526+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWPWM :
527+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWPTO :
528+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWINTERFACE :
529+ case Softdatatype . S7COMMP_SOFTDATATYPE_HWIEPORT :
530+ return 2 ;
531+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBANY :
532+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBDELAY :
533+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBTOD :
534+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBCYCLIC :
535+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBATT :
536+ return 2 ;
537+ case Softdatatype . S7COMMP_SOFTDATATYPE_CONNANY :
538+ return 2 ;
539+ case Softdatatype . S7COMMP_SOFTDATATYPE_CONNPRG :
540+ return 2 ;
541+ case Softdatatype . S7COMMP_SOFTDATATYPE_CONNOUC :
542+ return 2 ;
543+ case Softdatatype . S7COMMP_SOFTDATATYPE_CONNRID :
544+ return 4 ;
545+ case Softdatatype . S7COMMP_SOFTDATATYPE_PORT :
546+ return 2 ;
547+ case Softdatatype . S7COMMP_SOFTDATATYPE_RTM :
548+ return 2 ;
549+ case Softdatatype . S7COMMP_SOFTDATATYPE_PIP :
550+ return 2 ;
551+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBPCYCLE :
552+ return 2 ;
553+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBHWINT :
554+ return 2 ;
555+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBDIAG :
556+ return 2 ;
557+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBTIMEERROR :
558+ return 2 ;
559+ case Softdatatype . S7COMMP_SOFTDATATYPE_OBSTARTUP :
560+ return 2 ;
561+ case Softdatatype . S7COMMP_SOFTDATATYPE_DBANY :
562+ return 2 ;
563+ case Softdatatype . S7COMMP_SOFTDATATYPE_DBWWW :
564+ return 2 ;
565+ case Softdatatype . S7COMMP_SOFTDATATYPE_DBDYN :
566+ return 2 ;
567+ default :
568+ return 0 ;
569+ }
570+ }
571+
315572 private bool IsSoftdatatypeSupported ( uint softdatatype )
316573 {
317574 switch ( softdatatype )
@@ -404,6 +661,10 @@ protected class Node
404661 public UInt32 AccessId ;
405662 public UInt32 Softdatatype ;
406663 public UInt32 RelationId ;
664+ public PVartypeListElement Vte ;
665+ public UInt32 ArrayAdrOffsetOpt ; // Offset of an Element when it's an array, optimized
666+ public UInt32 ArrayAdrOffsetNonOpt ; // Offset of an Element when it's an array, not-optimized
667+
407668 public List < Node > Childs = new List < Node > ( ) ;
408669
409670 public Node ( )
@@ -423,6 +684,10 @@ public class VarInfo
423684 public string Name ;
424685 public string AccessSequence ;
425686 public UInt32 Softdatatype ;
687+ public UInt32 OptAddress ; // Optimized access: Byte-Offset where the value is located when reading a complete DB content.
688+ public int OptBitoffset ; // Optimized access: Bit-Offset where the value is located when reading a complete DB content.
689+ public UInt32 NonOptAddress ; // NonOptimized access: Byte-Offset where the value is located when reading a complete DB content.
690+ public int NonOptBitoffset ; // NonOptimized access: Bit-Offset where the value is located when reading a complete DB content.
426691 }
427692
428693 public enum eNodeType
0 commit comments