2323
2424using System ;
2525using System . Collections . Generic ;
26+ using System . Globalization ;
2627using System . IO ;
2728using System . Linq ;
2829using System . Text ;
2930using System . Threading ;
3031using System . Windows . Forms ;
3132using GSF ;
33+ using GSF . Configuration ;
3234using GSF . IO ;
3335using GSF . Snap ;
3436using GSF . Snap . Filters ;
3840using GSF . Threading ;
3941using GSF . Units ;
4042using GSF . Units . EE ;
43+ using GSF . Windows . Forms ;
4144using openHistorian . Net ;
4245using openHistorian . Snap ;
4346using openHistorian . Snap . Definitions ;
@@ -59,9 +62,43 @@ public OHTransfer()
5962 dateTimePickerTo . Value = nowFromTopOfHour ;
6063 }
6164
65+ private void OHTransfer_Load ( object sender , EventArgs e )
66+ {
67+ CategorizedSettingsElementCollection settings = ConfigurationFile . Current . Settings [ "systemSettings" ] ;
68+
69+ settings . Add ( "sourceFiles" , textBoxSourceFiles . Text , "openHistorian 2.0 source files location" , false , SettingScope . User ) ;
70+ settings . Add ( "destinationFiles" , textBoxDestinationFiles . Text , "openHistorian 2.0 destination files location" , false , SettingScope . User ) ;
71+ settings . Add ( "sourceCSVMeasurements" , textBoxSourceCSVMeasurements . Text , "openHistorian 2.0 source CSV measurements export file" , false , SettingScope . User ) ;
72+ settings . Add ( "destinationCSVMeasurements" , textBoxDestinationCSVMeasurements . Text , "openHistorian 2.0 destination CSV measurements export file" , false , SettingScope . User ) ;
73+ settings . Add ( "fromDate" , dateTimePickerFrom . Value . ToString ( dateTimePickerFrom . CustomFormat ) , "Start date for transfer" , false , SettingScope . User ) ;
74+ settings . Add ( "toDate" , dateTimePickerTo . Value . ToString ( dateTimePickerFrom . CustomFormat ) , "End date for transfer" , false , SettingScope . User ) ;
75+
76+ textBoxSourceFiles . Text = settings [ "sourceFiles" ] . Value ;
77+ textBoxDestinationFiles . Text = settings [ "destinationFiles" ] . Value ;
78+ textBoxSourceCSVMeasurements . Text = settings [ "sourceCSVMeasurements" ] . Value ;
79+ textBoxDestinationCSVMeasurements . Text = settings [ "destinationCSVMeasurements" ] . Value ;
80+ dateTimePickerFrom . Value = DateTime . ParseExact ( settings [ "fromDate" ] . Value , dateTimePickerFrom . CustomFormat , null , DateTimeStyles . AssumeUniversal ) ;
81+ dateTimePickerTo . Value = DateTime . ParseExact ( settings [ "toDate" ] . Value , dateTimePickerTo . CustomFormat , null , DateTimeStyles . AssumeUniversal ) ;
82+
83+ this . RestoreLocation ( ) ;
84+ }
85+
6286 private void OHTransfer_FormClosing ( object sender , FormClosingEventArgs e )
6387 {
88+ CategorizedSettingsElementCollection settings = ConfigurationFile . Current . Settings [ "systemSettings" ] ;
89+
6490 m_formClosing = true ;
91+
92+ this . SaveLocation ( ) ;
93+
94+ settings [ "sourceFiles" ] . Value = textBoxSourceFiles . Text ;
95+ settings [ "destinationFiles" ] . Value = textBoxDestinationFiles . Text ;
96+ settings [ "sourceCSVMeasurements" ] . Value = textBoxSourceCSVMeasurements . Text ;
97+ settings [ "destinationCSVMeasurements" ] . Value = textBoxDestinationCSVMeasurements . Text ;
98+ settings [ "fromDate" ] . Value = dateTimePickerFrom . Value . ToString ( dateTimePickerFrom . CustomFormat ) ;
99+ settings [ "toDate" ] . Value = dateTimePickerTo . Value . ToString ( dateTimePickerFrom . CustomFormat ) ;
100+
101+ ConfigurationFile . Current . Save ( ) ;
65102 }
66103
67104 private void buttonOpenSourceFilesLocation_Click ( object sender , EventArgs e )
@@ -220,24 +257,33 @@ private void buttonGo_Click(object sender, EventArgs e)
220257 // where the result is source CSV historian ID to destination CSV historian ID mapping
221258 Dictionary < ulong , ulong > historianIDMapping = new ( ) ;
222259
260+ // Pre-index destination signals for O(1) lookup by match key
261+ Dictionary < ( SignalKind Kind , int Index ) , ulong > signalReferenceIDMap = [ ] ;
262+ Dictionary < ( SignalKind Kind , int Index , string Acronym ) , ulong > calculatedSignalReferenceIDMap = [ ] ;
263+
264+ foreach ( KeyValuePair < ulong , SignalReference > destinationEntry in destinationCSVData )
265+ {
266+ SignalReference destinationSignal = destinationEntry . Value ;
267+
268+ if ( destinationSignal . Kind == SignalKind . Calculation )
269+ calculatedSignalReferenceIDMap [ ( destinationSignal . Kind , destinationSignal . Index , destinationSignal . Acronym ?? string . Empty ) ] = destinationEntry . Key ;
270+ else
271+ signalReferenceIDMap [ ( destinationSignal . Kind , destinationSignal . Index ) ] = destinationEntry . Key ;
272+ }
273+
223274 foreach ( KeyValuePair < ulong , SignalReference > sourceEntry in sourceCSVData )
224275 {
225276 SignalReference sourceSignal = sourceEntry . Value ;
226277
227- // Find matching SignalReference in destination CSV
228- foreach ( KeyValuePair < ulong , SignalReference > destinationEntry in destinationCSVData )
278+ if ( sourceSignal . Kind == SignalKind . Calculation )
229279 {
230- SignalReference destinationSignal = destinationEntry . Value ;
231-
232- if ( sourceSignal . Kind != destinationSignal . Kind || sourceSignal . Index != destinationSignal . Index )
233- continue ;
234-
235- // Also match on Acronym for Calculation signals
236- if ( sourceSignal . Kind == SignalKind . Calculation && sourceSignal . Acronym != destinationSignal . Acronym )
237- continue ;
238-
239- historianIDMapping [ sourceEntry . Key ] = destinationEntry . Key ;
240- break ; // Found a match, no need to check further
280+ if ( calculatedSignalReferenceIDMap . TryGetValue ( ( sourceSignal . Kind , sourceSignal . Index , sourceSignal . Acronym ?? string . Empty ) , out ulong destID ) )
281+ historianIDMapping [ sourceEntry . Key ] = destID ;
282+ }
283+ else
284+ {
285+ if ( signalReferenceIDMap . TryGetValue ( ( sourceSignal . Kind , sourceSignal . Index ) , out ulong destID ) )
286+ historianIDMapping [ sourceEntry . Key ] = destID ;
241287 }
242288 }
243289
@@ -277,7 +323,9 @@ private void buttonGo_Click(object sender, EventArgs e)
277323 HistorianServer server = new ( archiveInfo ) ;
278324 SnapClient client = SnapClient . Connect ( server . Host ) ;
279325 ClientDatabaseBase < HistorianKey , HistorianValue > database = client . GetDatabase < HistorianKey , HistorianValue > ( InstanceName ) ;
280- Dictionary < Guid , ArchiveDetails > attachedFiles = database . GetAllAttachedFiles ( ) . ToDictionary ( file => file . Id , file => file ) ;
326+ Dictionary < Guid , ArchiveDetails > attachedFiles = database . GetAllAttachedFiles ( )
327+ . OrderBy ( file => file . EndTime )
328+ . ToDictionary ( file => file . Id , file => file ) ;
281329
282330 using ArchiveList < HistorianKey , HistorianValue > archiveList = new ( ) ;
283331 archiveList . LoadFiles ( attachedFiles . Values . Select ( file => file . FileName ) ) ;
@@ -303,14 +351,21 @@ private void buttonGo_Click(object sender, EventArgs e)
303351
304352 string completeFileName = Path . Combine ( destinationPath , $ "{ deviceName } -Exported.d2") ;
305353 string pendingFileName = Path . Combine ( destinationPath , $ "{ FilePath . GetFileNameWithoutExtension ( completeFileName ) } .~d2i") ;
354+
355+ if ( File . Exists ( pendingFileName ) )
356+ File . Delete ( pendingFileName ) ;
357+
358+ if ( File . Exists ( completeFileName ) )
359+ File . Delete ( completeFileName ) ;
360+
306361 Guid stage3FileFlags = FileFlags . GetStage ( 3 ) ;
307362
308363 void processNewArchive ( Guid archiveID )
309364 {
310365 if ( ! attachedFiles . TryGetValue ( archiveID , out ArchiveDetails archiveDetails ) )
311366 return ;
312367
313- double processedDays = ( archiveDetails . EndTime - archiveDetails . StartTime ) . TotalDays ;
368+ double processedDays = ( archiveDetails . EndTime - startTime ) . TotalDays ;
314369
315370 UpdateProgressBar ( ( int ) processedDays ) ;
316371 ShowUpdateMessage ( "Processing archive \" {0}\" from {1} to {2}, {3:0.00%) complete..." , archiveDetails . FileName , archiveDetails . StartTime . ToString ( "yyyy-MM-dd HH:mm:ss" ) , archiveDetails . EndTime . ToString ( "yyyy-MM-dd HH:mm:ss" ) , processedDays / totalDays ) ;
@@ -352,7 +407,7 @@ private void buttonCancel_Click(object sender, EventArgs e)
352407 // Parse header to find column indices using robust CSV parser
353408 string [ ] headers = ParseCSVLine ( csvLines [ 0 ] ) ;
354409
355- int deviceIndex = Array . FindIndex ( headers , h => h . Trim ( ) . Equals ( "Device" , StringComparison . OrdinalIgnoreCase ) ) ;
410+ int deviceIndex = Array . FindIndex ( headers , header => header . Trim ( ) . Equals ( "Device" , StringComparison . OrdinalIgnoreCase ) ) ;
356411
357412 if ( deviceIndex < 0 )
358413 {
@@ -386,8 +441,8 @@ private void buttonCancel_Click(object sender, EventArgs e)
386441 }
387442 }
388443
389- int idIndex = Array . FindIndex ( headers , h => h . Trim ( ) . Equals ( "ID" , StringComparison . OrdinalIgnoreCase ) ) ;
390- int signalRefIndex = Array . FindIndex ( headers , h => h . Trim ( ) . Equals ( "SignalReference" , StringComparison . OrdinalIgnoreCase ) ) ;
444+ int idIndex = Array . FindIndex ( headers , header => header . Trim ( ) . Equals ( "ID" , StringComparison . OrdinalIgnoreCase ) ) ;
445+ int signalRefIndex = Array . FindIndex ( headers , header => header . Trim ( ) . Equals ( "SignalReference" , StringComparison . OrdinalIgnoreCase ) ) ;
391446
392447 if ( idIndex < 0 || signalRefIndex < 0 )
393448 {
0 commit comments