tbf/TBF/BenchControl/TestMethods/S640Communication/S640CommForm.cs

992 lines
46 KiB
C#

///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Windows.Forms;
using log4net;
using Common;
using Config.Entities;
using TBF.Resources;
using TBF.BenchControl.Sequences;
using System.IO;
namespace TBF.BenchControl.TestMethods.S640Communication
{
public enum CommErr
{
None = 0,
CommFailed, /// 1
HeadDisabledByUser, /// 2
}
///
/// (Program.LocalSettings.OptoHeadsEnabled & (1L << ix))) == 0 . . opto head is disabled in configuration
/// optoheads[ix] == null . . . . . . . . . . . . . . . . . . . . . opto head is not part of the selected sensors path
/// optoHeads[ix].Disabled == true . . . . . . . . . . . . . . . . opto head was disabled by the user
///
public partial class S640CommForm : Form, GenericDevices.IHasCompleted
{
private static readonly ILog log = LogManager.GetLogger(typeof(S640CommForm));
protected static readonly ILog sirtDataLogger = LogManager.GetLogger("SirtData");
public const int UIBoxesCount = 40;
public static Color DisabledColor = Color.DarkGray;
public static Color OptoOKColor = Color.Green;
public static Color OptoNokColor = Color.Red;
public const string StartFileName = "Start.pro";
public const string EndFileName = "Ende.pro";
public const string ErrorFileName = "Error.dat";
enum Step
{
/// Start
WatchOptoHeads,
SaveStartPro,
EnterSNsAndAwaitResponseToStartPro,
AwaitResponseToStartPro,
/// End
EnterSNs,
SaveEndePro,
AwaitResponseToEndePro,
ConfirmError,
Idle,
}
DateTime startTime;
int startTimeSec;
// Set to 'true' when the form closes
public bool Completed { get { return formCompleted; } }
bool formCompleted;
bool forcedClose; /// Set in the forced close handler
/// <summary> Number of text boxes for serial numbers </summary>
public int WaterMetersCount;
int textBoxesCount;
///
bool[] enabledInConfiguration;
Label[] labels;
PictureBox[] pictures;
TextBox[] messages;
TextBox[] serialNumbers;
CheckBoxImage[] checkBoxes;
int[] ckbIndex; /// Initialized by ShuffleTextBoxes() ... to be used in the future in case of test benches with two lines
RegisterReaders.S640Stream.S640Stream[] optoHeads;
///
/// Parameters and current state of activities
///
DebugMode debugLevel;
int optoDataTimeout;
string fileExchangePath;
int fileExchangeTimeout;
bool enterSerialNumbers;
ProcParams pPars;
///
IList<S640Activity> activities;
IList<Test> tests;
///
int currentActivityIx;
///
Step step;
DateTime savedTimestamp;
System.Windows.Forms.Timer timer;
///
/// Used in Step.WatchOptoHeads, initially all zeros
///
int[] commOkLoopsCount;
/// <summary>
/// Parameterless constructor (without watermeters, threads)
/// </summary>
public S640CommForm()
{
InitializeComponent();
labels = new Label[UIBoxesCount]
{
wmLabel1, wmLabel2, wmLabel3, wmLabel4, wmLabel5, wmLabel6, wmLabel7, wmLabel8,
wmLabel9, wmLabel10, wmLabel11, wmLabel12, wmLabel13, wmLabel14, wmLabel15, wmLabel16,
wmLabel17, wmLabel18, wmLabel19, wmLabel20, wmLabel21, wmLabel22, wmLabel23, wmLabel24,
wmLabel25, wmLabel26, wmLabel27, wmLabel28, wmLabel29, wmLabel30, wmLabel31, wmLabel32,
wmLabel33, wmLabel34, wmLabel35, wmLabel36, wmLabel37, wmLabel38, wmLabel39, wmLabel40,
};
pictures = new PictureBox[UIBoxesCount]
{
pictureBox1, pictureBox2, pictureBox3, pictureBox4, pictureBox5,
pictureBox6, pictureBox7, pictureBox8, pictureBox9, pictureBox10,
pictureBox11, pictureBox12, pictureBox13, pictureBox14, pictureBox15,
pictureBox16, pictureBox17, pictureBox18, pictureBox19, pictureBox20,
pictureBox21, pictureBox22, pictureBox23, pictureBox24, pictureBox25,
pictureBox26, pictureBox27, pictureBox28, pictureBox29, pictureBox30,
pictureBox31, pictureBox32, pictureBox33, pictureBox34, pictureBox35,
pictureBox36, pictureBox37, pictureBox38, pictureBox39, pictureBox40,
};
messages = new TextBox[UIBoxesCount]
{
fromOptoTextBox1, fromOptoTextBox2, fromOptoTextBox3, fromOptoTextBox4, fromOptoTextBox5,
fromOptoTextBox6, fromOptoTextBox7, fromOptoTextBox8, fromOptoTextBox9, fromOptoTextBox10,
fromOptoTextBox11, fromOptoTextBox12, fromOptoTextBox13, fromOptoTextBox14, fromOptoTextBox15,
fromOptoTextBox16, fromOptoTextBox17, fromOptoTextBox18, fromOptoTextBox19, fromOptoTextBox20,
fromOptoTextBox21, fromOptoTextBox22, fromOptoTextBox23, fromOptoTextBox24, fromOptoTextBox25,
fromOptoTextBox26, fromOptoTextBox27, fromOptoTextBox28, fromOptoTextBox29, fromOptoTextBox30,
fromOptoTextBox31, fromOptoTextBox32, fromOptoTextBox33, fromOptoTextBox34, fromOptoTextBox35,
fromOptoTextBox36, fromOptoTextBox37, fromOptoTextBox38, fromOptoTextBox39, fromOptoTextBox40,
};
serialNumbers = new TextBox[UIBoxesCount]
{
textBox1, textBox2, textBox3, textBox4, textBox5, textBox6, textBox7, textBox8,
textBox9, textBox10, textBox11, textBox12, textBox13, textBox14, textBox15, textBox16,
textBox17, textBox18, textBox19, textBox20, textBox21, textBox22, textBox23, textBox24,
textBox25, textBox26, textBox27, textBox28, textBox29, textBox30, textBox31, textBox32,
textBox33, textBox34, textBox35, textBox36, textBox37, textBox38, textBox39, textBox40,
};
checkBoxes = new CheckBoxImage[UIBoxesCount]
{
checkBoxImage1, checkBoxImage2, checkBoxImage3, checkBoxImage4, checkBoxImage5,
checkBoxImage6, checkBoxImage7, checkBoxImage8, checkBoxImage9, checkBoxImage10,
checkBoxImage11, checkBoxImage12, checkBoxImage13, checkBoxImage14, checkBoxImage15,
checkBoxImage16, checkBoxImage17, checkBoxImage18, checkBoxImage19, checkBoxImage20,
checkBoxImage21, checkBoxImage22, checkBoxImage23, checkBoxImage24, checkBoxImage25,
checkBoxImage26, checkBoxImage27, checkBoxImage28, checkBoxImage29, checkBoxImage30,
checkBoxImage31, checkBoxImage32, checkBoxImage33, checkBoxImage34, checkBoxImage35,
checkBoxImage36, checkBoxImage37, checkBoxImage38, checkBoxImage39, checkBoxImage40,
};
ckbIndex = new int[UIBoxesCount]; /// Initialized by ShuffleTextBoxes() ... to be used in the future in case of test benches with two lines
}
/// <summary>
/// Constructor for one S640Communication test
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public S640CommForm(S640Activity activity, I640Cfg config, Generic.IProcedureParams procParams, Test test)
: this(new List<S640Activity> { activity }, config, procParams, new List<Test> { test })
{
}
/// <summary>
/// Constructor for multiple S640Communication tests
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public S640CommForm(IList<S640Activity> activities, I640Cfg config, Generic.IProcedureParams procParams, IList<Test> tests)
: this()
{
this.activities = activities;
debugLevel = config.DebugLevel;
optoDataTimeout = config.OptoDataTimeout;
fileExchangePath = string.IsNullOrEmpty(config.FileExchangePath) ? string.Empty : config.FileExchangePath;
fileExchangeTimeout = config.FileExchangeTimeout;
enterSerialNumbers = config.EnterSerialNumbers;
this.tests = tests;
this.pPars = procParams as ProcParams;
if (activities.Count != tests.Count)
{
throw new Exception("Something strange: activities.Count != tests.Count");
}
if (ProcessData.RegisterReaders.Length != ProcessData.BatchRslts.Batch.WaterMeters.Count)
{
throw new Exception("Something strange: RegisterReaders.Length != WaterMeters.Count");
}
if (activities.Count > 0)
{
ProcessData.RegisterReaders = StateMachine.GetMetersPath(tests[0]).RegisterReaders;
}
optoHeads = new RegisterReaders.S640Stream.S640Stream[ProcessData.RegisterReaders.Length];
///
for (int wmPos = 0; wmPos < ProcessData.RegisterReaders.Length; wmPos++)
{
optoHeads[wmPos] = ProcessData.RegisterReaders[wmPos] as RegisterReaders.S640Stream.S640Stream;
}
WaterMetersCount = ProcessData.RegisterReaders.Length;
ShuffleTextBoxes(WaterMetersCount, ProcessData.LineSize);
enabledInConfiguration = new bool[textBoxesCount];
for (int i = 0; i < textBoxesCount; i++)
{
enabledInConfiguration[i] = (optoHeads[i] != null) && ((Program.LocalSettings.OptoHeadsEnabled & (1L << i)) != 0L);
}
formCompleted = false;
StartForceCloseHandler();
}
/// <summary>
/// Make sure the layout of labels/text boxes on the screen
/// corresponds to the layout of watermeters of the test bench.
/// </summary>
/// <param name="wmsCount">Number of watermeters</param>
/// <param name="lineSize">Number of watermeters in one line</param>
void ShuffleTextBoxes(int wmsCount, int lineSize)
{
textBoxesCount = UIBoxesCount;
///
if (wmsCount < textBoxesCount && lineSize > 0)
{
int nrLines = (wmsCount + lineSize - 1) / lineSize;
int gap = (textBoxesCount - wmsCount) / nrLines;
int dest = 0;
for (int l = 0; l < nrLines; l++)
{
for (int i = 0; i < lineSize; i++)
{
labels[dest] = labels[l * lineSize + l * gap + i];
pictures[dest] = pictures[l * lineSize + l * gap + i];
messages[dest] = messages[l * lineSize + l * gap + i];
serialNumbers[dest] = serialNumbers[l * lineSize + l * gap + i];
checkBoxes[dest] = checkBoxes[l * lineSize + l * gap + i];
ckbIndex[l * lineSize + l * gap + i] = dest;
dest++;
}
}
textBoxesCount = wmsCount;
}
for (int i = 0; i < textBoxesCount; i++)
{
labels[i].Visible = pictures[i].Visible = messages[i].Visible = checkBoxes[i].Visible = true;
if (optoHeads[i] != null) labels[i].Text = (i + 1).ToString();
}
///
/// Resize this form to fit enabled controls
///
//int xMax = 0;
//int yMax = 0;
//for (int i = 0; i < textBoxesCount; i++)
//{
// if (messages[i].Left + messages[i].Width > xMax) xMax = messages[i].Left + messages[i].Width;
// if (messages[i].Top + messages[i].Height > yMax) yMax = messages[i].Top + messages[i].Height;
//}
/////Width = xMax + 30;
//Height = yMax + 50;
}
private void S640CommForm_Load(object sender, EventArgs e)
{
Localize();
///
/// Set location and checkbox states to values stored in local settings
///
TBF.LocalSettings ls = Program.LocalSettings;
Left = (ls.S640CommFormLeft != 0) ? ls.S640CommFormLeft : 150;
Top = (ls.S640CommFormTop != 0) ? ls.S640CommFormTop : 150;
///
/// Set checkbox states accroding to optoHeads[i].Disabled states
///
for (int i = 0; i < textBoxesCount; i++)
{
if (!enabledInConfiguration[i])
{
/// Opto head is disabled in configuration
checkBoxes[i].Checked = false;
checkBoxes[i].Enabled = false;
pictures[i].BackColor = DisabledColor;
messages[i].Text = Strings.Opto_head_is_disabled_in_configuration;
}
else if ((i >= ProcessData.BatchRslts.Batch.WaterMeters.Count) ||
ProcessData.BatchRslts.Batch.WaterMeters[i] == null ||
ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled)
{
/// Opto head was disabled by an operator
checkBoxes[i].Checked = false;
checkBoxes[i].Enabled = false;
pictures[i].BackColor = DisabledColor;
messages[i].Text = Strings.Head_was_disabled_by_the_user;
}
else
{
/// Opto head is enabled
checkBoxes[i].Checked = true;
checkBoxes[i].Enabled = true;
messages[i].Text = "---";
}
/// Reset opto-data indication
pictures[i].BackColor = OptoNokColor;
messages[i].Enabled = true;
if (enterSerialNumbers)
{
serialNumbers[i].Visible = enabledInConfiguration[i];
serialNumbers[i].Enabled = (activities[currentActivityIx] == S640Activity.End);
}
}
startTimeSec = StateMachine.Time;
StartActivity(0);
timer = new System.Windows.Forms.Timer();
timer.Interval = 300; // ms
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void Localize()
{
/// Close/Continue button is localized in other code
Text = Strings.Water_Meter_States;
retryButton.Text = Strings.RetryBtnText;
sampleLabel1.Text = Strings.Optical_head_is_placed_correctly;
sampleLabel2.Text = Strings.Missing_opto_pulses;
samplePictureBox1.BackColor = OptoOKColor;
samplePictureBox2.BackColor = OptoNokColor;
}
void StartActivity(int acIx)
{
startTime = DateTime.Now;
activityLabel.Text = activities[acIx].ToString();
currentActivityIx = acIx;
step = (activities[acIx] == S640Activity.Start) ? Step.WatchOptoHeads : enterSerialNumbers ? Step.EnterSNs : Step.SaveEndePro;
closeButton.Visible = false;
retryButton.Visible = false;
responseTextBox.Text = string.Empty;
if (step == Step.WatchOptoHeads)
{
/// Start watching optical heads --> reset OK loop counters
if (commOkLoopsCount == null || commOkLoopsCount.Length != textBoxesCount)
{
commOkLoopsCount = new int[textBoxesCount];
}
for (int i = 0; i < textBoxesCount; i++) commOkLoopsCount[i] = 0;
progressBar1.Visible = (optoDataTimeout != 0);
progressBar1.Minimum = 0;
progressBar1.Maximum = Math.Max(optoDataTimeout, 1);
progressBar1.Value = 0;
}
TBF.UiBridge.TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 10, 0, 140, 0, 0, 0 });
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[acIx], Progress.JustStarted));
sirtDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data
sirtDataLogger.WarnFormat("Activity = {0}", activities[acIx]);
sirtDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data
}
/// <summary>
/// Invoked every 0.5 sec.
/// </summary>
void timer_Tick(object sender, EventArgs args)
{
///--------------------------------------------------------------------------
if (step == Step.WatchOptoHeads)
{
long optoHeadsConfig = Program.LocalSettings.OptoHeadsEnabled;
bool allOK = true;
for (int i = 0; i < textBoxesCount; i++)
{
if ((optoHeadsConfig & (1L << i)) == 0 || optoHeads[i] == null)
{
/// Opto head is disabled in configuration
checkBoxes[i].Checked = false;
checkBoxes[i].Enabled = false;
pictures[i].BackColor = DisabledColor;
messages[i].Text = Strings.Opto_head_is_disabled_in_configuration;
}
else if (!checkBoxes[i].Checked)
{
/// Opto head was disabled by the user
pictures[i].BackColor = DisabledColor;
messages[i].Text = Strings.Head_was_disabled_by_the_user;
}
else
{
/// Opto head is enabled
checkBoxes[i].Checked = true;
checkBoxes[i].Enabled = true;
if (optoHeads[i].PcbNumber == 0)
{
/// Communication is NOK right now
pictures[i].BackColor = OptoNokColor;
messages[i].Text = "---";
commOkLoopsCount[i] = 0;
allOK = false;
}
else
{
/// Communication is OK right now
messages[i].Text = string.Format("pcb={0} radio={1}", optoHeads[i].PcbNumber, optoHeads[i].RadioAddress);
pictures[i].BackColor = OptoOKColor;
/// increment commOkLoopsCount[i] and check its value, considered OK just after 5 repeats
commOkLoopsCount[i] = commOkLoopsCount[i] + 1;
if (commOkLoopsCount[i] < 5) allOK = false;
}
}
}
if (allOK)
{
log.WarnFormat("allOk");
/// Update water meter properties
for (int i = 0; i < textBoxesCount; i++)
{
if (i < ProcessData.BatchRslts.Batch.WaterMeters.Count &&
ProcessData.BatchRslts.Batch.WaterMeters[i] != null &&
!ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled)
{
if ((optoHeadsConfig & (1L << i)) != 0 && checkBoxes[i].Checked && optoHeads[i] != null)
{
/// Save PCB Number of the water meter
ProcessData.BatchRslts.Batch.WaterMeters[i].SerialNrAux = optoHeads[i].PcbNumber.ToString(); /// PCB number (640)
ProcessData.BatchRslts.Batch.WaterMeters[i].RadioAddress = optoHeads[i].RadioAddress; /// Radio address (640)
}
else
{
/// Disable the water meter
ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled = true;
}
}
}
step = Step.SaveStartPro;
}
else if (optoDataTimeout != 0 && DateTime.Now - startTime > new TimeSpan(0, 0, optoDataTimeout))
{
activityLabel.Text = String.Format("{0}: {1} {2}", Strings.Start, Strings.Optical_heads, Strings.Timeout);
log.Error("Start: Optical heads timeout");
step = Step.ConfirmError;
}
else if (optoDataTimeout != 0)
{
progressBar1.Value = (int)Math.Round((DateTime.Now - startTime).TotalSeconds);
}
}
///--------------------------------------------------------------------------
else if (step == Step.SaveStartPro)
{
activityLabel.Text = string.Format("Start: SIRT Communication");
int count = 0;
for (int i = 0; i < textBoxesCount; i++)
{
if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null) count++;
}
log.DebugFormat("Saving '{0}' file: {1} water meters found", StartFileName, count);
if (debugLevel == DebugMode.Normal)
{
SaveProFile(Path.Combine(fileExchangePath, StartFileName), S640Activity.Start, optoHeads);
}
SaveProFile(Path.Combine(Constants.SirtLogDir,
string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, StartFileName)),
S640Activity.Start, optoHeads);
savedTimestamp = DateTime.Now;
progressBar1.Visible = (fileExchangeTimeout != 0);
progressBar1.Minimum = 0;
progressBar1.Maximum = Math.Max(fileExchangeTimeout, 1);
progressBar1.Value = 0;
for (int i = 0; i < textBoxesCount; i++) { messages[i].Enabled = false; }
if (enterSerialNumbers)
{
for (int i = 0; i < textBoxesCount; i++) { serialNumbers[i].Enabled = true; }
serialNumbers[0].Focus();
closeButton.Visible = true;
closeButton.Enabled = true;
closeButton.Text = Strings.Continue;
step = Step.EnterSNsAndAwaitResponseToStartPro;
}
else
{
step = Step.AwaitResponseToStartPro;
}
}
///--------------------------------------------------------------------------
else if (step == Step.EnterSNsAndAwaitResponseToStartPro)
{
/// Don't do anything, move to the next step in closeButton_Click(...)
}
///--------------------------------------------------------------------------
else if (step == Step.AwaitResponseToStartPro)
{
if (!File.Exists(Path.Combine(fileExchangePath, StartFileName)))
{
/// File disappeared in time
UpdateFirstTestResult(tests);
UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Completed));
step = Step.Idle;
NormalClose();
}
else if (File.Exists(Path.Combine(fileExchangePath, ErrorFileName)))
{
/// Error file detected
string destination = Path.Combine(Constants.SirtLogDir,
string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, ErrorFileName));
File.Move(Path.Combine(fileExchangePath, ErrorFileName), destination);
ParseFileAndDisplayErrors(destination);
File.Delete(Path.Combine(fileExchangePath, StartFileName));
activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.Start, Strings.Error);
step = Step.ConfirmError;
}
else if (fileExchangeTimeout != 0 && DateTime.Now - savedTimestamp > new TimeSpan(0, 0, fileExchangeTimeout))
{
activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.Start, Strings.Timeout);
log.Error("Start: SIRT timeout");
step = Step.ConfirmError;
}
else if (fileExchangeTimeout != 0)
{
progressBar1.Value = (int)Math.Round((DateTime.Now - savedTimestamp).TotalSeconds);
}
else
{
progressBar1.Visible = false;
closeButton.Visible = true;
retryButton.Visible = true;
}
}
///--------------------------------------------------------------------------
else if (step == Step.EnterSNs)
{
/// Don't do anything, move to the next step in closeButton_Click(...)
}
///--------------------------------------------------------------------------
else if (step == Step.SaveEndePro)
{
activityLabel.Text = string.Format("End: SIRT Communication");
log.DebugFormat("Saving '{0}' file", EndFileName);
if (debugLevel == DebugMode.Normal)
{
SaveProFile(Path.Combine(fileExchangePath, EndFileName), S640Activity.End, optoHeads);
}
SaveProFile(Path.Combine(Constants.SirtLogDir,
string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, EndFileName)),
S640Activity.Start, optoHeads);
savedTimestamp = DateTime.Now;
progressBar1.Visible = (fileExchangeTimeout != 0);
progressBar1.Minimum = 0;
progressBar1.Maximum = Math.Max(fileExchangeTimeout, 1);
progressBar1.Value = 0;
step = Step.AwaitResponseToEndePro;
}
///--------------------------------------------------------------------------
else if (step == Step.AwaitResponseToEndePro)
{
if (!File.Exists(Path.Combine(fileExchangePath, EndFileName)))
{
/// File disappeared in time
UpdateFirstTestResult(tests);
UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Completed));
step = Step.Idle;
NormalClose();
}
else if (File.Exists(Path.Combine(fileExchangePath, ErrorFileName)))
{
/// Error.dat file detected
string destination = Path.Combine(Constants.SirtLogDir,
string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, ErrorFileName));
File.Move(Path.Combine(fileExchangePath, ErrorFileName), destination);
ParseFileAndDisplayErrors(destination);
File.Delete(Path.Combine(fileExchangePath, EndFileName));
activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.End, Strings.Error);
step = Step.ConfirmError;
}
else if (fileExchangeTimeout != 0 && DateTime.Now - savedTimestamp > new TimeSpan(0, 0, fileExchangeTimeout))
{
activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.End, Strings.Timeout);
log.Error("End: SIRT timeout");
step = Step.ConfirmError;
}
else if (fileExchangeTimeout != 0)
{
progressBar1.Value = (int)Math.Round((DateTime.Now - savedTimestamp).TotalSeconds);
}
else
{
closeButton.Visible = true;
}
}
///--------------------------------------------------------------------------
else if (step == Step.ConfirmError)
{
progressBar1.Visible = false;
retryButton.Visible = true;
closeButton.Visible = true;
closeButton.Enabled = true;
closeButton.Text = Strings.CloseBtnText;
}
///--------------------------------------------------------------------------
else if (step == Step.Idle)
{
/// Just wait until this form is closed
}
else
{
/// Invalid step
log.ErrorFormat("Unexpected step: activity = {0} step = {1}", activities[currentActivityIx], step);
}
}
void SaveProFile(string filename, S640Activity activity, IList<RegisterReaders.S640Stream.S640Stream> optoHeads)
{
string variant = string.IsNullOrEmpty(ProcessData.BatchRslts.Batch.WatermetersStr) ? string.Empty : ProcessData.BatchRslts.Batch.WatermetersStr;
int count = 0;
string purchaseOrder = null;
for (int i = 0; i < optoHeads.Count; i++)
{
if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null)
{
count++;
if (purchaseOrder == null && !string.IsNullOrEmpty(ProcessData.BatchRslts.Batch.WaterMeters[i].PurchaseOrder))
{
purchaseOrder = ProcessData.BatchRslts.Batch.WaterMeters[i].PurchaseOrder;
}
}
}
using (StreamWriter file = new StreamWriter(filename))
{
file.WriteLine("<?xml version=\"1.0\" ?>");
file.WriteLine("<Batch xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">");
file.WriteLine(string.Format(" <TimeStamp>{0}</TimeStamp>", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz")));
file.WriteLine(string.Format(" <Bench Mode=\"{0}\" Count=\"{1}\" TestBenchID=\"{2}\" TestBenchName=\"{3}\" EncyptionKeyMode=\"{4}\" />",
(activity == S640Activity.Start) ? "Start" : "End",
count,
ProcessData.BenchInfo.TestBenchId,
ProcessData.BenchInfo.TestBenchName,
"SensusKey"));
file.WriteLine(string.Format(" <OrderData Variantencode=\"{0}\" OrderNo=\"{1}\" ModulParameter=\"{2}\" />",
variant, (purchaseOrder != null) ? purchaseOrder : string.Empty, pPars.ModuleParameter));
file.WriteLine(" <Meters>");
for (int i = 0; i < optoHeads.Count; i++)
{
if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null)
{
if (activity == S640Activity.Start)
{
file.WriteLine(string.Format(" <Meter RadioAddress=\"{0}\" MeterNumber=\"{0}\" CustomerText=\"\" NewRadioAddress=\"{0}\" PCBNumber=\"{1}\" EncyptionKey=\"\" />",
optoHeads[i].RadioAddress.ToString(),
optoHeads[i].PcbNumber.ToString()));
}
else if (activity == S640Activity.End)
{
file.WriteLine(string.Format(" <Meter RadioAddress=\"{0}\" MeterNumber=\"{1}\" CustomerText=\"{1}\" NewRadioAddress=\"{2}\" PCBNumber=\"{3}\" EncyptionKey=\"\" />",
optoHeads[i].RadioAddress.ToString(),
optoHeads[i].RadioAddress.ToString(), /// TODO: Here should be the assigned serial number
optoHeads[i].RadioAddress.ToString(), /// TODO: Here should be the new radio address
optoHeads[i].PcbNumber.ToString()));
}
}
}
file.WriteLine(" </Meters>");
file.WriteLine(string.Format(" <Metro Enable=\"{0}\" PulseRatePiston=\"{1}\" PulseRateLED=\"{2}\" OffsetFactor=\"{3}\" FactoryCalibration=\"{4}\" Units=\"{5}\" MeterSize=\"{6}\" OffsetTime=\"{7}\" />",
B2S(pPars.MetroEnable),
pPars.PulseRatePiston.ToString("F3", CultureInfo.InvariantCulture),
pPars.PulseRateLed.ToString(CultureInfo.InvariantCulture),
pPars.OffsetFactor.ToString(CultureInfo.InvariantCulture),
pPars.FactoryCalibration,
pPars.Units,
pPars.MeterSize,
pPars.OffsetTime));
file.WriteLine(string.Format(" <NewRead Enable=\"{0}\" NewRead=\"{1}\" />", B2S(pPars.NewReadEnable), pPars.NewRead));
file.WriteLine(string.Format(" <TransInterval Enable=\"{0}\" Interval=\"{1}\" />", B2S(pPars.TransIntervalEnable), pPars.TransInterval));
file.WriteLine(string.Format(" <LatInterval Enable=\"{0}\" Interval=\"{1}\" />", B2S(pPars.LatIntervalEnable), pPars.LatInterval));
file.WriteLine(string.Format(" <ResetAlarm Enable=\"{0}\" />", B2S(pPars.ResetAlarmEnable)));
file.WriteLine(string.Format(" <MetrologyTestMode Enable=\"{0}\" Hours=\"{1}\" />", B2S(pPars.MetrologyTestModeEnable), pPars.MetrologyTestModeHours));
file.WriteLine(string.Format(" <OpticalTeleg Enable=\"{0}\" Minutes=\"{1}\" />", B2S(pPars.OpticalTelegramEnable), pPars.OpticalTelegramMinutes));
file.WriteLine(string.Format(" <ChangeRadio Enable=\"{0}\" />", B2S(pPars.ChangeRadioEnable)));
file.WriteLine(string.Format(" <ChangeMeterID Enable=\"{0}\" />", B2S(pPars.ChangeMeterIDEnable)));
file.WriteLine(string.Format(" <SoftSeal Enable=\"false\" />", B2S(pPars.SoftSealEnable)));
file.WriteLine(string.Format(" <GoToSleep Enable=\"{0}\" />", B2S(pPars.GoToSleepEnable)));
file.WriteLine(string.Format(" <SaveDB Enable=\"{0}\" />", B2S(pPars.SaveDBEnable)));
file.WriteLine("</Batch>");
}
}
/// <summary>
/// Boolean to lowercase string
/// </summary>
string B2S(bool b)
{
return b ? "true" : "false";
}
void ParseFileAndDisplayErrors(string fileName)
{
log.ErrorFormat("ParseFileAndDisplayErrors(\"{0}\")", fileName);
string message = File.ReadAllText(fileName);
responseTextBox.Text = message;
}
/// <summary>
/// Update test result representing RFID communication success/failure
/// </summary>
/// <param name="test"></param>
void UpdateFirstTestResult(IList<Config.Entities.Test> tests, bool commFailed = false)
{
DateTime endTime = DateTime.Now;
int testTime = StateMachine.Time - startTimeSec;
if (!tests.Contains(StateMachine.TestInstances[0].Test))
{
tests.Insert(0, StateMachine.TestInstances[0].Test); /// Add RFID test as the 1st item
}
foreach (var test in tests)
{
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(test.Name, test.Part);
if (tstRslt != null)
{
Results.Utils.GetCounterStates(tstRslt, Program.LocalSettings.Counters);
/// Auxiliary results ... not required
/// Main results
tstRslt.MethodClass = TbfComponents.FindComponent(test.Method).ClassName;
tstRslt.TestDone = true;
tstRslt.StartTime = tstRslt.Batch.StartTime;
tstRslt.EndTime = endTime;
tstRslt.FlowSetTime = 0;
tstRslt.MassOfEvapWater = 0;
tstRslt.TestTime += testTime; /// [s] total communication time of all tests
for (int i = 0; i < textBoxesCount; i++)
{
Results.Entities.MeterTestRslt meterRslt =
ProcessData.BatchRslts.GetMeterTestRslt(test.Name, i, Common.CompoundMeterId.Single);
if (meterRslt != null && (i < ProcessData.BatchRslts.Batch.WaterMeters.Count) &&
ProcessData.BatchRslts.Batch.WaterMeters[i] != null &&
!ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled)
{
if ((Program.LocalSettings.OptoHeadsEnabled & (1L << i)) != 0 &&
optoHeads[i] != null &&
!commFailed)
{
meterRslt.TestDone = true;
meterRslt.Passed = true;
}
else
{
meterRslt.TestDone = true;
meterRslt.Passed = false;
}
}
}
}
}
}
private void closeButton_Click(object sender, EventArgs e)
{
if (step == Step.EnterSNsAndAwaitResponseToStartPro)
{
UpdateSerialNumbers();
step = Step.AwaitResponseToEndePro;
closeButton.Visible = false;
}
else if (step == Step.EnterSNs)
{
UpdateSerialNumbers();
step = Step.SaveEndePro;
closeButton.Visible = false;
}
else
{
log.Error("User is closing this form, communication failed");
UpdateFirstTestResult(tests, true);
UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Aborted));
NormalClose();
}
}
private void UpdateSerialNumbers()
{
/// Update water meter properties
for (int i = 0; i < textBoxesCount; i++)
{
serialNumbers[i].Enabled = false;
if (i < ProcessData.BatchRslts.Batch.WaterMeters.Count &&
ProcessData.BatchRslts.Batch.WaterMeters[i] != null &&
!ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled &&
enabledInConfiguration[i])
{
/// Save brass water meter body serial number
ProcessData.BatchRslts.Batch.WaterMeters[i].SerialNr = serialNumbers[i].Text;
}
}
}
private void NormalClose()
{
if (Program.LocalSettings.S640CommFormLeft != Location.X ||
Program.LocalSettings.S640CommFormTop != Location.Y)
{
/// Update local settings
Program.LocalSettings.S640CommFormLeft = Location.X;
Program.LocalSettings.S640CommFormTop = Location.Y;
Program.LocalSettings.Save();
}
formCompleted = true;
DialogResult = DialogResult.OK;
Close();
}
#region Forced close handling
public void StartForceCloseHandler()
{
UiBridge.Bridge.CloseModelessFormHandler += delegate(object sender, EventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<EventArgs>(OnForceClose), sender, args); }
else OnForceClose(sender, args);
};
}
void OnForceClose(object sender, EventArgs args)
{
forcedClose = true;
DialogResult = DialogResult.Cancel;
Close();
}
#endregion
private void S640CommForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!forcedClose && !formCompleted)
{
e.Cancel = true;
}
}
private void retryButton_Click(object sender, EventArgs e)
{
if (step == Step.ConfirmError)
{
StartActivity(0);
}
}
private void textBox1_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox1); }
private void textBox2_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox2); }
private void textBox3_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox3); }
private void textBox4_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox4); }
private void textBox5_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox5); }
private void textBox6_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox6); }
private void textBox7_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox7); }
private void textBox8_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox8); }
private void textBox9_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox9); }
private void textBox10_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox10); }
private void textBox11_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox11); }
private void textBox12_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox12); }
private void textBox13_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox13); }
private void textBox14_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox14); }
private void textBox15_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox15); }
private void textBox16_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox16); }
private void textBox17_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox17); }
private void textBox18_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox18); }
private void textBox19_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox19); }
private void textBox20_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox20); }
private void textBox21_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox21); }
private void textBox22_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox22); }
private void textBox23_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox23); }
private void textBox24_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox24); }
private void textBox25_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox25); }
private void textBox26_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox26); }
private void textBox27_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox27); }
private void textBox28_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox28); }
private void textBox29_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox29); }
private void textBox30_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox30); }
private void textBox31_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox31); }
private void textBox32_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox32); }
private void textBox33_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox33); }
private void textBox34_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox34); }
private void textBox35_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox35); }
private void textBox36_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox36); }
private void textBox37_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox37); }
private void textBox38_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox38); }
private void textBox39_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox39); }
private void textBox40_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox40); }
/// <summary>
/// Process a key press within any enabled text boxe
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <param name="currentFocusOwner">TextBox control which received the event</param>
private void ProcKeyPress(object sender, KeyPressEventArgs e, TextBox currentFocusOwner)
{
if (e.KeyChar == '\r')
{
/// Process <enter> key ..... Next text field
if (textBoxesCount < 2) return; /// There is just one enabled textBox
for (int i = 0; i < textBoxesCount; i++)
{
if (serialNumbers[i] == currentFocusOwner)
{
int nextIx = i;
do
{
nextIx = (++nextIx) % textBoxesCount;
}
while (!enabledInConfiguration[nextIx]);
/// Change focus to the next enabled text box
serialNumbers[nextIx].Focus();
return;
}
}
}
}
}
}