@@ -193,40 +193,52 @@ internal async Task<IEnumerable<OnlinerULInt>> ReadIdentitiesAsync()
193193 {
194194 _connector . Logger . Information ( "Reading identities..." ) ;
195195 await _connector . ReadBatchAsync ( _identitiesTags ) ;
196- var lastIdentity = 0ul ;
197- if ( _identitiesTags . Count > 0 )
198- {
199- lastIdentity = _identitiesTags . Max ( p => p . LastValue ) ;
200- }
201-
202- List < ITwinPrimitive > IdentitiesToWrite = new ( ) ;
203-
204- _connector . Logger . Information ( "Assigning missing identities..." ) ;
205- foreach ( var it in _identitiesTags )
206- {
207- if ( it . LastValue == 0 )
208- {
209- it . Cyclic = ++ lastIdentity ;
210- IdentitiesToWrite . Add ( it ) ;
211- }
212-
213- }
214- await _connector . WriteBatchAsync ( IdentitiesToWrite ) ;
215-
216- _connector . Logger . Information ( "Reading identities done." ) ;
217196 _connector . Logger . Information (
218197 $ "Number of identities: { _identitiesTags . Count } | Unique :{ _identities . Count } ") ;
219198 }
220199
221200 return _identitiesTags ;
222201 }
223202
203+
204+ /// <summary>
205+ /// Assigns identities to all elements.
206+ /// </summary>
207+ /// <param name="identities">Identities</param>
208+ /// <param name="identityProvider">Identity creator.</param>
209+ /// <returns></returns>
210+ public IEnumerable < OnlinerULInt > AssignIdentities ( IEnumerable < OnlinerULInt > identities , Func < OnlinerULInt , ulong > identityProvider = null )
211+ {
212+ // If no identity provider is given, use default one based on hash code of the symbol.
213+ identityProvider ??= ( x ) => x . Cyclic = ( ulong ) x . Symbol . GetHashCode ( ) ;
214+
215+ _connector . Logger . Information ( "Assigning missing identities..." ) ;
216+ foreach ( var it in identities )
217+ {
218+ it . Cyclic = identityProvider ( it ) ;
219+ }
220+
221+ return identities ;
222+ }
223+
224+ /// <summary>
225+ /// Writes identities to the PLC.
226+ /// </summary>
227+ /// <param name="identitiesToWrite">List of identities to be written.</param>
228+ /// <returns></returns>
229+ public async Task WriteIdentities ( IEnumerable < OnlinerULInt > identitiesToWrite )
230+ {
231+ if ( _connector == null ) return ;
232+ await _connector . WriteBatchAsync ( identitiesToWrite ) ;
233+ _connector . Logger . Information ( "Identities have been written." ) ;
234+ }
235+
224236 /// <summary>
225237 /// Refreshes and sorts identities.
226238 /// </summary>
227- public async Task ConstructIdentitiesAsync ( )
239+ public async Task ConstructIdentitiesAsync ( Func < OnlinerULInt , ulong > identityProvider = null )
228240 {
229- await ReadIdentitiesAsync ( ) ;
241+ await WriteIdentities ( AssignIdentities ( await ReadIdentitiesAsync ( ) , identityProvider ) ) ;
230242 await SortIdentitiesAsync ( ) ;
231243 }
232244
@@ -243,10 +255,29 @@ await Task.Run(() =>
243255 {
244256 var key = identity . Key . LastValue == 0 ? identity . Key . GetAsync ( ) . Result : identity . Key . LastValue ;
245257 if ( ! _sortedIdentities . ContainsKey ( key ) )
258+ {
246259 _sortedIdentities . Add ( key , identity . Value ) ;
260+ }
261+ else
262+ {
263+ throw new DuplicateIdentityException ( "There is a duplicate identity: " +
264+ $ "{ identity . Value . Symbol } : { key } ." +
265+ $ "The algorithm for assigning identities needs to be adjusted." +
266+ $ "Use an algorithm that guarantees unique identities and is less prone to collisions.") ;
267+ }
247268 }
248269
249270 _connector ? . Logger . Information ( "Sorting identities done." ) ;
250271 } ) ;
251272 }
273+ }
274+
275+ /// <summary>
276+ /// Exception thrown when a duplicate identity is detected.
277+ /// </summary>
278+ public class DuplicateIdentityException : Exception
279+ {
280+ public DuplicateIdentityException ( string message ) : base ( message )
281+ {
282+ }
252283}
0 commit comments