diff --git a/Tractor/Com.QuantAsylum.Tractor.Database/AuditDb.cs b/Tractor/Com.QuantAsylum.Tractor.Database/AuditDb.cs
index ad93f20..50c9be9 100644
--- a/Tractor/Com.QuantAsylum.Tractor.Database/AuditDb.cs
+++ b/Tractor/Com.QuantAsylum.Tractor.Database/AuditDb.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
@@ -15,8 +16,8 @@ class AuditData
public string ProductId;
public string SerialNumber;
public string SessionName;
- public string Channel;
- public string TestGroup;
+ public string Channel = ""; // Needed to accept data in old format. Without this there's a server exception
+ public string TestGroup = ""; // Ditto
public string TestFile;
public string TestFileMd5;
public string Name;
@@ -59,17 +60,58 @@ static public int AuditQueueDepth
get { return _AuditQueueDepth; }
}
- static public void StartBackgroundWorker()
+ static public void StartBackgroundTask()
{
- var task = new Task(() => BackgroundWorker(), TaskCreationOptions.LongRunning);
+ var task = new Task(() => BackgroundTask(), TaskCreationOptions.LongRunning);
task.Start();
}
+ static DateTime LastServerAccess = DateTime.Now;
+
+ ///
+ /// Ensure server accesses happen at least 1 second apart. Accesses from same IP
+ /// address less than 1 second apart are ignored.
+ ///
+ ///
+ ///
+ static Task GetAsync(string requestUri)
+ {
+ while (DateTime.Now.Subtract(LastServerAccess).TotalSeconds < 1.05)
+ {
+ Thread.Sleep(100);
+ }
+
+ //Debug.WriteLine($"Last Server Access: {DateTime.Now.Subtract(LastServerAccess).TotalSeconds:0.0} seconds ago");
+ Task result = Client.GetAsync(requestUri);
+ LastServerAccess = DateTime.Now;
+ return result;
+ }
+
+ ///
+ /// Ensure server accesses happen at last 1 second apart. Accesses from same IP
+ /// address less than 1 second apart are ignored.
+ ///
+ ///
+ ///
+ ///
+ static Task PostAsync(string requestUri, HttpContent body)
+ {
+ while (DateTime.Now.Subtract(LastServerAccess).TotalSeconds < 1.05)
+ {
+ Thread.Sleep(100);
+ }
+
+ //Debug.WriteLine($"Last Server Access: {DateTime.Now.Subtract(LastServerAccess).TotalSeconds:0.0} seconds ago");
+ Task result = Client.PostAsync(requestUri, body);
+ LastServerAccess = DateTime.Now;
+ return result;
+ }
+
static public string CheckService()
{
try
{
- var response = Client.GetAsync(Url + "/api/CheckService").Result;
+ var response = GetAsync(Url + "/api/CheckService").Result;
if (response.IsSuccessStatusCode)
{
@@ -111,7 +153,7 @@ static public List QueryGroupsBySerialNumber(string pid, string sn)
var json = new JavaScriptSerializer().Serialize(d);
var body = new StringContent(json, Encoding.UTF8, "application/json");
- var response = Client.PostAsync(Url + "/api/QueryGroups", body).Result;
+ var response = PostAsync(Url + "/api/QueryGroups", body).Result;
string content = response.Content.ReadAsStringAsync().Result;
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
@@ -141,7 +183,7 @@ static public string QueryTestsByGroup(string pid, string group)
var json = new JavaScriptSerializer().Serialize(d);
var body = new StringContent(json, Encoding.UTF8, "application/json");
- var response = Client.PostAsync(Url + "/api/QueryTests", body).Result;
+ var response = PostAsync(Url + "/api/QueryTests", body).Result;
string content = response.Content.ReadAsStringAsync().Result;
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
@@ -177,7 +219,7 @@ static public List QueryTestNames(string pid)
var json = new JavaScriptSerializer().Serialize(d);
var body = new StringContent(json, Encoding.UTF8, "application/json");
- var response = Client.PostAsync(Url + "/api/QueryTestNames", body).Result;
+ var response = PostAsync(Url + "/api/QueryTestNames", body).Result;
string content = response.Content.ReadAsStringAsync().Result;
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
@@ -212,7 +254,7 @@ static public string QueryStatsByTest(string pid, string testName, string testSe
var json = new JavaScriptSerializer().Serialize(d);
var body = new StringContent(json, Encoding.UTF8, "application/json");
- var response = Client.PostAsync(Url + "/api/QueryResults", body).Result;
+ var response = PostAsync(Url + "/api/QueryResults", body).Result;
string content = response.Content.ReadAsStringAsync().Result;
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
@@ -245,7 +287,7 @@ static public string QueryTestNamesByProductId(string pid)
var json = new JavaScriptSerializer().Serialize(d);
var body = new StringContent(json, Encoding.UTF8, "application/json");
- var response = Client.PostAsync(Url + "/api/QueryResults", body).Result;
+ var response = PostAsync(Url + "/api/QueryResults", body).Result;
string content = response.Content.ReadAsStringAsync().Result;
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
@@ -296,7 +338,7 @@ static bool SubmitAuditDataToCloud(AuditData d)
{
var json = new JavaScriptSerializer().Serialize(d);
var body = new StringContent(json, Encoding.UTF8, "application/json");
- var response = Client.PostAsync(Url + "/api/AddTest", body).Result;
+ var response = PostAsync(Url + "/api/AddTest", body).Result;
Log.WriteLine(LogType.Database, string.Format("PostAsync() to cloud finished. Response: " + response.StatusCode.ToString()));
if (response.IsSuccessStatusCode)
@@ -305,33 +347,39 @@ static bool SubmitAuditDataToCloud(AuditData d)
return false;
}
- static void BackgroundWorker()
+ static void BackgroundTask()
{
- const int fileLimit = 500;
+ Random r = new Random();
+
while (true)
{
try
{
- string[] filePaths = Directory.GetFiles(Constants.AuditPath, "*.cache", SearchOption.TopDirectoryOnly);
+ List filePaths = Directory.GetFiles(Constants.AuditPath, "*.cache", SearchOption.TopDirectoryOnly).ToList();
+
+ _AuditQueueDepth = filePaths.Count;
- _AuditQueueDepth = filePaths.Length;
- if (filePaths.Length > fileLimit)
+ // Do in batches of 50. Do in random order so if we see a bad record, we're not always
+ // starting with that one and trying that record over and over: If that record is corrupted
+ // then the effort will never finish.
+ if (filePaths.Count > 0)
{
- for (int i = 0; i <= fileLimit; i++)
+ for (int i = 0; i < 50; i++)
{
- SubmitFileToServer(filePaths[i]);
- Thread.Sleep(1100);
+ int randIndex = r.Next(0, filePaths.Count);
+ if (SubmitFileToServer(filePaths[randIndex]))
+ {
+ filePaths.RemoveAt(randIndex);
+ _AuditQueueDepth = filePaths.Count;
+ }
+ Thread.Sleep(1000);
+
+ if (filePaths.Count == 0)
+ break;
}
}
- else if (filePaths.Length >= 1)
- {
- SubmitFileToServer(filePaths[0]);
- Thread.Sleep(1100);
- }
- else
- {
- Thread.Sleep(5000);
- }
+
+ Thread.Sleep(5000);
}
catch (Exception ex)
{
@@ -345,7 +393,7 @@ static void BackgroundWorker()
/// Reads a file from the filesystem, converts it to an Audit, and pushes to cloud
///
///
- static void SubmitFileToServer(string fileName)
+ static bool SubmitFileToServer(string fileName)
{
try
{
@@ -355,6 +403,7 @@ static void SubmitFileToServer(string fileName)
{
File.Delete(fileName);
Log.WriteLine(LogType.Database, "AuditDb BackgroundWorker successfully submitted a file to cloud");
+ return true;
}
else
{
@@ -365,6 +414,8 @@ static void SubmitFileToServer(string fileName)
{
Log.WriteLine(LogType.Database, "AuditDb BackgroundWorker exception: " + ex.Message);
}
+
+ return false;
}
}
}
diff --git a/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.Designer.cs b/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.Designer.cs
index d2a6d36..a9e6d04 100644
--- a/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.Designer.cs
+++ b/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.Designer.cs
@@ -314,6 +314,7 @@ private void InitializeComponent()
this.MinimizeBox = false;
this.Name = "DlgQuery";
this.Text = "Audit Database Query Parameters";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DlgQuery_FormClosing);
this.Load += new System.EventHandler(this.DlgQuery_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
diff --git a/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.cs b/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.cs
index c87f505..30d53a4 100644
--- a/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.cs
+++ b/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgQuery.cs
@@ -31,6 +31,11 @@ private void DlgQuery_Load(object sender, EventArgs e)
UpdateButtonState();
}
+ private void DlgQuery_FormClosing(object sender, FormClosingEventArgs e)
+ {
+
+ }
+
private void UpdateButtonState()
{
if (TestGroups.Count == 0 || TestGroups.Count == 1)
@@ -72,9 +77,6 @@ private void button2_Click(object sender, EventArgs e)
{
TestGroups = AuditDb.QueryGroupsBySerialNumber(textBox2.Text, textBox1.Text);
- // Need to limit rate webservice rate to no more than one call per second
- Thread.Sleep(1000);
-
UpdateButtonState();
if (TestGroups.Count > 0)
{
@@ -222,5 +224,7 @@ private void LoadGuid(TextBox tb)
Log.WriteLine(LogType.Error, "An exception occured load a PID fron a file: " + ex.Message);
}
}
+
+
}
}
diff --git a/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgSettings.cs b/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgSettings.cs
index c0806c4..288dcba 100644
--- a/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgSettings.cs
+++ b/Tractor/Com.QuantAsylum.Tractor.Dialogs/DlgSettings.cs
@@ -50,7 +50,11 @@ private void DlgSettings_Load(object sender, EventArgs e)
textBox3.Text = Settings.DbSessionName;
textBox4.Text = Settings.ProductId.ToString();
textBox5.Text = Settings.AuditDbSessionName;
+
+ checkBox4.CheckedChanged -= checkBox4_CheckedChanged;
checkBox4.Checked = Settings.UseAuditDb;
+ checkBox4.CheckedChanged += checkBox4_CheckedChanged;
+
textBox6.Text = Settings.AuditDbEmail;
checkBox2.Checked = Settings.LockTestScreen;
textBox1.Text = Settings.Password;
diff --git a/Tractor/Com.QuantAsylum.Tractor.Tests/Other/MicCompareA01.cs b/Tractor/Com.QuantAsylum.Tractor.Tests/Other/MicCompareA01.cs
index f3b5f08..2fffca3 100644
--- a/Tractor/Com.QuantAsylum.Tractor.Tests/Other/MicCompareA01.cs
+++ b/Tractor/Com.QuantAsylum.Tractor.Tests/Other/MicCompareA01.cs
@@ -33,8 +33,6 @@ public MicCompareA01() : base()
{
Name = this.GetType().Name;
_TestType = TestTypeEnum.Other;
- if (FftSize < 32768)
- FftSize = 32768;
}
public override void DoTest(string title, out TestResult tr)
@@ -59,8 +57,8 @@ public override void DoTest(string title, out TestResult tr)
int passCount = 0;
if (CheckPhase)
{
- if (((IAudioAnalyzer)Tm.TestClass).LRVerifyPhase((int)FftSize / 4)) ++passCount;
- if (((IAudioAnalyzer)Tm.TestClass).LRVerifyPhase((int)FftSize / 4 + 300)) ++passCount;
+ if (((IAudioAnalyzer)Tm.TestClass).LRVerifyPhase((int)FftSize * 1024 / 4)) ++passCount;
+ if (((IAudioAnalyzer)Tm.TestClass).LRVerifyPhase((int)FftSize * 1024 / 4 + 300)) ++passCount;
if (passCount != 2)
passPhase = false;
}
@@ -88,7 +86,8 @@ public override string GetTestLimits()
public override string GetTestDescription()
{
- return "Compares a reference microphone to a test microphone. The difference is compared to a specified mask.";
+ return "Compares a reference microphone (left channel) to a test microphone (right channel). The difference (L-R) is " +
+ "displayed and compared to a specified mask.";
}
internal override int HardwareMask
diff --git a/Tractor/Constants.cs b/Tractor/Constants.cs
index ea8967c..330aab3 100644
--- a/Tractor/Constants.cs
+++ b/Tractor/Constants.cs
@@ -10,7 +10,7 @@ namespace Tractor
static class Constants
{
public static string TitleBarText = "QuantAsylum TRACTOR";
- public static readonly double Version = 0.993;
+ public static readonly double Version = 0.994;
public static string VersionSuffix = "";
public static double RequiredWebserviceVersion = 0.5;
diff --git a/Tractor/Form1.cs b/Tractor/Form1.cs
index 031ca53..8c18fe6 100644
--- a/Tractor/Form1.cs
+++ b/Tractor/Form1.cs
@@ -113,7 +113,7 @@ private void Form1_Load(object sender, EventArgs e)
SetTreeviewControls();
- Com.QuantAsylum.Tractor.Database.AuditDb.StartBackgroundWorker();
+ Com.QuantAsylum.Tractor.Database.AuditDb.StartBackgroundTask();
string[] args = Environment.GetCommandLineArgs();
if (args.Length >= 2)
@@ -494,7 +494,7 @@ private void newTestPlan_Click(object sender, EventArgs e)
AppSettings = new AppSettings();
AppSettingsDirty = true;
- UpdateTitleBar();
+ SettingsFile = "";
Type t = Type.GetType(AppSettings.TestClass);
Tm.TestClass = Activator.CreateInstance(t);
foreach (TestBase test in AppSettings.TestList)
diff --git a/Tractor/Maths.cs b/Tractor/Maths.cs
index cf404d4..b70fde2 100644
--- a/Tractor/Maths.cs
+++ b/Tractor/Maths.cs
@@ -8,21 +8,24 @@ namespace Tractor
{
static class Maths
{
- static public void StdDev(List doubles, out double average, out double stdDev)
+ static public void StdDev(List data, out double avg, out double stdDev)
{
- double avg = 0;
- average = 0;
- stdDev = 0;
- int count = doubles.Count();
- if (count > 1)
+ if (data.Count == 0)
+ throw new InvalidOperationException("There must be at least 1 data point in the array presented to StdDev");
+
+ if (data.Count == 1)
{
- avg = doubles.Average();
+ avg = data[0];
+ stdDev = 0;
+ return;
+ }
- double sum = doubles.Sum(d => (d - avg) * (d - avg));
+ // Can't use ref in anonymous method. Need to create mirror.
+ double average = data.Average();
+ double sum = data.Sum(d => (d - average) * (d - average));
- stdDev = Math.Sqrt(sum / (count - 1));
- average = avg;
- }
+ stdDev = Math.Sqrt(sum / (data.Count - 1));
+ avg = average;
}
}
}
diff --git a/Tractor/Releases.txt b/Tractor/Releases.txt
index f27c2ee..85dd510 100644
--- a/Tractor/Releases.txt
+++ b/Tractor/Releases.txt
@@ -1,4 +1,11 @@
-0.993
+0.994
+- Fixed bug where older-style audit records could get stuck and never upload to server
+- Fixed bug where stuck records hogged all the upload time and fresh records were ignored
+- Fixed bug so that AuditDb warning was only shown when first enabled instead of everytime you entered settings
+- Updated cloud server to 0.52
+- Updates to Mic Comparison to handle new Axis and FFT
+
+0.993
- Fixed bug where switching tests plans could result in inability to re-establish connection to QA401.
- Moved FFT sizes from bytes to kBytes. In older test-plans (pre 0.993) that are opened, they will be migrated automatically.
- EfficiencyA07 wil now work on single channel or both channels