Skip to content

Commit 9997a69

Browse files
Improved O(n^2) mapping, fixed percent complete calcs, added load/save for UI elements
1 parent c08f6e6 commit 9997a69

3 files changed

Lines changed: 113 additions & 53 deletions

File tree

Source/Tools/OHTransfer/OHTransfer.Designer.cs

Lines changed: 36 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/Tools/OHTransfer/OHTransfer.cs

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323

2424
using System;
2525
using System.Collections.Generic;
26+
using System.Globalization;
2627
using System.IO;
2728
using System.Linq;
2829
using System.Text;
2930
using System.Threading;
3031
using System.Windows.Forms;
3132
using GSF;
33+
using GSF.Configuration;
3234
using GSF.IO;
3335
using GSF.Snap;
3436
using GSF.Snap.Filters;
@@ -38,6 +40,7 @@
3840
using GSF.Threading;
3941
using GSF.Units;
4042
using GSF.Units.EE;
43+
using GSF.Windows.Forms;
4144
using openHistorian.Net;
4245
using openHistorian.Snap;
4346
using 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
{

Source/Tools/OHTransfer/OHTransfer.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@
4242
<Reference Include="GSF.Core">
4343
<HintPath>..\..\Dependencies\GSF\GSF.Core.dll</HintPath>
4444
</Reference>
45+
<Reference Include="GSF.Windows">
46+
<HintPath>..\..\Dependencies\GSF\GSF.Windows.dll</HintPath>
47+
</Reference>
4548
<Reference Include="System" />
49+
<Reference Include="System.Configuration" />
4650
<Reference Include="System.Core" />
4751
<Reference Include="System.Xml.Linq" />
4852
<Reference Include="System.Data.DataSetExtensions" />

0 commit comments

Comments
 (0)