iPerlCommunication simultaneously with purging, STOP button function fixed, version 1.5.106

This commit is contained in:
Milan Hanajik 2015-09-04 13:49:04 +02:00
parent 7827fa4e5b
commit d5cb6ca71b
13 changed files with 474 additions and 239 deletions

View File

@ -0,0 +1,22 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
///
using System;
namespace TBF.BenchControl.GenericDevices
{
public interface ISimultTestMethod : ITestMethod
{
/// <summary>
/// True = execute this test method (communication with the water meter, etc.) simultaneously
/// with the previous step or with purging
/// </summary>
bool SimultWithPrevious { get; }
/// <summary>
/// True = execute this test method (communication with the water meter, etc.) simultaneously
/// with the next step or with emptying
/// </summary>
bool SimultWithNext { get; }
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using log4net;
using TBF.UiBridge;
using TBF.BenchControl;
using TBF.BenchControl.Operations;
using TBF.BenchControl.GenericDevices;
using TBF.Boxes;
@ -19,6 +20,39 @@ namespace TBF.BenchControl.Sequences
public override string ToString() { return "Sequences.MainSeq"; }
System.Windows.Forms.Form modelessDlg;
///
delegate void iPerlCommFormDlgt(MainSeq myRef, Generic.IComponentCfg cfg, IList<Generic.ITestParams> multiTestParams);
///
void OpenIPerlCommForm(MainSeq myRef, Generic.IComponentCfg cfg, IList<Generic.ITestParams> multiTestParams)
{
/// 1st argument
IList<GenericDevices.IWaterMeter> wMtrs = new List<GenericDevices.IWaterMeter>();
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is GenericDevices.IWaterMeter) wMtrs.Add(rr as GenericDevices.IWaterMeter);
}
/// 2nd argument
TestMethods.iPerlCommunication.TestMethodCfg iPerlCfg = cfg as TestMethods.iPerlCommunication.TestMethodCfg;
/// 3rd argument
IList<TestMethods.iPerlCommunication.iPerlCommunicationParams> iPerlCommParams = new List<TestMethods.iPerlCommunication.iPerlCommunicationParams>();
foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as TestMethods.iPerlCommunication.iPerlCommunicationParams);
myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(wMtrs, iPerlCfg, iPerlCommParams);
myRef.modelessDlg.Show();
}
void CloseIPerlCommForm()
{
UiBridge.Bridge.OnCloseModelessForm(this, null);
modelessDlg = null;
}
/// <summary> Constructor </summary>
public MainSeq()
{
@ -39,6 +73,10 @@ namespace TBF.BenchControl.Sequences
Selection selection;
bool benchFilled = false;
int simultWithPurgingCount = 0;
Generic.IComponentCfg simultWithPurgingCfg;
IList<Generic.ITestParams> simultWithPurgingParams;
StateMachine.LoadProcedure(true); // TODO: Implement as an operation so that the worker thread is not blocked
Bridge.Bench2UI(ButtonsEtc.StopBtnEn);
@ -211,13 +249,85 @@ namespace TBF.BenchControl.Sequences
fill_the_bench:
/// Purge - Begin
switch (Transition(purgeBegin, TransitionContext.PurgeBegin))
///
/// Analyze whether there are steps (e.g. iPerl communication) to be done simultaneously with purging
///
simultWithPurgingCount = 0;
simultWithPurgingCfg = null;
simultWithPurgingParams = new List<Generic.ITestParams>();
foreach (var test in StateMachine.Tests)
{
case Event.Error: goto error;
case Event.UiCmdStop: goto stop;
Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method);
ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod;
if (simultTest == null) break;
sensPath = StateMachine.GetMetersPath(test);
testMethodComp.Cfg.UpdateTestParams(test);
if (!simultTest.SimultWithPrevious ||
((simultWithPurgingCount > 0) && (simultTest.Cfg != simultWithPurgingCfg)))
{
break;
}
if (simultWithPurgingCount == 0) simultWithPurgingCfg = simultTest.Cfg;
simultWithPurgingParams.Add(testMethodComp.Cfg.GetTestParams() as Generic.ITestParams);
simultWithPurgingCount++;
}
if (simultWithPurgingCount > 0)
{
/// Make sure the entry form is closed
if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop;
OpenIPerlCommForm(this, simultWithPurgingCfg, simultWithPurgingParams);
}
///
/// Purging @ cycle start
///
Event evt = Transition(purgeBegin, TransitionContext.PurgeBegin);
///
switch (evt)
{
case Event.Error:
if (simultWithPurgingCount > 0) CloseIPerlCommForm();
goto error;
case Event.UiCmdStop:
if (simultWithPurgingCount > 0) CloseIPerlCommForm();
goto stop;
default:
break;
}
///
/// Wait until iPerl communications are completed
///
bool completed = (modelessDlg is GenericDevices.IHasCompleted)
&& (modelessDlg as GenericDevices.IHasCompleted).Completed;
if (!completed)
{
State.Create("MainSeq : Wait until the entry form is closed")
.AddOperation(checkUiOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.UiCmdStop))
{
CloseIPerlCommForm();
goto stop;
}
completed = (modelessDlg is GenericDevices.IHasCompleted)
&& (modelessDlg as GenericDevices.IHasCompleted).Completed;
}
while (!completed);
}
assume_bench_filled:
benchFilled = true;
@ -253,9 +363,11 @@ namespace TBF.BenchControl.Sequences
if (selection == Selection.Cycle)
{
TimeEstimateTotal = 0;
foreach (var test in StateMachine.Tests)
{
TimeEstimateTotal += (test.Repeats * (test.TstTime + 10.0f));
for (int i = simultWithPurgingCount; i < StateMachine.Tests.Count; i++)
{
Entities.Test test = StateMachine.Tests[i];
TimeEstimateTotal += (test.Repeats * (test.TstTime + 10.0f));
/// Try to fetch all test paths and transitions
/// to detect configuration errors as early as possible.
@ -271,18 +383,20 @@ namespace TBF.BenchControl.Sequences
}
TimeEstimateBeginRpts = 0;
foreach (var test in StateMachine.Tests)
{
/// Fetch the test paths and transitions
string errorMsg;
if (!StateMachine.GetPaths(test, out inPath, out benchPath,
out outPath, out sensPath,
out transitionBefore, out transitionAfter,
out errorMsg))
{
UiBridge.Bridge.OnError(this, errorMsg);
for (int i = simultWithPurgingCount; i < StateMachine.Tests.Count; i++)
{
Entities.Test test = StateMachine.Tests[i];
/// Fetch the test paths and transitions
string errorMsg;
if (!StateMachine.GetPaths(test, out inPath, out benchPath,
out outPath, out sensPath,
out transitionBefore, out transitionAfter,
out errorMsg))
{
UiBridge.Bridge.OnError(this, errorMsg);
goto select_cycle_or_test;
}
}
/// Update format for the water mass
mass.Format = outPath.Balance.Format;
@ -290,20 +404,20 @@ namespace TBF.BenchControl.Sequences
endMass.Format = outPath.Balance.Format;
TimeEstimateOneTest = test.TstTime + 10.0f;
//--------------------------------------------------------------
//--------------------------------------------------------------
ITestMethod testMethodSequence = TbfComponents.FindComponent(test.Method) as ITestMethod;
if (testMethodSequence != null && testMethodSequence.CanTest(StateMachine.Procedure.MetersKind))
{
StateMachine.LoadTestParams(test);
if (BenchInfo != null && sensPath.RegisterReaders != null)
{
foreach (var rr in sensPath.RegisterReaders)
if (rr is WaterMeters.iPerl.WaterMeter)
(rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchId;
}
if (BenchInfo != null && sensPath.RegisterReaders != null)
{
foreach (var rr in sensPath.RegisterReaders)
if (rr is WaterMeters.iPerl.WaterMeter)
(rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchId;
}
e = testMethodSequence.Execute(test);
e = testMethodSequence.Execute(test);
if (e.Contains(Event.ConfigurationError)) goto select_cycle_or_test;
if (e.Contains(Event.Error)) goto error;

View File

@ -416,7 +416,6 @@ namespace TBF.BenchControl
pfeed = null;
pben = null;
pout = null;
pmtrs = null;
transitionBefore = null;
transitionAfter = null;
@ -435,22 +434,7 @@ namespace TBF.BenchControl
if (test.OutputPath == path.Name) { pout = new OutputPath(path, components); break; }
}
foreach (var path in metersPaths)
{
if (test.MetersPath == path.Name) { pmtrs = new MetersPath(path, components); break; }
}
if (pmtrs != null)
{
int count = Math.Min(Program.WMsCount, pmtrs.RegisterReaders.Length);
for (int i = 0; i < count; i++)
{
if ((pmtrs.RegisterReaders[i] != null) &&
(pmtrs.RegisterReaders[i].Cfg.DebugLevel == Entities.DebugMode.DetectedOff))
{
pmtrs.RegisterReaders[i] = null;
}
}
}
pmtrs = GetMetersPath(test);
foreach (var tr in TransitionSequences)
{
@ -480,6 +464,33 @@ namespace TBF.BenchControl
return true;
}
/// <summary>
/// Updates paths based on the selected test
/// </summary>
public static MetersPath GetMetersPath(Entities.Test test)
{
MetersPath pmtrs = null;
foreach (var path in metersPaths)
{
if (test.MetersPath == path.Name) { pmtrs = new MetersPath(path, components); break; }
}
if (pmtrs != null)
{
int count = Math.Min(Program.WMsCount, pmtrs.RegisterReaders.Length);
for (int i = 0; i < count; i++)
{
if ((pmtrs.RegisterReaders[i] != null) &&
(pmtrs.RegisterReaders[i].Cfg.DebugLevel == Entities.DebugMode.DetectedOff))
{
pmtrs.RegisterReaders[i] = null;
}
}
}
return pmtrs;
}
/// <summary>
/// Stops the state machine (and the worker thread)
/// </summary>

View File

@ -10,7 +10,7 @@ using TBF.BenchControl;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class TestMethod : ComponentBase, GenericDevices.ITestMethod, Generic.IDevice
public class TestMethod : ComponentBase, GenericDevices.ISimultTestMethod, Generic.IDevice
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
@ -19,6 +19,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
readonly TestMethodCfg testMethodCfg;
public bool SimultWithPrevious { get { return testMethodCfg.TestParams.SimultWithPrevious; } }
public bool SimultWithNext { get { return testMethodCfg.TestParams.SimultWithNext; } }
public bool Evaluate { get { return false; } }
public bool Publish { get { return false; } }
public bool CanTest(Entities.MetersKind meters) { return meters == Entities.MetersKind.Single; }

View File

@ -1,6 +1,5 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Collections.Generic;

View File

@ -1,6 +1,5 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Collections.Generic;
@ -227,32 +226,34 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
readonly bool[] disabled;
Entities.TestResult tr;
int textBoxesCount;
Label[] labels;
TextBox[] messages;
static TestMethodCfg cfg;
static IList<WaterMeters.iPerl.WaterMeter> waterMeters;
Modbus.QuidoRS.QuidoRS quido;
static IList<WaterMeters.iPerl.WaterMeter> waterMeters;
Modbus.QuidoRS.QuidoRS quido;
///
/// RFID multiplexer PCB / RFID serial port and worker thread related variables
///
static string activity;
static int currentGroup; /// form -> worker thread (0 = none)
static TestMethodCfg cfg;
static IList<iPerlCommunicationParams> multiTestParams;
static int currentActivityStep;
static int currentGroup; /// form -> worker thread (0 = none)
static int lastGroup;
static int completedCommCount; /// Number of completed communication steps
static IList<Thread> workerThreads;
static IList<int> rfidPortNrs;
static IList<bool> stopWorkerThreads; /// form -> worker thread
static bool stopWorkerThreads; /// form -> worker thread
/// <summary> Parameterless constructor for 3 watermeters </summary>
/// <summary> Parameterless constructor (without watermeters, threads) </summary>
public iPerlCommunicationForm()
{
InitializeComponent();
@ -286,16 +287,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
wmTextBox46, wmTextBox47, wmTextBox48,
};
currentGroup = 0;
lastGroup = 0; /// group numbers are >=1, lastGroup == 0 means no group
completedCommCount = 0;
workerThreads = new List<Thread>();
rfidPortNrs = new List<int>();
stopWorkerThreads = new List<bool>();
formCompleted = false;
tr = null;
/// Find QuidoRS
foreach (var comp in StateMachine.Components)
@ -328,63 +320,97 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
};
}
/// <summary>
/// Constructor
/// Constructor with a list of watermeters.
/// Creates a list of iPerl-s, re-shuffles UI conrols and allocates 'disabled' array.
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm(TestMethodCfg cfg, IList<GenericDevices.IWaterMeter> waterMeters, string activity)
public iPerlCommunicationForm(IList<GenericDevices.IWaterMeter> waterMeters)
: this()
{
this.WaterMetersCount = waterMeters.Count;
iPerlCommunicationForm.waterMeters = new List<WaterMeters.iPerl.WaterMeter>();
///
foreach (var wm in waterMeters)
{
WaterMeters.iPerl.WaterMeter iPerl = wm as WaterMeters.iPerl.WaterMeter;
iPerlCommunicationForm.waterMeters.Add(iPerl);
}
ShuffleTextBoxes(this.WaterMetersCount, Program.LineSize);
disabled = new bool[this.WaterMetersCount];
///
/// Prepare worker threads, 'rfidPortNrs', 'lastGroup', etc..
///
workerThreads = new List<Thread>();
rfidPortNrs = new List<int>();
currentActivityStep = 0;
currentGroup = 0;
lastGroup = 0; /// group numbers are >=1, lastGroup == 0 means no group
completedCommCount = 0;
stopWorkerThreads = false;
foreach (var iPerl in iPerlCommunicationForm.waterMeters)
{
if (!rfidPortNrs.Contains(iPerl.MuxBoardNr))
{
rfidPortNrs.Add(iPerl.MuxBoardNr);
if (workerThreads.Count < NrThreads)
{
Thread thread = new Thread(iPerlCommunicationForm.Worker);
workerThreads.Add(thread);
}
}
if (iPerl.Group > lastGroup) lastGroup = iPerl.Group;
}
}
/// <summary>
/// Constructor for one iPerlCommunication 'test'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm(IList<GenericDevices.IWaterMeter> waterMeters,
TestMethodCfg cfg, iPerlCommunicationParams testParams)
: this(waterMeters)
{
iPerlCommunicationForm.cfg = cfg;
iPerlCommunicationForm.activity = activity;
this.WaterMetersCount = waterMeters.Count;
iPerlCommunicationForm.waterMeters = new List<WaterMeters.iPerl.WaterMeter>();
#if DEFINE
foreach (var wm in waterMeters)
{
WaterMeters.iPerl.WaterMeter iPerlWM = wm as WaterMeters.iPerl.WaterMeter;
iPerlCommunicationForm.waterMeters.Add(iPerlWM);
if (iPerlWM.Group > lastGroup) lastGroup = iPerlWM.Group;
if (!rfidPortNrs.Contains(iPerlWM.RfidComPortNr))
{
int threadId = workerThreads.Count;
Thread thread = new Thread(iPerlCommunicationForm.Worker);
workerThreads.Add(thread);
rfidPortNrs.Add(iPerlWM.RfidComPortNr);
stopWorkerThreads.Add(false);
thread.Start(new Boxes.IntBox(threadId));
}
}
#else
foreach (var wm in waterMeters)
{
WaterMeters.iPerl.WaterMeter iPerlWM = wm as WaterMeters.iPerl.WaterMeter;
iPerlCommunicationForm.waterMeters.Add(iPerlWM);
if (!rfidPortNrs.Contains(iPerlWM.MuxBoardNr))
{
rfidPortNrs.Add(iPerlWM.MuxBoardNr);
iPerlCommunicationForm.multiTestParams = new List<iPerlCommunicationParams>();
iPerlCommunicationForm.multiTestParams.Add(testParams);
int newThreadId = workerThreads.Count;
if (newThreadId < NrThreads)
{
Thread thread = new Thread(iPerlCommunicationForm.Worker);
workerThreads.Add(thread);
stopWorkerThreads.Add(false);
thread.Start(new Boxes.IntBox(newThreadId));
}
}
if (iPerlWM.Group > lastGroup) lastGroup = iPerlWM.Group;
}
#endif
activityLabel.Text = activity;
activityLabel.Text = testParams.Activity;
ShuffleTextBoxes(this.WaterMetersCount, Program.LineSize);
disabled = new bool[this.WaterMetersCount];
/// Start worker threads
int wtId = 0;
foreach (var wt in workerThreads) wt.Start(new Boxes.IntBox(wtId++));
}
/// <summary>
/// Constructor for multiple iPerlCommunication 'tests'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm(IList<GenericDevices.IWaterMeter> waterMeters, TestMethodCfg cfg,
IList<iPerlCommunicationParams> multiTestParams)
: this(waterMeters)
{
iPerlCommunicationForm.cfg = cfg;
iPerlCommunicationForm.multiTestParams = multiTestParams;
if (multiTestParams.Count > 0) activityLabel.Text = multiTestParams[0].Activity;
/// Start worker threads
int wtId = 0;
foreach (var wt in workerThreads) wt.Start(new Boxes.IntBox(wtId++));
}
/// <summary>
/// Make sure the layout of labels/text boxes on the screen
/// corresponds to the layout of watermeters of the test bench.
@ -422,6 +448,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
}
}
private void iPerlCommunicationForm_Load(object sender, EventArgs e)
{
Localize();
@ -457,6 +484,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
Top = (ls.iPerlCommunicationsFormTop != 0) ? ls.iPerlCommunicationsFormTop : 150;
}
private void NormalClose()
{
CommCompletedHandler = null;
@ -471,35 +499,6 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
Close();
}
void OnAdjustmentInProgress(object sender, UiBridge.AdjustmentInProgressEventArgs args)
{
tr = args.TestResult;
Redraw();
}
void Redraw()
{
if (tr != null)
{
for (int i = 0; i < textBoxesCount; i++)
{
messages[i].Text = tr.Meters[i].VolumeErrorPct.ToString("F1");
}
}
}
private void WMErrorsForm_Paint(object sender, PaintEventArgs e)
{
//if (tr != null)
//{
// System.Drawing.Graphics graphics = this.CreateGraphics();
// for (int i = 0; i < WaterMetersCount; i++)
// {
// PaintOne(graphics, rects[i], tr.Meters[i].VolumeErrorPct, tr.ErrLimLo, tr.ErrLimHi);
// }
//}
}
#region Forced close handling
@ -517,6 +516,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
CommCompletedHandler = null;
AllCompletedHandler = null;
stopWorkerThreads = true;
DialogResult = DialogResult.Cancel;
Close();
}
@ -532,62 +533,83 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
int threadId = (threadData as Boxes.IntBox).Val;
if (threadId == 0)
{
rfidDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data
rfidDataLogger.WarnFormat("Activity = {0}", activity);
rfidDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data
}
int activityStep = 0; /// activity step > 0 in case multiTestParams are used
for (int group = 1; group <= lastGroup; group++)
{
while (currentGroup != group && !stopWorkerThreads[threadId]) Thread.Sleep(50);
foreach (var testParams in multiTestParams)
{
string activity = testParams.Activity; /// Current activity
if (stopWorkerThreads[threadId]) break;
for (int rfidPortIx = threadId; rfidPortIx < threadId + 4; rfidPortIx += NrThreads)
{
int rfidPortNr = rfidPortNrs[rfidPortIx];
int wmNr = 0;
bool wmFound = false;
foreach (var wm in waterMeters)
{
if ((wm.MuxBoardNr == rfidPortNr) && (wm.Group == group))
{
wmFound = true;
if (threadId == 0)
{
rfidDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data
rfidDataLogger.WarnFormat("Activity = {0}", activity);
rfidDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data
}
CommErr error;
string resultStr = string.Empty;
for (int group = 1; group <= lastGroup; group++)
{
/// Synchronize with QuidoRS and other threads
while (((currentGroup != group) || (activityStep != currentActivityStep)) && !stopWorkerThreads)
{
Thread.Sleep(50);
}
if (activity.ToLower().Contains(ReadConfigurationStr.ToLower())) error = ReadConfiguration(wm, ref resultStr);
else if (activity.ToLower().Contains(SetTestModeStr.ToLower())) error = SetTestMode(wm, ref resultStr);
else if (activity.ToLower().Equals(SetActiveModeStr.ToLower())) error = SetActiveMode(wm, ref resultStr);
else if (activity.ToLower().Equals(ReadCalibrationStr.ToLower())) error = ReadCalibration(wm, ref resultStr);
else if (activity.ToLower().Contains(WriteCalibrationFactorStr.ToLower())) error = WriteCalibrationFactor(wm, ref resultStr);
else if (activity.ToLower().Equals(ResetQ2CorrectionStr.ToLower())) error = ResetQ2Correction(wm, ref resultStr);
else if (activity.ToLower().Equals(WriteQ2CorrectionStr.ToLower())) error = WriteQ2Correction(wm, ref resultStr);
else
{
error = CommErr.None;
resultStr = "Invalid activity";
}
if (stopWorkerThreads) break;
if (error == CommErr.None) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, resultStr));
else if (wm.Disabled || error == CommErr.Disabled) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Watermeter is disabled"));
else
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, string.Format("{0} failed ({1}) !!!", activity, error)));
rfidDataLogger.ErrorFormat("Group={0}, Board={1}, {2} failed ({3}) !!!", currentGroup, wm.MuxBoardNr, activity, error);
wm.Disabled = true;
}
break;
}
wmNr++;
}
for (int rfidPortIx = threadId; rfidPortIx < threadId + 4; rfidPortIx += NrThreads)
{
int rfidPortNr = rfidPortNrs[rfidPortIx];
int wmNr = 0;
bool wmFound = false;
if (!wmFound) OnCommCompleted(null, new CommCompletedEventArgs(threadId, -1, string.Empty)); /// Send negative wmNr
}
}
foreach (var wm in waterMeters)
{
if ((wm.MuxBoardNr == rfidPortNr) && (wm.Group == group))
{
wmFound = true;
CommErr error;
string resultStr = string.Empty;
if (activity.ToLower().Contains(ReadConfigurationStr.ToLower())) error = ReadConfiguration(wm, ref resultStr);
else if (activity.ToLower().Contains(SetTestModeStr.ToLower())) error = SetTestMode(wm, ref resultStr);
else if (activity.ToLower().Equals(SetActiveModeStr.ToLower())) error = SetActiveMode(wm, ref resultStr);
else if (activity.ToLower().Equals(ReadCalibrationStr.ToLower())) error = ReadCalibration(wm, ref resultStr);
else if (activity.ToLower().Contains(WriteCalibrationFactorStr.ToLower())) error = WriteCalibrationFactor(wm, ref resultStr);
else if (activity.ToLower().Equals(ResetQ2CorrectionStr.ToLower())) error = ResetQ2Correction(wm, ref resultStr);
else if (activity.ToLower().Equals(WriteQ2CorrectionStr.ToLower())) error = WriteQ2Correction(wm, ref resultStr);
else
{
error = CommErr.None;
resultStr = "Invalid activity";
}
if (error == CommErr.None) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, resultStr));
else if (wm.Disabled || error == CommErr.Disabled) OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Watermeter is disabled"));
else
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, string.Format("{0} failed ({1}) !!!", activity, error)));
rfidDataLogger.ErrorFormat("Group={0}, Board={1}, {2} failed ({3}) !!!", currentGroup, wm.MuxBoardNr, activity, error);
wm.Disabled = true;
}
break;
}
wmNr++;
}
if (!wmFound) OnCommCompleted(null, new CommCompletedEventArgs(threadId, -1, string.Empty)); /// Send negative wmNr
if (stopWorkerThreads) break;
}
if (stopWorkerThreads) break;
} /// for (int group
activityStep++;
if (stopWorkerThreads) break;
}
}
@ -603,7 +625,7 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
/// The activity is "Read configuration" (this enables the watermeter, resets error flag)
/// or "Read configuration if enabled" (this keeps th error flag).
///
if (!activity.ToLower().Contains(" if enabled"))
if (!multiTestParams[currentActivityStep].Activity.ToLower().Contains(" if enabled"))
{
wm.Disabled = false;
}
@ -648,9 +670,9 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
Byte testModeConfig = 0xA0; /// Default value
///
if (activity.Length > SetTestModeStr.Length)
if (multiTestParams[currentActivityStep].Activity.Length > SetTestModeStr.Length)
{
string testModeConfigStr = activity.Substring(SetTestModeStr.Length + 1);
string testModeConfigStr = multiTestParams[currentActivityStep].Activity.Substring(SetTestModeStr.Length + 1);
UInt16 byteVal;
if (UInt16.TryParse(testModeConfigStr, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out byteVal) && byteVal <= 255)
{
@ -834,9 +856,9 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
UInt16 newCalibFactor = 3000; /// Default value
///
if (activity.Length > WriteCalibrationFactorStr.Length)
if (multiTestParams[currentActivityStep].Activity.Length > WriteCalibrationFactorStr.Length)
{
string calibFactrorStr = activity.Substring(WriteCalibrationFactorStr.Length + 1);
string calibFactrorStr = multiTestParams[currentActivityStep].Activity.Substring(WriteCalibrationFactorStr.Length + 1);
UInt16 val;
if (UInt16.TryParse(calibFactrorStr, out val) && val > 0)
{
@ -1012,14 +1034,25 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
if (currentGroup < lastGroup)
{
/// Go to the next step / next group
if (quido != null)
currentGroup++;
if (quido != null)
{
quido.SetOutputs((ushort)(16 - currentGroup - 1));
quido.SetOutputs((ushort)(16 - currentGroup));
Thread.Sleep(100);
}
currentGroup++;
}
else
else if (currentActivityStep + 1 < multiTestParams.Count)
{
currentActivityStep++;
activityLabel.Text = multiTestParams[currentActivityStep].Activity;
currentGroup = 1;
if (quido != null)
{
quido.SetOutputs((ushort)(16 - currentGroup));
Thread.Sleep(100);
}
}
else
{
/// Wait until all threads are finished
workerThreads[data.ThreadId].Join(2000);

View File

@ -1210,7 +1210,6 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
this.Text = "Water Meter States";
this.TopMost = true;
this.Load += new System.EventHandler(this.iPerlCommunicationForm_Load);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.WMErrorsForm_Paint);
this.ResumeLayout(false);
this.PerformLayout();

View File

@ -1,6 +1,5 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.IO;
@ -14,16 +13,22 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
public class iPerlCommunicationParams : TestParamsBase, IParamsProvider, ITestParams
{
public string Activity; /// Communication activity
public bool SimultWithPrevious;
public bool SimultWithNext;
public override void InitializeAll()
{
Activity = "Read Configuration";
SimultWithPrevious = false;
SimultWithNext = false;
}
string[] paramNames = new string[]
{
Strings.Activity,
Strings.Simultaneous_with_previous_step,
Strings.Simultaneous_with_next_step,
};
public override string ParamName(int i) { return paramNames[i]; }
public override int ParamsCount() { return paramNames.Length; }
@ -33,6 +38,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
switch (i)
{
case 0: return Activity;
case 1: return (SimultWithPrevious ? Strings.yes : Strings.no);
case 2: return (SimultWithNext ? Strings.yes : Strings.no);
default: return string.Empty;
}
}
@ -42,6 +49,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
switch (i)
{
case 0: Activity = strValue; return;
case 1: SimultWithPrevious = strValue.Equals(Strings.yes); return;
case 2: SimultWithNext = strValue.Equals(Strings.yes); return;
default: return;
}
}
@ -54,10 +63,17 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
case 0:
return true;
case 1:
case 2:
if (strValue.Equals(Strings.yes) || strValue.Equals(Strings.no)) return true;
break;
default:
message = "Invalid index";
return false;
}
message = ParamName(i) + " is invalid";
return false;
}
public override void UpdateTestParams(Entities.ComponentTest dbEntity)
@ -73,6 +89,8 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
test = dbEntity.Test;
Activity = tmp.Activity;
SimultWithPrevious = tmp.SimultWithPrevious;
SimultWithNext = tmp.SimultWithNext;
}
catch
{

View File

@ -16,21 +16,30 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationSeq));
System.Windows.Forms.Form modelessDlg;
///
delegate void iPerlCommFormDlgt(iPerlCommunicationSeq myRef, TestMethodCfg cfg, string activity);
delegate void iPerlCommFormDlgt(iPerlCommunicationSeq myRef, TestMethodCfg cfg, iPerlCommunicationParams testParams);
///
void OpenIPerlCommForm(iPerlCommunicationSeq myRef, TestMethodCfg cfg, string activity)
void OpenIPerlCommForm(iPerlCommunicationSeq myRef, TestMethodCfg cfg, iPerlCommunicationParams testParams)
{
IList<GenericDevices.IWaterMeter> wMtrs = new List<GenericDevices.IWaterMeter>();
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is GenericDevices.IWaterMeter) wMtrs.Add(rr as GenericDevices.IWaterMeter);
}
myRef.modelessDlg = new iPerlCommunicationForm(cfg, wMtrs, activity);
modelessDlg.Show();
myRef.modelessDlg = new iPerlCommunicationForm(wMtrs, cfg, testParams);
myRef.modelessDlg.Show();
}
void CloseIPerlCommForm()
{
UiBridge.Bridge.OnCloseModelessForm(this, null);
modelessDlg = null;
}
/// <summary>
/// Flying start mass collection method sequence
/// </summary>
@ -46,18 +55,10 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
IList<Event> e = new List<Event>(); /// Events from currently running operations
Event retVal = Event.Done;
checkUiOp = new Operations.CheckUIOp(true); /// Runs in more then one state
modelessDlg = null;
processDataLoggingOp = new TBF.BenchControl.Operations.ProcessDataLoggingOp(processDataLogger, this);
//====================================
// Transition or SetRoute - Start
//====================================
switch (Transition(transitionBefore, TransitionContext.BeforeTest))
{
case Event.Error: { retVal = Event.Error; goto stopTest; }
case Event.UiCmdStop: { retVal = Event.UiCmdStop; goto stopTest; }
}
const string Q2correctedFromCmd = "Q2 corrected from ";
if (testParams.Activity.Contains(Q2correctedFromCmd))
@ -103,42 +104,41 @@ namespace TBF.BenchControl.TestMethods.iPerlCommunication
iPerl.NominalTestFlow = 500.0 * (double)(test.Qfrom + test.Qto); /// Ave. + convert to liter/hour
}
}
IList<Event> rList = new List<Event>(1);
rList.Add(Event.Done);
return rList;
}
else
{
///
/// Show the modeless dialog with error indication
///
Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, cfg, testParams.Activity });
}
Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, cfg, testParams });
loop:
//------------------------------------------------
Bridge.OnActivity(this, Strings.Test_in_progress);
//------------------------------------------------
//------------------------------------------------
Bridge.OnActivity(this, Strings.iPerl_Communication_in_progress);
//------------------------------------------------
/// Make sure the CycleBeginForm is closed so that water meter data (s/n) can be copied into results
if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stopTest;
bool stopPressed = false; /// true when STOP button pressed
bool completed = false;
/// Test 'Quit'
if ((modelessDlg is GenericDevices.IHasCompleted) && !(modelessDlg as GenericDevices.IHasCompleted).Completed)
{
goto loop; /// Modeless dilaog not closed, keep looping
}
modelessDlg = null; /// Modeless dialog is closed now
State.Create("iPerlCommunicationSeq : Wait until the entry form is closed")
.AddOperation(checkUiOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
stopPressed = e.Contains(Event.UiCmdStop);
completed = (modelessDlg is GenericDevices.IHasCompleted)
&& (modelessDlg as GenericDevices.IHasCompleted).Completed;
}
while (!stopPressed && !completed);
stopTest:
if (stopPressed)
{
CloseIPerlCommForm();
retVal = Event.UiCmdStop;
}
/// Transition sequence at the end of test
/// Prevent overwriting 'retVal' in case it was set to non-default value earlier
switch (Transition(transitionAfter, TransitionContext.AfterTest))
{
case Event.Error: { if (retVal == Event.Done) retVal = Event.Error; break; }
case Event.UiCmdStop: { if (retVal == Event.Done) retVal = Event.UiCmdStop; break; }
/// Test 'Quit'
modelessDlg = null; /// Modeless dialog is closed now
}
/// Create a list with one item 'retVal' (default is Event.Done) and return it

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.5.105.1")]
[assembly: AssemblyFileVersion("1.5.105.1")]
[assembly: AssemblyVersion("1.5.106.1")]
[assembly: AssemblyFileVersion("1.5.106.1")]

View File

@ -1077,6 +1077,15 @@ namespace TBF.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to iPerl Communication in progress.
/// </summary>
internal static string iPerl_Communication_in_progress {
get {
return ResourceManager.GetString("iPerl_Communication_in_progress", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Less.
/// </summary>
@ -2256,6 +2265,24 @@ namespace TBF.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Simultaneous with next step.
/// </summary>
internal static string Simultaneous_with_next_step {
get {
return ResourceManager.GetString("Simultaneous_with_next_step", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Simultaneous with previous step.
/// </summary>
internal static string Simultaneous_with_previous_step {
get {
return ResourceManager.GetString("Simultaneous_with_previous_step", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Single.
/// </summary>

View File

@ -1096,4 +1096,13 @@
<data name="Publish" xml:space="preserve">
<value>Publish</value>
</data>
<data name="Simultaneous_with_next_step" xml:space="preserve">
<value>Simultaneous with next step</value>
</data>
<data name="Simultaneous_with_previous_step" xml:space="preserve">
<value>Simultaneous with previous step</value>
</data>
<data name="iPerl_Communication_in_progress" xml:space="preserve">
<value>iPerl Communication in progress</value>
</data>
</root>

View File

@ -277,6 +277,7 @@
<Compile Include="BenchControl\Elde\ValveEx\ValveFactory.cs" />
<Compile Include="BenchControl\GenericDevices\IModbus.cs" />
<Compile Include="BenchControl\GenericDevices\IBenchInfo.cs" />
<Compile Include="BenchControl\GenericDevices\ISimultTestMethod.cs" />
<Compile Include="BenchControl\MettlerToledo\KeepReadingMassesOp.cs" />
<Compile Include="BenchControl\MettlerToledo\Multi\BalanceCfg.cs" />
<Compile Include="BenchControl\MettlerToledo\Multi\BalanceCfgCtrl.cs">