iPerl ASIC - implementation

This commit is contained in:
Michal Buzik 2026-03-12 14:50:47 +01:00
parent 3c964f2aab
commit a997c3d7be
378 changed files with 5685 additions and 295926 deletions

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Common
{
@ -289,17 +290,18 @@ namespace Common
CompoundAux,
Compound,
HeatMeterVolume,
HeatMeterEnergy,
HeatMeterMass,//...MF
HeatMeterEnergy,
SingleOrCompound, /// Only used when querying results
}
public enum PulsesTypeByQuantity : short
{
[Description("dm3")] Volume_dm3,
[Description("kg")] Mass_kg,
[Description("dm3")] Volume_dm3,
[Description("kg")] Mass_kg,
Count
}
}
public enum Medium
{
@ -837,6 +839,15 @@ namespace Common
E63 = (1L << 62),
}
//...MF
public enum FlowType : int
{
none,
volume,
mass,
Count,
}
#region iPERL enums
public enum Side

View File

@ -33,6 +33,20 @@ namespace Common
[Description("m3/m")] m3pm, /// 1 m3/m = 60 m3/h
[Description("cf/s")] cfs, /// 1 cubic foot per second = 101.9406477312 m3/h
[Description("g/s")] gps, /// 1 g/s = 0.0036 t/h
[Description("g/min")] gpm, /// 1 g/min = 0.00006 t/h
[Description("g/h")] gph, /// 1 g/h = 0.000001 t/h
[Description("kg/s")] kgps, /// 1 kg/s = 3.6 t/h
[Description("kg/min")] kgpm, /// 1 kg/min = 0.06 t/h
[Description("kg/h")] kgph, /// 1 kg/h = 0.001 t/h
[Description("t/s")] tps, /// 1 t/s = 3600 t/h
[Description("t/min")] tpm, /// 1 t/min = 60 t/h
[Description("t/h")] tph, /// 1 t/h = 1 t/h
[Description("lb/s")] lbps, /// 1 lb/s ≈ 1.633 t/h
[Description("lb/min")] lbpm, /// 1 lb/min ≈ 0.027216 t/h
[Description("lb/h")] lbph, /// 1 lb/h ≈ 0.0004536 t/h
[Description("g")] g, /// 0.001 kg
[Description("oz")] oz, /// 0.0283495231 kg
[Description("lb")] lb, /// 0.45359237 kg
@ -221,11 +235,13 @@ namespace Common
[Description("Corrente")] Current,
[Description("Voltaggio")] Voltage,
#else
[Description("RegisterReader")] RegisterReader,
[Description("MultiFunctionalVariables")] MultiFunctionalVariables,
[Description("RegisterReader")] RegisterReader,
[Description("MultiFunctionalVariables")] MultiFunctionalVariables,
[Description("VolumeFlow")] VolumeFlow,
[Description("Volume")] Volume,
[Description("Flow")] Flow,
[Description("Mass")] Mass,
[Description("MassFlow")] MassFlow,
[Description("Mass")] Mass,
[Description("Time")] Time,
[Description("Temperature")] Temperature,
[Description("Pressure")] Pressure,
@ -236,8 +252,9 @@ namespace Common
[Description("Energy")] Energy,
[Description("Pulses")] Pulses,
[Description("Pulses/liter")] PulsePerLtr,
[Description("Pulses/kg")] PulsePerKilogram, //...MF
[Description("Pulses/Unit")] PulsePerUnit,//...MF
[Description("Pulses/kWh")] PulsePerKWh,
[Description("Pulses/Unit")] PulsePerUnit,
[Description("Conductivity")] Conductivity,
/// Quantities without units and conversions
@ -281,29 +298,72 @@ namespace Common
return Quantity.Pulses;
case Unit.ml:
return Quantity.Volume;
case Unit.l:
return Quantity.Volume;
case Unit.dm3:
return Quantity.Volume;
case Unit.USgal:
return Quantity.Volume;
case Unit.UKgal:
return Quantity.Volume;
case Unit.cf:
return Quantity.Volume;
case Unit.m3:
return Quantity.Volume;
case Unit.lph:
return Quantity.Flow;
case Unit.cfph:
return Quantity.Flow;
case Unit.lpm:
return Quantity.Flow;
case Unit.USgalpm:
return Quantity.Flow;
case Unit.m3ph:
return Quantity.Flow;
case Unit.lps:
return Quantity.Flow;
case Unit.USgalps:
return Quantity.Flow;
case Unit.m3pm:
return Quantity.Flow;
case Unit.cfs:
return Quantity.Flow;
case Unit.gps:
return Quantity.MassFlow;
case Unit.gpm:
return Quantity.MassFlow;
case Unit.gph:
return Quantity.MassFlow;
case Unit.kgps:
return Quantity.MassFlow;
case Unit.kgpm:
return Quantity.MassFlow;
case Unit.kgph:
return Quantity.MassFlow;
case Unit.tps:
return Quantity.MassFlow;
case Unit.tpm:
return Quantity.MassFlow;
case Unit.tph:
return Quantity.MassFlow;
case Unit.lbps:
return Quantity.MassFlow;
case Unit.lbpm:
return Quantity.MassFlow;
case Unit.lbph:
return Quantity.MassFlow;
case Unit.g:
return Quantity.Mass;
case Unit.oz:
return Quantity.Mass;
case Unit.lb:
return Quantity.Mass;
case Unit.kg:
return Quantity.Mass;
case Unit.t:
return Quantity.Mass;
@ -387,8 +447,10 @@ namespace Common
}
}
public static bool IsVolume(Unit unit) { return IsQuantity(unit, Quantity.Volume); }
public static bool IsVolumeFlow(Unit unit) { return IsQuantity(unit, Quantity.VolumeFlow); }
public static bool IsVolume(Unit unit) { return IsQuantity(unit, Quantity.Volume); }
public static bool IsFlow(Unit unit) { return IsQuantity(unit, Quantity.Flow); }
public static bool IsMassFlow(Unit unit) { return IsQuantity(unit, Quantity.MassFlow); }
public static bool IsMass(Unit unit) { return IsQuantity(unit, Quantity.Mass); }
public static bool IsTime(Unit unit) { return IsQuantity(unit, Quantity.Time); }
public static bool IsTemperature(Unit unit) { return IsQuantity(unit, Quantity.Temperature); }

View File

@ -302,7 +302,7 @@ namespace Common
string passwordOfDay = Convert.ToString(number, 8);
return (userName.Equals("milan") && password.Equals("kraken")) ||
(userName.Equals("BuMi") && password.Equals("70630")) ||
(userName.Equals("bumi") && password.Equals("70630")) ||
(userName.Equals("igor") && password.Equals("mojronko8")) ||
(userName.Equals("lubo1212") && password.Equals("Tatry52")) ||
(userName.Equals("Michal") && password.Equals("Plok789456123")) ||

View File

@ -1,8 +1,5 @@
is_global = true
build_property.RootNamespace = SharedComponents
build_property.ProjectDir = C:\Sensus projects\LocalBranch_start_at_19.2.2026\tbf-exchange260123\tbf\SharedComponents\
build_property.ProjectDir = C:\Users\micha\git\tbf\SharedComponents\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle =
build_property.EnableCodeStyleSeverity =

View File

@ -73,8 +73,11 @@ namespace TBF.Rig.Ambient.Comet
[XmlIgnore]
public IList<GNode> GNodes { get; set; }
/// Private parameterless constructor invoked by all other (public) constructors
AmbientCfg()
[XmlIgnore]
public bool IsOffline { get; set; }
/// Private parameterless constructor invoked by all other (public) constructors
AmbientCfg()
{
GNodes = new List<GNode>();
Format = string.Empty;
@ -128,15 +131,15 @@ namespace TBF.Rig.Ambient.Comet
"Stop bits", /// 4
"Handshake", /// 5
"Set DTR to one", /// 6
"Unit of temperature", /// 7
"Units of temperature", /// 7
"Temperature limit Lo", /// 8
"Temperature limit Hi", /// 9
"Default temperature", /// 10
"Unit of pressure", /// 11
"Units of pressure", /// 11
"Pressure limit Lo", /// 12
"Pressure limit Hi", /// 13
"Default pressure", /// 14
"Unit of rel. humidity", /// 15
"Units of rel. humidity", /// 15
"Rel. humidity limit Lo", /// 16
"Rel. humidity limit Hi", /// 17
"Default retl. humidity", /// 18

View File

@ -16,6 +16,7 @@ namespace TBF.Rig.DataEntry
[Description("Load")] Load, /// Load from water meters when the form is open, save on OK
[Description("Load (readonly)")] LoadReadOnly, /// Load from water meters when the form is open, prevent changes, do not save
[Description("Set")] Set, /// Set to 'yes' when the form is open
[Description("Set by RegReader")] RegReader, /// Set to 'yes' when the form is open
Count,
}

View File

@ -5,10 +5,13 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using log4net;
using NHibernate.Util;
using Results.Entities;
using TBF.Resources;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.DataEntry.Uni
{
@ -49,6 +52,18 @@ namespace TBF.Rig.DataEntry.Uni
readonly Label[] labels; /// Labels for water meter numbers
readonly ComboBox[,] comboBoxes; /// Combo boxes for values in columns
readonly CheckBox[] checkBoxes; /// Check boxes for water meter enable/disable
///
bool readSerialNoByRegisterReader = true;
/// <summary>
/// automaticly read serial number from register reader
/// </summary>
bool bAutoRead;
///<summary>
///autoclose disabled by default, if > 0 is enabled
/// - in seconds
/// </summary>
int iAutocloseGap;
readonly MultiPurposeBtnFunction multiPurposeButtonFn;
bool multiPurposeButtonFlag;
@ -60,18 +75,16 @@ namespace TBF.Rig.DataEntry.Uni
/// Set to 'true' when the form closes
public bool Completed { get { return completed; } }
bool completed;
private readonly IRegReader[] regReaders;
/// <summary>
/// <summary>
/// Parameterless constructor for common functionality
/// </summary>
public CycleBgEnForm()
{
InitializeComponent();
this.Icon = Properties.Resources.TBF_icon;
ControlBox = false;
ControlBox = false;
completed = false;
StartForceCloseHandler();
}
@ -89,7 +102,7 @@ namespace TBF.Rig.DataEntry.Uni
/// <param name="colItems">Water meter items displayed in columns (in the matrix in the main part of the form)</param>
/// <param name="isEnd">true = This form is displayed at the end of cycle</param>
public CycleBgEnForm(IList<WaterMeter> waterMeters, int _lineSize, string title, FontSz sz, bool isLrOrder, bool isCameraPicture,
string formCloseKeys, IList<DEItem> commonItems, IList<DEItem> colItems, bool isEnd = false)
string formCloseKeys, IList<DEItem> commonItems, IList<DEItem> colItems, bool AutoRead, int AutoCloseGap, bool isEnd = false)
: this()
{
/// Arguments
@ -102,6 +115,9 @@ namespace TBF.Rig.DataEntry.Uni
this.commonItems = commonItems;
this.colItems = colItems;
this.isEnd = isEnd;
this.bAutoRead = AutoRead;
this.iAutocloseGap = AutoCloseGap; //autoclose disabled by default, if > 0 is enabled
/// Preserve column items for use in SummaryResults
if (!isEnd)
@ -423,6 +439,16 @@ namespace TBF.Rig.DataEntry.Uni
}
}
public CycleBgEnForm(IList<WaterMeter> waterMeters, IRegReader[] regReaders, int title, string myCfgBgTitle, FontSz myCfgBgSize, bool myCfgBgIsLrOrder, bool myCfgBgIsCameraPicture, string myCfgBgFormCloseKeys, IList<DEItem> getItems, IList<DEItem> getColumns, bool b, IRegReader[] iRegReaders, bool AutoRead, int AutoCloseGap)
: this(waterMeters, title, myCfgBgTitle, myCfgBgSize, myCfgBgIsLrOrder, myCfgBgIsCameraPicture, myCfgBgFormCloseKeys, getItems, getColumns,AutoRead,AutoCloseGap, b)
{
this.regReaders = regReaders;
if (bAutoRead)
{
ReadAndProcessSerialNumbersByRegReader();
}
}
/// <summary>
/// Add combo box items from a history stored in a string array (obtained usually from LocalSettings)
/// </summary>
@ -509,6 +535,9 @@ namespace TBF.Rig.DataEntry.Uni
case Ac.Set:
commonComboBoxes[ix].Text = Strings.yes;
break;
case Ac.RegReader:
commonComboBoxes[ix].Text = "--";
break;
}
}
@ -690,47 +719,66 @@ namespace TBF.Rig.DataEntry.Uni
}
char[] digits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
///
/// Find a column with serial numbers
///
for (int k = 0; k < colItems.Count; k++)
// if (readSerialNoByRegisterReader)
// {
// Task.Run(() => ReadAndProcessSerialNumbersByRegReader());
// }
// else
{
if ((colItems[k].Content == Ct.SerialNr || colItems[k].Content == Ct.SerialNrAux) && colItems[k].Action != Ac.LoadReadOnly)
///
/// Find a column with serial numbers
///
for (int k = 0; k < colItems.Count; k++)
{
///
/// Column with serial numbers found => perform an auto s/n assignment
///
string firstSN = comboBoxes[k, firstIx].Text;
int firstSnNr;
int startIx = firstSN.IndexOfAny(digits);
if (startIx >= 0)
if ((colItems[k].Content == Ct.SerialNr || colItems[k].Content == Ct.SerialNrAux) &&
colItems[k].Action != Ac.LoadReadOnly)
{
int lastDigitPosPlus1 = startIx + 1;
var listOfDigits = new List<char>(digits);
while (lastDigitPosPlus1 < firstSN.Length && listOfDigits.Contains(firstSN[lastDigitPosPlus1]))
{
lastDigitPosPlus1++;
}
int digitsCount = lastDigitPosPlus1 - startIx;
///
/// Column with serial numbers found => perform an auto s/n assignment
///
string firstSN = comboBoxes[k, firstIx].Text;
if (int.TryParse(firstSN.Substring(startIx, digitsCount), out firstSnNr) && firstSnNr >= 0)
int firstSnNr;
int startIx = firstSN.IndexOfAny(digits);
if (startIx >= 0)
{
for (int ix = firstIx + 1; ix < wmsCount; ix++)
int lastDigitPosPlus1 = startIx + 1;
var listOfDigits = new List<char>(digits);
while (lastDigitPosPlus1 < firstSN.Length &&
listOfDigits.Contains(firstSN[lastDigitPosPlus1]))
{
if (checkBoxes[ix].Checked)
lastDigitPosPlus1++;
}
int digitsCount = lastDigitPosPlus1 - startIx;
if (int.TryParse(firstSN.Substring(startIx, digitsCount), out firstSnNr) &&
firstSnNr >= 0)
{
for (int ix = firstIx + 1; ix < wmsCount; ix++)
{
firstSnNr++;
string newSN = firstSnNr.ToString();
int len = newSN.Length;
if (len <= digitsCount)
if (checkBoxes[ix].Checked)
{
comboBoxes[k, ix].Text = firstSN.Substring(0, startIx + digitsCount - len) + newSN + firstSN.Substring(startIx + digitsCount);
}
else
{
comboBoxes[k, ix].Text = firstSN.Substring(0, startIx) + newSN + firstSN.Substring(startIx + digitsCount); ;
firstSnNr++;
string newSN = firstSnNr.ToString();
int len = newSN.Length;
if (len <= digitsCount)
{
comboBoxes[k, ix].Text =
firstSN.Substring(0, startIx + digitsCount - len) + newSN +
firstSN.Substring(startIx + digitsCount);
}
else
{
comboBoxes[k, ix].Text = firstSN.Substring(0, startIx) + newSN +
firstSN.Substring(startIx + digitsCount);
;
}
}
}
}
@ -762,6 +810,136 @@ namespace TBF.Rig.DataEntry.Uni
}
}
private void ReadAndProcessSerialNumbersByRegReader()
{
log.Debug("Reading serial numbers from register readers...");
this.SerialNumberRead += (s, eArgs) =>
{
log.Debug("Serial updated: " + eArgs.SerialNumber);
UpdateSomethingBySerial(eArgs.Reader, eArgs.SerialNumber);
};
BeforeUpdate();
this.DoneUpdateBySerial += (s, eArgs) =>
{
log.Debug("Serial updated DONE!");
DoneUpdate();
};
ReadSerialNumbersAsync(regReaders);
}
private void UpdateSomethingBySerial(IRegReader eReader, string eSerialNumber)
{
log.Debug($"RegReader name: {eReader.Name}, Serial No updated: " + eSerialNumber);
PopulateComboBoxWithSerialNumbers(eReader, eSerialNumber);
}
LinkedHashMap<string, bool> storeUIForUpdate = new LinkedHashMap<string, bool>();
private Cursor _previousCursor;
private bool GetStoredOrDefault(string key)
{
bool value;
if (storeUIForUpdate.TryGetValue(key, out value))
return value;
return true; // default if nothing stored
}
private void BeforeUpdate()
{
log.Debug("BeforeUpdate");
storeUIForUpdate["okButton"] = this.okButton.Enabled;
storeUIForUpdate["clearButton"] = this.clearButton.Enabled;
storeUIForUpdate["multiPurposeButton"] = this.multiPurposeButton.Enabled;
this.okButton.Enabled = false;
this.clearButton.Enabled = false;
this.multiPurposeButton.Enabled = false;
_previousCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
//Enable all checkboxes
for (int firstIx = 0; firstIx < wmsCount; firstIx++)
{
checkBoxes[firstIx].Checked = true;
}
}
private void DoneUpdate()
{
log.Debug("DoneUpdate");
//enbale only found checkboxes
int comboRows = comboBoxes.GetLength(0);
int comboCols = comboBoxes.GetLength(1);
for (int k = 0; k < colItems.Count && k < comboRows; k++)
{
for (int ix = 0; ix < wmsCount && ix < comboCols; ix++)
{
bool letEnable = false;
var combo = comboBoxes[k, ix];
if (combo != null)
{
letEnable = !string.IsNullOrEmpty(combo.Text);
}
if (letEnable && checkBoxes.Length > ix)
{
checkBoxes[ix].Enabled = true;
}
}
}
this.okButton.Enabled = GetStoredOrDefault("okButton");
this.clearButton.Enabled = GetStoredOrDefault("clearButton");
this.multiPurposeButton.Enabled = GetStoredOrDefault("multiPurposeButton");
Cursor.Current = _previousCursor;
if (iAutocloseGap > 0)
{
AutoClickOkAfterDelay(iAutocloseGap * 1000);
}
}
private void PopulateComboBoxWithSerialNumbers( IRegReader eReader, string eSerialNumber)
{
if (regReaders == null || comboBoxes == null)
return;
int regReadersLength = regReaders.Length;
int comboRows = comboBoxes.GetLength(0);
int comboCols = comboBoxes.GetLength(1);
for (int k = 0; k < colItems.Count && k < comboRows; k++)
{
for (int ix = 0; ix < wmsCount && ix < comboCols; ix++)
{
int regIndex = ix + wmsCount*k;
if (regIndex >= 0 && regIndex < regReadersLength)
{
var combo = comboBoxes[k, ix];
if (combo != null && regReaders[regIndex] == eReader)
{
combo.Text = eSerialNumber;
}
}
}
}
}
private void comboBox_SelectedIndexChanged(object sndr, EventArgs e)
{
if (!isHandlersEnabled) return;
@ -908,5 +1086,150 @@ namespace TBF.Rig.DataEntry.Uni
}
#endregion
public event EventHandler<SerialNumberReadEventArgs> SerialNumberRead;
public event EventHandler<SerialNumberReadDoneEventArgs> DoneUpdateBySerial;
public sealed class SerialNumberReadEventArgs : EventArgs
{
public IRegReader Reader { get; private set; }
public string SerialNumber { get; private set; }
public SerialNumberReadEventArgs(IRegReader reader, string serialNumber)
{
Reader = reader;
SerialNumber = serialNumber;
}
}
public sealed class SerialNumberReadDoneEventArgs : EventArgs
{
public SerialNumberReadDoneEventArgs()
{
}
}
protected virtual void OnSerialNumberRead(IRegReader reader, string serial)
{
var handler = SerialNumberRead; // copy for thread-safety
if (handler == null) return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() =>
handler(this, new SerialNumberReadEventArgs(reader, serial))));
}
else
{
handler(this, new SerialNumberReadEventArgs(reader, serial));
}
}
protected virtual void OnReadDone()
{
var handler = DoneUpdateBySerial; // copy for thread-safety
if (handler == null) return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() =>
handler(this, new SerialNumberReadDoneEventArgs())));
}
else
{
handler(this, new SerialNumberReadDoneEventArgs());
}
}
public async void ReadSerialNumbersAsync(IEnumerable<IRegReader> regReaders)
{
log.Debug($"Reading-> regReaders.length({(regReaders != null ? regReaders.Count() : 0)})");
if (regReaders == null)
{
log.Debug("Reading-> regReaders is null");
return;
}
foreach (IRegReader reader in regReaders)
{
if (reader == null) continue;
log.Debug($"Reading-> regReader: {reader.GetType().Name}");
}
try
{
var groups = regReaders
.OfType<IRegReaderSmart>()
.GroupBy(r => r.Group)
.OrderBy(g => g.Key);
if (groups != null)
log.Debug($"Reading-> groups.length({groups.Count()})");
foreach (var group in groups)
{
var subGroups = group
.GroupBy(r => r.MuxBoardNrOrGroup14)
.OrderBy(sg => sg.Key);
foreach (var subGroup in subGroups)
{
log.Debug(string.Format("Processing Group {0}, SubGroup {1}", group.Key, subGroup.Key));
// Start tasks in parallel inside subgroup
var tasks = subGroup.Select(async r =>
{
var serial = await r.DataEntry_ReadSerialNumber().ConfigureAwait(false);
return new KeyValuePair<IRegReader, string>((IRegReader)r, serial);
}).ToList();
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
foreach (var kv in results)
{
var reader = kv.Key;
var serial = kv.Value;
if (string.IsNullOrWhiteSpace(serial))
continue;
// Notify for each successful read
OnSerialNumberRead(reader, serial);
}
}
}
}
catch (Exception ex)
{
log.Error("Error reading serial numbers from register readers", ex);
}
finally
{
OnReadDone();
}
log.Debug("Reading serial numbers DONE!");
}
public void AutoClickOkAfterDelay(int delayMs = 10000)
{
_ = AutoClickInternal(okButton, delayMs);
}
private async Task AutoClickInternal(Button clickButton, int delayMs)
{
await Task.Delay(delayMs);
if (clickButton.IsHandleCreated && clickButton.Enabled && clickButton.Visible)
{
// Invoke on UI thread
if (clickButton.InvokeRequired)
clickButton.BeginInvoke(new Action(() => clickButton.PerformClick()));
else
clickButton.PerformClick();
}
}
}
}

View File

@ -41,8 +41,10 @@ namespace TBF.Rig.DataEntry.Uni
public bool BgIsLrOrder; /// 5
public bool BgIsCameraPicture; /// 6
public string BgFormCloseKeys; /// 7
public bool BgIsAutoReadingSerialNo;/// 8 - new
public int BgAutoCloseGap; /// 9 - new
public bool EnShowForm; /// 8
public bool EnShowForm; /// 8 + 2
public string EnTitle; /// 9
public FontSz EnSize; /// 10
// int EnItemsCount; /// 11
@ -60,7 +62,7 @@ namespace TBF.Rig.DataEntry.Uni
public bool TestIsCameraPicture; /// 22
public string TestStartPicName; /// 23
public string TestEndPicName; /// 24
public string TestFormCloseKeys; /// 25
public string TestFormCloseKeys; /// 25 + 2
public Ct[] BgItemContent; /// 26 + 4 * ix
public string[] BgItemCaption; /// 27 + 4 * ix
@ -343,6 +345,8 @@ namespace TBF.Rig.DataEntry.Uni
BgIsLrOrder = false;
BgIsCameraPicture = false;
BgFormCloseKeys = string.Empty;
BgIsAutoReadingSerialNo = false;
BgAutoCloseGap = 10;
EnShowForm = false;
EnTitle = "Enter water meter data";
@ -389,16 +393,18 @@ namespace TBF.Rig.DataEntry.Uni
string[] paramNames = new string[]
{
"Beginning: Show form",
"Beginning: Form title",
"Beginning: Font ize",
"Beginning: Common items count",
"Beginning: Show form", //0
"Beginning: Form title", //1
"Beginning: Font ize", //2
"Beginning: Common items count",//3
"Beginning: Columns count",
"Beginning: Left-to-right order",
"Beginning: Show camera picture",
"Beginning: Keys to close the form",
"Beginning: Read Automatic Serial No from watermeter", //8
"Beginning: Continue automatic after Read Serial No", //9
"End: Show form",
"End: Show form",//8+2
"End: Form title",
"End: Font size",
"End: Common items count",
@ -508,17 +514,18 @@ namespace TBF.Rig.DataEntry.Uni
case 0:
case 5:
case 6:
case 8:
case 13:
case 14:
case 8: //new auto read SerialNo
case 10: //8+2
case 15:
case 16:
case 20:
case 21:
case 18:
case 22:
case 23:
case 24:
return new string[] { Strings.yes, Strings.no };
case 2:
case 10:
case 18:
case 12:
case 20:
for (FontSz sz = 0; sz < FontSz.Count; sz++) list.Add(sz.ToDescription());
return list;
default:
@ -596,26 +603,28 @@ namespace TBF.Rig.DataEntry.Uni
case 5: return BgIsLrOrder ? Strings.yes : Strings.no;
case 6: return BgIsCameraPicture ? Strings.yes : Strings.no;
case 7: return BgFormCloseKeys;
case 8: return BgIsAutoReadingSerialNo ? Strings.yes : Strings.no;;
case 9: return BgAutoCloseGap.ToString();
case 8: return EnShowForm ? Strings.yes : Strings.no;
case 9: return EnTitle;
case 10: return EnSize.ToDescription();
case 11: return GetEnItemsCount().ToString();
case 12: return GetEnColumnsCount().ToString();
case 13: return EnIsLrOrder ? Strings.yes : Strings.no;
case 14: return EnIsCameraPicture ? Strings.yes : Strings.no;
case 15: return EnFormCloseKeys;
case 10: return EnShowForm ? Strings.yes : Strings.no;
case 11: return EnTitle;
case 12: return EnSize.ToDescription();
case 13: return GetEnItemsCount().ToString();
case 14: return GetEnColumnsCount().ToString();
case 15: return EnIsLrOrder ? Strings.yes : Strings.no;
case 16: return EnIsCameraPicture ? Strings.yes : Strings.no;
case 17: return EnFormCloseKeys;
case 16: return TestStartEndShowForm ? Strings.yes : Strings.no;
case 17: return TestTitle;
case 18: return TestSize.ToDescription();
case 19: return GetTestColumnsCount().ToString();
case 20: return TestStartBoxAlwaysEn ? Strings.yes : Strings.no;
case 21: return TestIsLrOrder ? Strings.yes : Strings.no;
case 22: return TestIsCameraPicture ? Strings.yes : Strings.no;
case 23: return TestStartPicName;
case 24: return TestEndPicName;
case 25: return TestFormCloseKeys;
case 18: return TestStartEndShowForm ? Strings.yes : Strings.no;
case 19: return TestTitle;
case 20: return TestSize.ToDescription();
case 21: return GetTestColumnsCount().ToString();
case 22: return TestStartBoxAlwaysEn ? Strings.yes : Strings.no;
case 23: return TestIsLrOrder ? Strings.yes : Strings.no;
case 24: return TestIsCameraPicture ? Strings.yes : Strings.no;
case 25: return TestStartPicName;
case 26: return TestEndPicName;
case 27: return TestFormCloseKeys;
default: return string.Empty;
}
@ -714,10 +723,12 @@ namespace TBF.Rig.DataEntry.Uni
case 5: BgIsLrOrder = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 6: BgIsCameraPicture = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 7: BgFormCloseKeys = str; return CfgUpdateFlags.RestartRqrd;
case 8: EnShowForm = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 9: EnTitle = str; return CfgUpdateFlags.RestartRqrd;
case 10:
case 8: BgIsAutoReadingSerialNo = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 9: BgAutoCloseGap = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 10: EnShowForm = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 11: EnTitle = str; return CfgUpdateFlags.RestartRqrd;
case 12:
for (FontSz sz = 0; sz < FontSz.Count; sz++)
{
if (str == sz.ToDescription())
@ -727,15 +738,15 @@ namespace TBF.Rig.DataEntry.Uni
}
}
return CfgUpdateFlags.None;
case 11: SetEnItemsCount(int.Parse(str)); return CfgUpdateFlags.RestartRqrd;
case 12: SetEnColumnsCount(int.Parse(str)); return CfgUpdateFlags.RestartRqrd;
case 13: EnIsLrOrder = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 14: EnIsCameraPicture = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 15: EnFormCloseKeys = str; return CfgUpdateFlags.RestartRqrd;
case 13: SetEnItemsCount(int.Parse(str)); return CfgUpdateFlags.RestartRqrd;
case 14: SetEnColumnsCount(int.Parse(str)); return CfgUpdateFlags.RestartRqrd;
case 15: EnIsLrOrder = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 16: EnIsCameraPicture = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 17: EnFormCloseKeys = str; return CfgUpdateFlags.RestartRqrd;
case 16: TestStartEndShowForm = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 17: TestTitle = str; return CfgUpdateFlags.RestartRqrd;
case 18:
case 18: TestStartEndShowForm = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 19: TestTitle = str; return CfgUpdateFlags.RestartRqrd;
case 20:
for (FontSz sz = 0; sz < FontSz.Count; sz++)
{
if (str == sz.ToDescription())
@ -745,13 +756,13 @@ namespace TBF.Rig.DataEntry.Uni
}
}
return CfgUpdateFlags.None;
case 19: SetTestColumnsCount(int.Parse(str)); return CfgUpdateFlags.RestartRqrd;
case 20: TestStartBoxAlwaysEn = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 21: TestIsLrOrder = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 22: TestIsCameraPicture = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 23: TestStartPicName = str; return CfgUpdateFlags.RestartRqrd;
case 24: TestEndPicName = str; return CfgUpdateFlags.RestartRqrd;
case 25: TestFormCloseKeys = str; return CfgUpdateFlags.RestartRqrd;
case 21: SetTestColumnsCount(int.Parse(str)); return CfgUpdateFlags.RestartRqrd;
case 22: TestStartBoxAlwaysEn = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 23: TestIsLrOrder = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 24: TestIsCameraPicture = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 25: TestStartPicName = str; return CfgUpdateFlags.RestartRqrd;
case 26: TestEndPicName = str; return CfgUpdateFlags.RestartRqrd;
case 27: TestFormCloseKeys = str; return CfgUpdateFlags.RestartRqrd;
default:
return CfgUpdateFlags.None;
@ -872,34 +883,36 @@ namespace TBF.Rig.DataEntry.Uni
case 2:
case 5:
case 6:
case 8:
case 10:
case 13:
case 14:
case 8://Auto close - yes/No
case 10://8+2
case 12:
case 15:
case 16:
case 18:
case 20:
case 21:
case 22:
case 23:
case 24:
message = string.Empty;
if (ParamValues(i).Contains(str)) return true;
break;
case 3:
case 4:
case 11:
case 12:
case 19:
case 9: //Gap AutoClose
case 13:
case 14:
case 21:
message = string.Empty;
if (int.TryParse(str, out idummy)) return true;
break;
case 1:
case 7:
case 9:
case 15:
case 11:
case 17:
case 23:
case 24:
case 19:
case 25:
case 26:
case 27:
message = string.Empty;
return true;
default:
@ -942,6 +955,8 @@ namespace TBF.Rig.DataEntry.Uni
prms.BgIsLrOrder = BgIsLrOrder;
prms.BgIsCameraPicture = BgIsCameraPicture;
prms.BgFormCloseKeys = BgFormCloseKeys;
prms.BgIsAutoReadingSerialNo = BgIsAutoReadingSerialNo;
prms.BgAutoCloseGap = BgAutoCloseGap;
prms.EnShowForm = EnShowForm;
prms.EnTitle = EnTitle;

View File

@ -155,6 +155,7 @@ namespace TBF.Rig.DataEntry.Uni
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
currentOp = CurrentOp.FormAtCycleBeginning;
this.waterMeters = Sequences.ProcessData.BatchRslts.Batch.WaterMeters;
regReaders = regReadersOptional;
return this;
}
@ -234,9 +235,17 @@ namespace TBF.Rig.DataEntry.Uni
DEItem.AddColumn(myCfg.BgColumnContent[i], myCfg.BgColumnCaption[i], myCfg.BgColumnAction[i], myCfg.BgColumnWidth[i]);
}
}
modelessDlg = new CycleBgEnForm(waterMeters, TBF.Data.LineSize, myCfg.BgTitle, myCfg.BgSize, myCfg.BgIsLrOrder, myCfg.BgIsCameraPicture,
myCfg.BgFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), false);
if (regReaders != null)
{
modelessDlg = new CycleBgEnForm(waterMeters, regReaders, TBF.Data.LineSize, myCfg.BgTitle, myCfg.BgSize, myCfg.BgIsLrOrder, myCfg.BgIsCameraPicture,
myCfg.BgFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), false, regReaders, myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap);
}
else
{
modelessDlg = new CycleBgEnForm(waterMeters, TBF.Data.LineSize, myCfg.BgTitle, myCfg.BgSize, myCfg.BgIsLrOrder, myCfg.BgIsCameraPicture,
myCfg.BgFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap, false);
}
modelessDlg.Show();
}
///
@ -264,7 +273,7 @@ namespace TBF.Rig.DataEntry.Uni
}
modelessDlg = new CycleBgEnForm(waterMeters, TBF.Data.LineSize, myCfg.EnTitle, myCfg.EnSize, myCfg.EnIsLrOrder, myCfg.EnIsCameraPicture,
myCfg.EnFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), true);
myCfg.EnFormCloseKeys, DEItem.GetItems(), DEItem.GetColumns(), myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap, true);
modelessDlg.Show();
}
///
@ -286,7 +295,8 @@ namespace TBF.Rig.DataEntry.Uni
modelessDlg = new TestStartEndForm(waterMeters, myRef.regReaders, TBF.Data.LineSize, myCfg.TestTitle, myCfg.TestSize,
myCfg.TestStartBoxAlwaysEn, myCfg.TestIsLrOrder, myCfg.TestFormCloseKeys,
DEItem.GetColumns(), isCompound, volumeUnit, myCfg.TestIsCameraPicture,
startImages, endImages, ocr, ocrMessage, myRef.OcrStream);
startImages,endImages, ocr, ocrMessage, myRef.OcrStream,
myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap);
modelessDlg.Show();
}
///
@ -308,7 +318,7 @@ namespace TBF.Rig.DataEntry.Uni
modelessDlg = new TestStartEndForm(waterMeters, myRef.regReaders, TBF.Data.LineSize, myCfg.TestTitle, myCfg.TestSize,
myCfg.TestStartBoxAlwaysEn, myCfg.TestIsLrOrder, myCfg.TestFormCloseKeys, DEItem.GetColumns(),
isCompound, volumeUnit, myCfg.TestIsCameraPicture, startImages, endImages,
ocr, ocrMessage, myRef.OcrStream, wmStartStateStr, refVolume, errLimLo, errLimHi);
ocr, ocrMessage, myRef.OcrStream, myCfg.BgIsAutoReadingSerialNo, myCfg.BgAutoCloseGap, wmStartStateStr, refVolume, errLimLo, errLimHi);
modelessDlg.Show();
}
///
@ -330,7 +340,7 @@ namespace TBF.Rig.DataEntry.Uni
modelessDlg = new TestStartEndForm(waterMeters, myRef.regReaders, TBF.Data.LineSize, myCfg.TestTitle, myCfg.TestSize,
myCfg.TestStartBoxAlwaysEn, myCfg.TestIsLrOrder, myCfg.TestFormCloseKeys, DEItem.GetColumns(),
isCompound, volumeUnit, myCfg.TestIsCameraPicture, startImages, endImages,
ocr, ocrMessage, myRef.OcrStream, wmStartStateStr, refVolume, errLimLo, errLimHi);
ocr, ocrMessage, myRef.OcrStream, myCfg.BgIsAutoReadingSerialNo,myCfg.BgAutoCloseGap, wmStartStateStr, refVolume, errLimLo, errLimHi);
modelessDlg.Show();
}
///

View File

@ -1,11 +1,11 @@
using Common;
using Config.Entities;
using log4net;
using System;
///
/// Copyright (c) 2022-2023 Sensus Slovensko a.s.
///
using System;
using System.IO;
using System.Xml.Serialization;
using TBF.Rig.Generic;
@ -97,16 +97,16 @@ namespace TBF.Rig.DataEntry.Uni
return pars;
}
public override bool UpdateFromDbEntity(ComponentProcedure dbEntity)
{
if (dbEntity == null) return false;
try
{
ProcParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcParams;
public override bool UpdateFromDbEntity(ComponentProcedure dbEntity)
{
if (dbEntity == null) return false;
try
{
ProcParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcParams;
procedureParamsEntity = dbEntity;
componentName = dbEntity.CmpntName;
procedure = dbEntity.Procedure;
procedureParamsEntity = dbEntity;
componentName = dbEntity.CmpntName;
procedure = dbEntity.Procedure;
if (tmp != null)
{
@ -118,7 +118,7 @@ namespace TBF.Rig.DataEntry.Uni
catch (Exception ex)
{
log.DebugFormat(
"Error during RRProcParams deserialization. CmpntName='{0}', Procedure='{1}', Parameters='{2}', Exception: {3}",
"Error during Procedure parameters deserialization. CmpntName='{0}', Procedure='{1}', Parameters='{2}', Exception: {3}",
dbEntity?.CmpntName,
dbEntity?.Procedure,
dbEntity?.Parameters,
@ -129,10 +129,10 @@ namespace TBF.Rig.DataEntry.Uni
}
}
/// <summary>
/// Parameterless constructor initializes the parameters
/// </summary>
public ProcParams()
/// <summary>
/// Parameterless constructor initializes the parameters
/// </summary>
public ProcParams()
{
}

View File

@ -13,6 +13,8 @@ using TBF.Rig.GenericDevices;
using TBF.Resources;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
using NHibernate.Util;
using static System.Net.Mime.MediaTypeNames;
namespace TBF.Rig.DataEntry.Uni
@ -60,6 +62,17 @@ namespace TBF.Rig.DataEntry.Uni
readonly double refVolume;
readonly double warningLimLo; /// limit to display exclamation mark, typically 2x errLimLo
readonly double warningLimHi; /// limit to display exclamation mark, typically 2x errLimHi
private bool _readDataFromRegReaders = true;
/// <summary>
/// automaticly read serial number from register reader
/// </summary>
bool bAutoRead;
///<summary>
///autoclose disabled by default, if > 0 is enabled
/// - in seconds
/// </summary>
int iAutocloseGap;
/// Derived from arguments in the constructor
readonly bool isEnd;
@ -121,10 +134,7 @@ namespace TBF.Rig.DataEntry.Uni
public TestStartEndForm()
{
InitializeComponent();
this.Icon = Properties.Resources.TBF_icon;
ControlBox = false;
ControlBox = false;
imageProcessingThread = null;
completed = false;
StartForceCloseHandler();
@ -157,7 +167,7 @@ namespace TBF.Rig.DataEntry.Uni
public TestStartEndForm(IList<WaterMeter> waterMeters, IRegReader[] regReaders, int _lineSize, string title, FontSz sz,
bool isStartBoxAlwaysEn, bool isLrOrder, string formCloseKeys, IList<DEItem> colItems, bool isCompound,
Unit initialVolumeUnit, bool isCameraPicture, string[] startImages, string[] endImages,
OcrVidi ocrVidi, string ocrMessage, string streamName, string[] wmStartStateStr = null,
OcrVidi ocrVidi, string ocrMessage, string streamName, bool bAutoRead, int iAutocloseGap, string[] wmStartStateStr = null,
double refVolume = 0, double errLimLo = 0, double errLimHi = 0)
: this()
{
@ -182,6 +192,8 @@ namespace TBF.Rig.DataEntry.Uni
this.refVolume = refVolume;
this.warningLimLo = 2 * errLimLo;
this.warningLimHi = 2 * errLimHi;
this.bAutoRead = bAutoRead;
this.iAutocloseGap = iAutocloseGap;
if (waterMeters == null || regReaders == null ||
(wmStartStateStr != null && wmStartStateStr.Length != (isCompound ? 2 : 1) * waterMeters.Count))
@ -466,6 +478,8 @@ namespace TBF.Rig.DataEntry.Uni
okButton.Text = Strings.OkBtnText;
}
/// <summary>
/// Initialize combo boxes state defined by related 'Action'.
/// Clear check boxes.
@ -496,6 +510,7 @@ namespace TBF.Rig.DataEntry.Uni
textBoxes[k, i].Enabled = (isStartBoxAlwaysEn || !isEnd) && waterMeters[i] != null && !waterMeters[i].Disabled
&& rrIx < regReaders.Length && regReaders[rrIx] != null;
}
}
else if (colItems[k].Content == Ct.StartStateAux)
{
@ -567,10 +582,207 @@ namespace TBF.Rig.DataEntry.Uni
}
}
if (bAutoRead)
{
log.Debug($"Reading serial numbers from register readers... IsEnd: {isEnd}");
this.VolumeStartReadbyRegReader += (s, eArgs) =>
{
log.Debug("Volume updated: " + eArgs.Volume);
UpdateVolume(eArgs.Reader, eArgs.Volume);
};
BeforeUpdate();
this.DoneUpdateByRegReader += (s, eArgs) =>
{
log.Debug("Volume updated DONE!");
DoneUpdate();
};
ReadVolumeAsync(regReaders);
}
isHandlersEnabled = true;
}
LinkedHashMap<string, bool> storeUIForUpdate = new LinkedHashMap<string, bool>();
private Cursor _previousCursor;
private bool GetStoredOrDefault(string key)
{
bool value;
if (storeUIForUpdate.TryGetValue(key, out value))
return value;
return true; // default if nothing stored
}
private void BeforeUpdate()
{
log.Debug("BeforeUpdate");
storeUIForUpdate["okButton"] = this.okButton.Enabled;
storeUIForUpdate["largeTextBox"] = this.largeTextBox.Enabled;
storeUIForUpdate["largeExclamationLabel"] = this.largeExclamationLabel.Enabled;
storeUIForUpdate["unitComboBox"] = this.unitComboBox.Enabled;
this.okButton.Enabled = false;
this.largeTextBox.Enabled = false;
this.largeExclamationLabel.Enabled = false;
this.unitComboBox.Enabled = false;
_previousCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
}
private void DoneUpdate()
{
log.Debug("DoneUpdate");
this.okButton.Enabled = GetStoredOrDefault("okButton");
this.largeTextBox.Enabled = GetStoredOrDefault("largeTextBox");
this.largeExclamationLabel.Enabled = GetStoredOrDefault("largeExclamationLabel");
this.unitComboBox.Enabled = GetStoredOrDefault("unitComboBox");
Cursor.Current = _previousCursor;
if (iAutocloseGap > 0)
{
AutoClickOkAfterDelay();
}
}
public void UpdateVolume(IRegReader eArgsReader, double eArgsVolume)
{
log.Debug($"RegReader name: {eArgsReader.Name}, Serial No updated: " + eArgsVolume);
PopulateVolume(eArgsReader, eArgsVolume);
}
/// 24-bit counter wrap in liters: 2^24 ticks * 0.00025 L/tick
private const double VOL_RANGE_LITERS = 16777216.0 * 0.00025; // 4194.304
/// <summary>
/// Populate Volume - also include roll over VOL_RANGE_LITERS
/// Unit test Concept: TBFTests/Rig/DataEntry/Uni/PopulateVolumeRolloverTests_Concept.cs
/// </summary>
/// <param name="eArgsReader"></param>
/// <param name="eArgsVolume"></param>
public void PopulateVolume(IRegReader eArgsReader, double eArgsVolume)
{
if (regReaders == null || Double.IsNaN(eArgsVolume) || textBoxes == null)
return;
int regReadersLength = regReaders.Length;
int comboRows = textBoxes.GetLength(0);
int comboCols = textBoxes.GetLength(1);
//just combine Start and End - switch column to write
List<Ct> ctValues = isEnd
? new List<Ct> { Ct.EndState, Ct.EndStateAux }
: new List<Ct> { Ct.StartState, Ct.StartStateAux };
double VolumeRaw = eArgsVolume;
// Test and compensate roll over
if (isEnd)
{
if (eArgsReader != null && (!Double.IsNaN(eArgsReader.BeginWMState)))
{
if (eArgsReader.BeginWMState > VolumeRaw) //Do RollOver
{
VolumeRaw = eArgsVolume + VOL_RANGE_LITERS;
log.Debug(
$"Roll over detected: {eArgsReader.Name} - {eArgsReader.BeginWMState} -> {VolumeRaw}");
}
}
else
{
//volume from form
Double beginVolume = findBeginStateFromForm();
if (beginVolume > VolumeRaw) //Do RollOver
{
VolumeRaw = eArgsVolume + VOL_RANGE_LITERS;
log.Debug(
$"Begin from Form! Roll over detected: {eArgsReader.Name} - {beginVolume} -> {VolumeRaw}");
}
}
}
for (int k = 0; k < colItems.Count && k < comboRows; k++)
{
Ct current = (Ct)colItems[k].Content;
if (ctValues.Contains(current)) // it define if is start or end
{
for (int ix = 0; ix < wmsCount && ix < comboCols; ix++)
{
int regIndex = ix;
if (regIndex >= 0 && regIndex < regReadersLength)
{
var textBox = textBoxes[k, ix];
if (textBox != null && regReaders[regIndex] == eArgsReader)
{
try
{
if (VolumeUnit == Unit.None)
VolumeUnit = Unit.l;
Double convertTo = Units.ConvertTo(VolumeUnit, VolumeRaw);
textBox.Text = convertTo.ToString();
}
catch (Exception ex)
{
log.Error($"Error converting volume to {VolumeUnit}: {ex.Message}");
}
}
}
}
}
}
}
private Double findBeginStateFromForm()
{
List<Ct> ctValues = new List<Ct> { Ct.StartState, Ct.StartStateAux };
int regReadersLength = regReaders.Length;
int comboRows = textBoxes.GetLength(0);
int comboCols = textBoxes.GetLength(1);
for (int k = 0; k < colItems.Count && k < comboRows; k++)
{
Ct current = (Ct)colItems[k].Content;
if (ctValues.Contains(current)) // it define if is start or end
{
for (int ix = 0; ix < wmsCount && ix < comboCols; ix++)
{
int regIndex = ix;
if (regIndex >= 0 && regIndex < regReadersLength)
{
var textBox = textBoxes[k, ix];
if (textBox != null && textBox.Text != null && textBox.Text.Length > 0)
{
try
{
if (VolumeUnit == Unit.None)
VolumeUnit = Unit.l;
double VolumeRaw = Double.Parse(textBox.Text);
Double convertBeginVolumeINLiters = Units.ConvertFrom(VolumeUnit, VolumeRaw);
return convertBeginVolumeINLiters;
}
catch (Exception ex)
{
log.Error($"Error converting volume to {VolumeUnit}: {ex.Message}");
}
}
}
}
}
}
return 0.0D;
}
/// <summary>
/// When one combo box is updated using drop-down menu, all combo boxes
/// are updated by this function.
@ -1181,7 +1393,11 @@ namespace TBF.Rig.DataEntry.Uni
Brush lightBrush = new SolidBrush(Color.LightGreen);
Brush darkBrush = new SolidBrush(Color.Green);
Font largeFont = new Font("arial", 24.0F, FontStyle.Bold); /// normal image
Font smallFont = new Font("arial", 12.0F, FontStyle.Bold); /// zoomed image
Font smallFont = new Font("arial", 12.0F, FontStyle.Bold);
/// zoomed image
/// <summary>
/// Show selected image in the picture box.
@ -1252,5 +1468,137 @@ namespace TBF.Rig.DataEntry.Uni
}
#endregion
public event EventHandler<VolumeReadEventArgs> VolumeStartReadbyRegReader;
public event EventHandler<VolumeReadDoneEventArgs> DoneUpdateByRegReader;
public sealed class VolumeReadEventArgs : EventArgs
{
public IRegReader Reader { get; private set; }
public double Volume { get; private set; }
public VolumeReadEventArgs(IRegReader reader, double volume)
{
Reader = reader;
Volume = volume;
}
}
public sealed class VolumeReadDoneEventArgs : EventArgs
{
public VolumeReadDoneEventArgs()
{
}
}
protected virtual void OnReadVolume(IRegReader reader, double volume)
{
var handler = VolumeStartReadbyRegReader; // copy for thread-safety
if (handler == null) return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() =>
handler(this, new VolumeReadEventArgs(reader, volume))));
}
else
{
handler(this, new VolumeReadEventArgs(reader, volume));
}
}
protected virtual void OnReadDone()
{
var handler = DoneUpdateByRegReader; // copy for thread-safety
if (handler == null) return;
if (IsHandleCreated && InvokeRequired)
{
BeginInvoke(new Action(() =>
handler(this, new VolumeReadDoneEventArgs())));
}
else
{
handler(this, new VolumeReadDoneEventArgs());
}
}
public async void ReadVolumeAsync(IEnumerable<IRegReader> regReaders)
{
log.Debug("Reading serial numbers from register readers...");
try
{
var groups = regReaders
.OfType<IRegReaderSmart>()
.GroupBy(r => r.Group)
.OrderBy(g => g.Key);
foreach (var group in groups)
{
var subGroups = group
.GroupBy(r => r.MuxBoardNrOrGroup14)
.OrderBy(sg => sg.Key);
foreach (var subGroup in subGroups)
{
log.Debug(string.Format("Processing Group {0}, SubGroup {1}", group.Key, subGroup.Key));
// Start tasks in parallel inside subgroup
var tasks = subGroup.Select(async r =>
{
double volume = Double.NaN;
if (isEnd)
{
volume = await r.DataEntry_ReadEndVolume().ConfigureAwait(false);
}
else
{
volume = await r.DataEntry_ReadBeginVolume().ConfigureAwait(false);
}
return new KeyValuePair<IRegReader, double>((IRegReader)r, volume);
}).ToList();
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
foreach (var kv in results)
{
var reader = kv.Key;
var volume = kv.Value;
// Notify for each successful read
OnReadVolume(reader, volume);
}
}
}
}
catch (Exception ex)
{
log.Error("Error reading Strat Volume from register readers", ex);
}
finally
{
OnReadDone();
}
log.Debug("Reading Start Volume DONE!");
}
public void AutoClickOkAfterDelay(int delayMs = 10000)
{
_ = AutoClickInternal(okButton, delayMs);
}
private async Task AutoClickInternal(Button clickButton, int delayMs)
{
await Task.Delay(delayMs);
if (clickButton.IsHandleCreated && clickButton.Enabled && clickButton.Visible)
{
// Invoke on UI thread
if (clickButton.InvokeRequired)
clickButton.BeginInvoke(new Action(() => clickButton.PerformClick()));
else
clickButton.PerformClick();
}
}
}
}

View File

@ -39,10 +39,7 @@ namespace TBF.Rig.DataEntry.iPerl
public CycleBeginningForm()
{
InitializeComponent();
this.Icon = Properties.Resources.TBF_icon;
ControlBox = false;
ControlBox = false;
completed = false;
StartForceCloseHandler();

View File

@ -50,10 +50,7 @@ namespace TBF.Rig.DataEntry.iPerl
public TestStartEndForm()
{
InitializeComponent();
this.Icon = Properties.Resources.TBF_icon;
ControlBox = false;
ControlBox = false;
TextBoxesCount = 48;

View File

@ -54,9 +54,12 @@ namespace TBF.Rig.Dummy.FlowMeter
double msrdValLimLo = 0;
double msrdValLimHi;
[XmlIgnore]
public bool IsOffline { get; set; }
/// Private parameterless constructor invoked by all other (public) constructors
FlowMeterCfg()
/// Private parameterless constructor invoked by all other (public) constructors
FlowMeterCfg()
{
GNodes = new List<GNode>();
}
@ -89,7 +92,7 @@ namespace TBF.Rig.Dummy.FlowMeter
{
"Nominal flow [m3/h]", /// 0
"Display format", /// 1
"Unit of flow on a display", /// 2
"Units of flow on a display", /// 2
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }

View File

@ -0,0 +1,16 @@
using System;
using System.Threading.Tasks;
namespace TBF.Rig.GenericDevices
{
public interface IRegReaderSmart
{
Task<string> DataEntry_ReadSerialNumber();
Task<double> DataEntry_ReadBeginVolume();
Task<double> DataEntry_ReadEndVolume();
int Group { get; }
int MuxBoardNrOrGroup14 { get; }
}
}

View File

@ -14,7 +14,7 @@ namespace TBF.Rig.GenericDevices
float BuoyancyTemp { get; set; } /// ambient temperature in [degree C]
float BuoyancyPress { get; set; } /// ambient pressure in [100000 Pa]
float BuoyancyHumi { get; set; } /// ambient relative humidity in [%]
float WeightStandardDensity { get; set; } /// density of the weight standard used to calibrate the scale [kg/m3]
float WeightStandardDensity { get; set; } /// density of the volume standard used to calibrate the scale [kg/m3]
}
}

View File

@ -9,12 +9,19 @@ namespace TBF.Rig.GenericDevices
{
public interface ITestMethod : TBF.Rig.Generic.IComponent
{
/// <summary>
/// Check compatibility of the method with the watermeters
/// </summary>
/// <param name="meters">Type of watermeters</param>
/// <returns>true when the watermeters can be tested by this method</returns>
bool CanTest(MetersKind meters);
/// <summary>
/// Check compatibility of the method with the watermeters
/// </summary>
/// <param name="meters">Type of watermeters</param>
/// <returns>true when the watermeters can be tested by this method</returns>
FlowType MethodFlowType { get; }
/// <summary>
/// Check compatibility of the method with the watermeters
/// </summary>
/// <param name="meters">Type of watermeters</param>
/// <returns>true when the watermeters can be tested by this method</returns>
bool CanTest(MetersKind meters);
/// <summary>
/// Check capabilities of devces in the output path required for this test method

View File

@ -0,0 +1,11 @@
namespace TBF.Rig.GenericDevices
{
/// <summary>
/// * mark test method from smart family devices
/// * (this Test method is used for devices that support smart reader)
/// </summary>
public interface ITestMethodSmart
{
}
}

View File

@ -56,23 +56,39 @@ namespace TBF.Rig.Sequences
{
try
{
// /// 1nd argument
// ITestMethodCfg testMethodCfg = cfg as ITestMethodCfg;
// if (testMethodCfg == null)
// {
//
// }
//
// /// 2rd argument: as is
//
// /// 3th argument
// IList<ITestParams> iPerlCommParams = new List<ITestParams>();
// foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as iPerlCommunicationParams);
//
// /*myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(iPerlCfg, tests, iPerlCommParams);
// myRef.modelessDlg.Show();*/
//
// myRef.modelessDlg = new SmartCommunicationForm( testMethod , tests, iPerlCommParams);
// myRef.modelessDlg.Show();
/// 1nd argument
ITestMethodCfg testMethodCfg = cfg as ITestMethodCfg;
if (testMethodCfg == null)
{
}
TestMethods.iPerlCommunication.TestMethodCfg iPerlCfg = cfg as TestMethods.iPerlCommunication.TestMethodCfg;
/// 2rd argument: as is
/// 3th argument
IList<ITestParams> iPerlCommParams = new List<ITestParams>();
foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as iPerlCommunicationParams);
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(iPerlCfg, tests, iPerlCommParams);
myRef.modelessDlg.Show();*/
myRef.modelessDlg = new SmartCommunicationForm( testMethod , tests, iPerlCommParams);
myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(
testMethod as TBF.Rig.TestMethods.iPerlCommunication.TestMethod, tests, iPerlCommParams);
myRef.modelessDlg.Show();
}
catch (Exception e)

View File

@ -13,6 +13,9 @@ namespace TBF.Rig.TestMethods.Adjustment
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -13,6 +13,9 @@ namespace TBF.Rig.TestMethods.ChangeFlowDirection
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -24,6 +24,8 @@ namespace TBF.Rig.TestMethods.CombinedWithDetection
readonly TestMethodCfg testMethodCfg;
public bool IsRise { get { return testMethodCfg != null ? testMethodCfg.IsRise : false; } }
public FlowType MethodFlowType => FlowType.volume;
public TestMethod() { }
///
public TestMethod(Generic.IComponentCfg cfg)

View File

@ -29,6 +29,9 @@ namespace TBF.Rig.TestMethods.Counter
/// </summary>
static int nextCounterIdx = 0;
public static int CountersCount { get { return nextCounterIdx; } }
public FlowType MethodFlowType => FlowType.volume;
public static TestMethod[] Counters = new TestMethod[0];
///
private int counterIdx0; /// 0-based index of this counter

View File

@ -24,7 +24,9 @@ namespace TBF.Rig.TestMethods.DiverterTest
readonly TestMethodCfg testMethodCfg;
public Component() { }
public FlowType MethodFlowType => FlowType.volume;
public Component() { }
public Component(Generic.IComponentCfg cfg)
: base(cfg)

View File

@ -13,6 +13,9 @@ namespace TBF.Rig.TestMethods.Dummy
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -24,6 +24,8 @@ namespace TBF.Rig.TestMethods.Endurance
readonly TestMethodCfg testMethodCfg;
public FlowType MethodFlowType => FlowType.volume;
public Component() { }
///
public Component(Generic.IComponentCfg cfg)

View File

@ -12,7 +12,9 @@ namespace TBF.Rig.TestMethods.Evacuation
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public override string ToString()
public FlowType MethodFlowType => FlowType.volume;
public override string ToString()
{
return string.Format("{0}({1})", GetType().Namespace.Substring(8), Cfg.ToString(1));
}

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStart.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStart.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStart.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -13,6 +13,9 @@ namespace TBF.Rig.TestMethods.FixedStartAdvanced.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -35,7 +35,9 @@ namespace TBF.Rig.TestMethods.FixedStartDeferredEval.Compound
private IntermediateData intermediateData;
public object IntermediateData { get { return intermediateData; } }
public IList<Event> Execute(Test test, int repetNr, bool isLastRepetition)
public FlowType MethodFlowType => FlowType.volume;
public IList<Event> Execute(Test test, int repetNr, bool isLastRepetition)
{
return (new FixedStartDeferredEvalSeq()).Execute(test, repetNr, isLastRepetition, true, null, DebugLevel, out intermediateData);
}

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartDeferredEval.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethodWith2ndPass
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartDeferredEval.Single
public class Component : ComponentBase, GenericDevices.ITestMethodWith2ndPass
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollAdvanced.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod, ISequenceCondition
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollAdvanced.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod, ISequenceCondition
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollAdvanced.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollDeferredEval.Compound
public class Component : ComponentBase, GenericDevices.ITestMethodWith2ndPass
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollDeferredEval.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethodWith2ndPass
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartMassCollDeferredEval.Single
public class Component : ComponentBase, GenericDevices.ITestMethodWith2ndPass
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartTankCollection.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FixedStartTankCollection.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlowAdjustment
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStart.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStart.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStart.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartFirstRepetWithMassColl.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartFirstRepetWithMassColl.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartFirstRepetWithMassColl.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollComparative.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollComparative.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollComparative.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollProlonged.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollProlonged.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollProlonged.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartTankCollection.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.FlyingStartTankCollection.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.GrabImage
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -15,6 +15,8 @@ namespace TBF.Rig.TestMethods.LeakTest
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.LiveStream
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.ManualEntry
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
readonly ManualEntryCfg myCfg;

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.OuterLoop.End
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.OuterLoop.Start
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -15,6 +15,8 @@ namespace TBF.Rig.TestMethods.PMaxTest
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.PulsesTest
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.PulsesTestManual
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.Q2CorrectionFromHistory
public class Component : ComponentBase, GenericDevices.ISimultTestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.RoiDetection
public class RoiDetection : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(RoiDetection));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return true; }

View File

@ -21,7 +21,9 @@ namespace TBF.Rig.TestMethods.S640Communication
public class S640End : ComponentBase, GenericDevices.ISimultTestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(S640End));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return false; }

View File

@ -21,7 +21,9 @@ namespace TBF.Rig.TestMethods.S640Communication
public class S640Start : ComponentBase, GenericDevices.ISimultTestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(S640Start));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return false; }

View File

@ -13,6 +13,8 @@ namespace TBF.Rig.TestMethods.SensitivityTest
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -22,7 +22,8 @@ namespace TBF.Rig.TestMethods.SmartMeterFlyingStartMassCollection
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return false; }
public bool SimultWithPrevious { get { return _testMethodCfg.TestParams.SimultWithPrevious; } }

View File

@ -22,6 +22,8 @@ namespace TBF.Rig.TestMethods.SmartTest
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return false; }

View File

@ -12,6 +12,9 @@ namespace TBF.Rig.TestMethods.StandingStart.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.StandingStart.HeatMeters
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }

View File

@ -12,6 +12,9 @@ namespace TBF.Rig.TestMethods.StandingStart.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,9 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollWODiv
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -12,6 +12,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollection.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollection.HeatMeters
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }
public bool DoTransitions() { return true; }
public bool CheckDeviceCaps(Test test, OutputPath devices, out string message)

View File

@ -13,7 +13,9 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollection.Single
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return true; }
public bool CheckDeviceCaps(Test test, OutputPath devices, out string message)

View File

@ -12,6 +12,9 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance.Compound
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance.HeatMeters
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }
public bool DoTransitions() { return true; }
public bool CheckDeviceCaps(Test test, OutputPath devices, out string message)

View File

@ -17,6 +17,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance.Single
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool IsSupportedCollector(IComponent component) { return (component is IProcedureCameraCollect); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return true; }
public bool CheckDeviceCaps(Test test, OutputPath devices, out string message)

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvanceCollect.Single
public class Component : ComponentBase, GenericDevices.ITestMethod, IProcedureCameraCollect
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.volume;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
private Procedure parentProcedure;

View File

@ -14,6 +14,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionPoseidon.Compound
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.Combined; }
public bool DoTransitions() { return true; }
public bool CheckDeviceCaps(Test test, OutputPath devices, out string message)

View File

@ -13,7 +13,9 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionPoseidon.HeatMeters
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.HeatMeter; }
public bool DoTransitions() { return true; }
public bool CheckDeviceCaps(Test test, OutputPath devices, out string message)

View File

@ -12,6 +12,9 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionPoseidon.Single
public class Component : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
public FlowType MethodFlowType => FlowType.mass;
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }

View File

@ -31,7 +31,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
ThreadId,
WMNr0,
(Ihead != null) ? Ihead.Name : "null",
Wm.WMPosition,
(Wm != null) ? Wm.WMPosition : -1,
(CommMessage != null) ? CommMessage : "null",
CommErr);
}

View File

@ -1,4 +1,4 @@
using Config.Resources;
using Config.Resources;
using log4net;
using Sensus.iPerl.RfidCom.Helper;
using Sensus.iPerl.RfidCom.Services;
@ -7,8 +7,6 @@ using System;
using System.Threading;
using TBF.Rig.Hart.Common;
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations;
using static Sensus.iPerl.NfcHandler.MCI_Protocol;
namespace TBF.Rig.TestMethods.iPerlCommunication
@ -28,7 +26,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
try
{
byte[] pcb = null;
int readRetVal = IPerlCorrections.ReadRequestPort(SmartCommunicationForm.TestMethodCfg, iHead, RegisterReaders.CommonRR.MessageID.Configuration, Sensus.iPerl.NfcHandler.MCI_Protocol.StructName.Configuration, 16, 5, out pcb);
int readRetVal = iPerlCommunicationForm.ReadRequestPort(iHead, MessageID.Configuration, Sensus.iPerl.NfcHandler.MCI_Protocol.StructName.Configuration, 16, 5, out pcb);
if (readRetVal == 0)
{
return RfidHelper.HexLiteral2Unsigned(RfidHelper.SwapHexcode(BitConverter.ToString(pcb).Replace("-", string.Empty))).ToString();
@ -45,7 +43,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
internal static string SetActiveMode(IperlHead iHead)
{
byte[] cmd = new byte[1] { (byte)Command.SetActiveMode };
if (0 == IPerlCorrections.WriteRequestPort(SmartCommunicationForm.TestMethodCfg, iHead, RegisterReaders.CommonRR.MessageID.Command, StructName.Command, 0, 1, cmd))
if (0 == iPerlCommunicationForm.WriteRequestPort(iHead, MessageID.Command, StructName.Command, 0, 1, cmd))
{
return "OK";
}
@ -58,7 +56,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
internal static string SetTestMode(IperlHead iHead)
{
byte[] cmd = new byte[1] { (byte)Command.SetTestMode };
if (0 == IPerlCorrections.WriteRequestPort(SmartCommunicationForm.TestMethodCfg, iHead, RegisterReaders.CommonRR.MessageID.Command, StructName.Command, 0, 1, cmd))
if (0 == iPerlCommunicationForm.WriteRequestPort(iHead, MessageID.Command, StructName.Command, 0, 1, cmd))
{
return "OK";
}
@ -73,7 +71,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
{
try
{
int retValue = IPerlCorrections.WriteRequestPort(SmartCommunicationForm.TestMethodCfg, iHead, RegisterReaders.CommonRR.MessageID.RadioPassthrough, StructName.RadioParams, 0x1898, 1, new byte[] { (byte)3 }); // WakeUpInterval
int retValue = iPerlCommunicationForm.WriteRequestPort(iHead, MessageID.RadioPassthrough, StructName.RadioParams, 0x1898, 1, new byte[] { (byte)3 }); // WakeUpInterval
return 0 == retValue ? "OK" : "Error";
}
catch (Exception ex)
@ -86,7 +84,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
{
try
{
int retValue = IPerlCorrections.WriteRequestPort(SmartCommunicationForm.TestMethodCfg,iHead, RegisterReaders.CommonRR.MessageID.RadioPassthrough, StructName.RadioInfo, 0x1804, 1, new byte[] { (byte)1 }); // System Status
int retValue = iPerlCommunicationForm.WriteRequestPort(iHead, MessageID.RadioPassthrough, StructName.RadioInfo, 0x1804, 1, new byte[] { (byte)1 }); // System Status
return 0 == retValue ? "OK" : "Error";
}
catch (Exception ex)

View File

@ -6,7 +6,6 @@ using System.Collections.Generic;
using log4net;
using Common;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
using TBF.Rig.Sequences;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
@ -14,18 +13,20 @@ using TBF.UiBridge;
namespace TBF.Rig.TestMethods.iPerlCommunication
{
public class TestMethod : SmartComponentBase, ISimultTestMethod, ISequenceCondition, ISessionDataMngmnt
public class TestMethod : SmartComponentBase, ISimultTestMethod, ISequenceCondition, ISessionDataMngmnt, ITestMethodSmart
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public FlowType MethodFlowType => FlowType.volume;
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
public bool CanTest(MetersKind meters) { return meters == MetersKind.Single; }
public bool DoTransitions() { return false; }
public bool SimultWithPrevious { get { return _testMethodCfgIPerl.TestParams.SimultWithPrevious; } }
public bool SimultWithNext { get { return _testMethodCfgIPerl.TestParams.SimultWithNext; } }
public bool SimultWithPrevious { get { return testMethodCfg.TestParams.SimultWithPrevious; } }
public bool SimultWithNext { get { return testMethodCfg.TestParams.SimultWithNext; } }
#region Configuration Change Handling
@ -42,18 +43,18 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
{
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
{
TestMethodCfg_IPerl tmpCfgIPerl = args.Cfg as TestMethodCfg_IPerl;
if (tmpCfgIPerl != null && tmpCfgIPerl.Name.Equals(Name))
TestMethodCfg tmpCfg = args.Cfg as TestMethodCfg;
if (tmpCfg != null && tmpCfg.Name.Equals(Name))
{
if (args.Command == CfgChangeCmd.CfgChange)
{
_testMethodCfgIPerl.CommTimeout = tmpCfgIPerl.CommTimeout;
_testMethodCfgIPerl.DelayBetweenRetries = tmpCfgIPerl.DelayBetweenRetries;
_testMethodCfgIPerl.MaxCommRetries = tmpCfgIPerl.MaxCommRetries;
_testMethodCfgIPerl.IperlCheckErrorsToStop = tmpCfgIPerl.IperlCheckErrorsToStop;
_testMethodCfgIPerl.UseWebService = tmpCfgIPerl.UseWebService;
_testMethodCfgIPerl.BaseUrl = tmpCfgIPerl.BaseUrl;
_testMethodCfgIPerl.RelativeUrl = tmpCfgIPerl.RelativeUrl;
testMethodCfg.CommTimeout = tmpCfg.CommTimeout;
testMethodCfg.DelayBetweenRetries = tmpCfg.DelayBetweenRetries;
testMethodCfg.MaxCommRetries = tmpCfg.MaxCommRetries;
testMethodCfg.IperlCheckErrorsToStop = tmpCfg.IperlCheckErrorsToStop;
testMethodCfg.UseWebService = tmpCfg.UseWebService;
testMethodCfg.BaseUrl = tmpCfg.BaseUrl;
testMethodCfg.RelativeUrl = tmpCfg.RelativeUrl;
}
}
};
@ -62,7 +63,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
#endregion Configuration Change Handling
readonly TestMethodCfg_IPerl _testMethodCfgIPerl;
readonly TestMethodCfg testMethodCfg;
public bool[] IperlCommMilestone;
IList<IOperation> sequenceConditionOps;
@ -75,7 +76,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
public TestMethod(Generic.IComponentCfg cfg)
: base(cfg)
{
_testMethodCfgIPerl = cfg as TestMethodCfg_IPerl;
testMethodCfg = cfg as TestMethodCfg;
CreateMilestonesAndConditions();
}
@ -110,7 +111,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
{
if (DebugLevel == DebugMode.Normal)
{
return (new iPerlCommunicationSeq()).Execute(test, repetNr, this, _testMethodCfgIPerl.TestParams);
return (new iPerlCommunicationSeq()).Execute(test, repetNr, this, testMethodCfg.TestParams);
}
else
{

View File

@ -14,9 +14,9 @@ using TBF.Rig.TestMethods.SmartMeterFlyingStartMassCollection;
namespace TBF.Rig.TestMethods.iPerlCommunication
{
[XmlRoot("TestMethodCfg")] // Add this attribute to match the XML root
public class TestMethodCfg_IPerl : ComponentCfgBase, IiPerlTestMethodCfg
public class TestMethodCfg : ComponentCfgBase, IiPerlTestMethodCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TestMethodCfg_IPerl) })[0];
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TestMethodCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new TestMethodCfgCtrl(); }
@ -30,7 +30,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
}
/// Private parameterless constructor invoked by all other (public) constructors
TestMethodCfg_IPerl()
TestMethodCfg()
{
Name = "SmartCommunication";
ParentName = string.Empty;
@ -49,7 +49,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
TestParams = CreateTestParamsProvider() as iPerlCommunicationParams;
}
public TestMethodCfg_IPerl(IComponentFactory factory)
public TestMethodCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;

View File

@ -7,7 +7,6 @@ using Common;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Resources;
using TBF.Rig.RegisterReaders.CommonRR.IPerl;
namespace TBF.Rig.TestMethods.iPerlCommunication
{
@ -15,13 +14,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
{
public bool ShowMore { get { return false; } }
TestMethodCfg_IPerl config;
TestMethodCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as TestMethodCfg_IPerl;
config = value as TestMethodCfg;
Redraw();
}
}

View File

@ -9,18 +9,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
public class TestMethodFactory : IComponentFactory
{
public string ClassName { get { return GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public IComponent DummyComponent() { return new TestMethod(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new TestMethod(cfg); }
public IComponentCfg DefaultConfig() { return new TestMethodCfg_IPerl(this); }
public IComponentCfg DefaultConfig() { return new TestMethodCfg(this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(TestMethodCfg_IPerl.Serializer, component, this);
return ComponentCfgBase.CreateFromDbEntity(TestMethodCfg.Serializer, component, this);
}
}
}

View File

@ -0,0 +1,351 @@
///
/// Copyright (c) 2015-2021 Sensus Metering Systems
///
using System;
using System.Globalization;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed.parserer;
namespace TBF.Rig.TestMethods.iPerlCommunication.common
{
public enum OptoTelegramFlags : byte
{
OK = 0,
OK_TestStart,
OK_TestEnd,
InvalidTelegram, /// Wrong telegram format of checksum error
SyncError,
}
public class OptoTelegramRaw
{
public static readonly int Length = 42;
private static CultureInfo culture;
///
/// Strobed value
///
public static decimal TestStartTimestampDec;
///
/// Stored values
///
public OptoTelegramFlags Flags;
public DateTime DateTime; /// From PC
public float RefFlow; /// [m3/h]
public int Counter;
public Int32 EmfRaw; /// Signed EMF from iPerl opto data
public Int16 MagneticFieldRaw;
public Int16 FlowRaw;
public double VolumeRaw;
public double VolumeRawExt;
public Int16 Impedance;
public double Timestamp;
public double TimestampExt;
public byte CheckSum;
///
/// Calculated values
///
public double EMF()
{
return 0.000000333 * (double)EmfRaw;
}
public double MagneticField() { return (double)MagneticFieldRaw; }
public double Flow(double scalingFactor) { return 0.225 * scalingFactor * (double)FlowRaw; }
public double Volume(double scalingFactor) { return 0.0000625 * scalingFactor * (double)VolumeRawExt; }
public Int32 FlipTime() { return Impedance; }
public decimal TimestampDec() { return (decimal)TimestampExt / (decimal)8192; }
public double VolumeDelta(double scalingFactor, OptoTelegramRaw previous) { return (previous == null) ? 0 : Volume(scalingFactor) - previous.Volume(scalingFactor); }
public decimal TimeDelta() { return TimestampDec() - TestStartTimestampDec; }
public string Label()
{
if (Flags == OptoTelegramFlags.OK_TestStart) return "#### start test ####";
else if (Flags == OptoTelegramFlags.OK_TestEnd) return "#### end of test ####";
else return string.Empty;
}
static OptoTelegramRaw()
{
culture = CultureInfo.CreateSpecificCulture("DE"); /// This is to use comma as decimal number separator
}
public OptoTelegramRaw()
{
}
/// <summary>
/// Parses optical telegram and returns OptoTelegramRaw object
/// </summary>
/// <description>
/// Create a configuration structure from a complete byte array
///
/// Telegram description:
///
/// AAAAAA[tab]BBBB[tab]CCCC[tab]DDDDDD[tab]EEEE[tab]FFFFFFFF[tab]GG[cr][lf] (42 bytes)
///
/// Data Comment Type Calculate to decimal
/// ----------------------------------------------------------------
/// AAAAAA EMF Int24 Value * 0.000000333
/// BBBB Magnetic field Int16 Value
/// CCCC Flow Int16 Value * 0.225 * Scalig factor
/// DDDDDD Volume Int24 Value / 16000 * Scaling factor
/// EEEE Impedance Int16 Value
/// FFFFFFFF Timestamp Uint32 Value / 8192
/// GG Checksum Byte
/// ----------------------------------------------------------------
///
/// Example:
/// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86
/// FFDD3A 51F9 0000 65324E 0088 F631A60B 45
/// ...
/// </description>
/// <param name="data">A complete byte array data</param>
/// <returns>true = telegram OK, false = telegram NOK</returns>
// public bool UpdateFromString(string telegram, int counter, float refFlow, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast, bool isLog = false)
// {
// DateTime = DateTime.Now;
// Counter = counter;
// RefFlow = refFlow;
//
// if ((telegram == null) || (telegram.Length < Length) ||
// (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') ||
// (telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') ||
// (!isLog && (telegram[40] != '\r' || telegram[41] != '\n')))
// {
// Flags = OptoTelegramFlags.InvalidTelegram;
// return false;
// }
//
// UInt32 uEmfRaw;
// bool f1 = UInt32.TryParse(telegram.Substring(0, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uEmfRaw);
// EmfRaw = (uEmfRaw > 0x7FFFFF) ? ((int)uEmfRaw - 0x1000000) : (int)uEmfRaw;
//
// bool f2 = Int16.TryParse(telegram.Substring(7, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out MagneticFieldRaw);
// bool f3 = Int16.TryParse(telegram.Substring(12, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out FlowRaw);
// bool f4 = UInt32.TryParse(telegram.Substring(17, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out VolumeRaw);
// bool f5 = Int16.TryParse(telegram.Substring(24, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out Impedance);
// bool f6 = UInt32.TryParse(telegram.Substring(29, 8), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out Timestamp);
// bool f7 = byte.TryParse(telegram.Substring(38, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out CheckSum);
//
// byte calculatedCheckSum = 0;
// for (int i = 0; i < Length - 4; i++)
// {
// calculatedCheckSum += (byte)telegram[i];
// }
//
// bool allOk = f1 && f2 && f3 && f4 && f5 && f6 && f7 && (calculatedCheckSum == CheckSum);
//
// if (allOk)
// {
// ///
// /// Cope with 'VolumeRaw' overflow
// ///
// Int64 uncorrected = (Int64)(((UInt64)volumeRawExtLast & 0xFFFFFFFFFF000000UL) | VolumeRaw);
// if (Math.Abs(uncorrected - volumeRawExtLast) <= 0x800000L)
// {
// VolumeRawExt = volumeRawExtLast = uncorrected;
// }
// else if (Math.Abs(uncorrected + 0x1000000L - volumeRawExtLast) <= 0x800000L)
// {
// VolumeRawExt = volumeRawExtLast = uncorrected + 0x1000000L;
// }
// else if (Math.Abs(uncorrected - 0x1000000L - volumeRawExtLast) <= 0x800000L)
// {
// VolumeRawExt = volumeRawExtLast = uncorrected - 0x1000000L;
// }
// else
// {
// VolumeRawExt = volumeRawExtLast = uncorrected;
// }
//
// ///
// /// Cope with 'Timestamp' overflow
// ///
// uncorrected = (Int64)(((UInt64)timestampExtLast & 0xFFFFFFFF00000000UL) | Timestamp);
// if (Math.Abs(uncorrected - timestampExtLast) <= 0x80000000L)
// {
// TimestampExt = timestampExtLast = uncorrected;
// }
// else if (Math.Abs(uncorrected + 0x100000000L - timestampExtLast) <= 0x80000000L)
// {
// TimestampExt = timestampExtLast = uncorrected + 0x100000000L;
// }
// else if (Math.Abs(uncorrected - 0x100000000L - timestampExtLast) <= 0x80000000L)
// {
// TimestampExt = timestampExtLast = uncorrected - 0x100000000L;
// }
// else
// {
// TimestampExt = timestampExtLast = uncorrected;
// }
// }
//
// Flags = allOk ? OptoTelegramFlags.OK : OptoTelegramFlags.InvalidTelegram;
//
// return allOk;
// }
// -------- TIMESTAMP (seconds) --------
// bbbbbbbb unsigned 32 bit ASIC time stamp in 8192 ticks per second rolls over after 2^32
private const double TS_TICKS_PER_SEC = 8192.0;
private const double TS_RANGE = 4294967296.0 / TS_TICKS_PER_SEC; // 2^32 / 8192 = 524288 sec
// -------- VOLUME (liters) --------
// vvvvvv is unsigned 24-bit, 1 tick = 1/4 ml = 0.00025 L
private const double VOL_LITERS_PER_TICK = 0.00025; // liters per tick
private const double VOL_RANGE = 16777216.0 * VOL_LITERS_PER_TICK; // 2^24 * 0.00025 = 4194.304 L
// -------- VOLUME (liters) --------
private const double GAL_TO_LITER = 3.785411784;
public void UpdateFromSmart(
DiagnosticLedState4Data data,
int counter,
float refFlow,
ref double volumeRawExtLast,
ref double timestampExtLast)
{
DateTime = DateTime.Now;
Counter = counter;
RefFlow = refFlow;
FlowRaw = data.RawFlow;
VolumeRaw = data.RawVolume;
// ---- TIMESTAMP RAW (seconds, modulo TS_RANGE) ----
// If upstream conversion ever produced negative values, normalize them.
double ts = data.AsicTimestamp; // already in seconds, but wraps every TS_RANGE
ts = ts % TS_RANGE;
if (ts < 0) ts += TS_RANGE;
Timestamp = ts;
// ---------- VOLUME UNWRAP ----------
double v = VolumeRaw;
if (double.IsNaN(volumeRawExtLast))
{
VolumeRawExt = volumeRawExtLast = v;
}
else
{
// nearest-lap unwrap
//double k = Math.Round(volumeRawExtLast - v) / VOL_RANGE);
if (v < volumeRawExtLast)
{
VolumeRawExt = volumeRawExtLast = v + VOL_RANGE;
}
else
{
VolumeRawExt = volumeRawExtLast = v;
}
}
// ---------- TIMESTAMP UNWRAP (seconds) ----------
if (double.IsNaN(timestampExtLast))
{
TimestampExt = timestampExtLast = ts;
}
else
{
// robust unwrap: choose the smallest jump across the modulo boundary
double lastMod = timestampExtLast % TS_RANGE;
if (lastMod < 0) lastMod += TS_RANGE;
double delta = ts - lastMod;
if (delta < -TS_RANGE / 2.0) delta += TS_RANGE;
else if (delta > TS_RANGE / 2.0) delta -= TS_RANGE;
TimestampExt = timestampExtLast = timestampExtLast + delta;
}
}
/// <summary>
/// Alternative to UpdateFromString(...) when data are flushed
/// </summary>
public bool UpdateFromStringDummy(string telegram)
{
DateTime = DateTime.Now;
RefFlow = 0;
if ((telegram == null) || (telegram.Length < Length) ||
(telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') ||
(telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') ||
(telegram[40] != '\r') || (telegram[41] != '\n'))
{
Flags = OptoTelegramFlags.InvalidTelegram;
return false;
}
bool f7 = byte.TryParse(telegram.Substring(38, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out CheckSum);
byte calculatedCheckSum = 0;
for (int i = 0; i < Length - 4; i++)
{
calculatedCheckSum += (byte)telegram[i];
}
bool allOk = f7 && (calculatedCheckSum == CheckSum);
Flags = allOk ? OptoTelegramFlags.OK : OptoTelegramFlags.InvalidTelegram;
return allOk;
}
public void SetFlags(OptoTelegramFlags flags)
{
this.Flags = flags;
}
public string ToString(double scalingFactor, OptoTelegramRaw previous)
{
if (Flags == OptoTelegramFlags.SyncError)
{
return "Sychronization error";
}
else if (Flags == OptoTelegramFlags.InvalidTelegram)
{
return "Invalid telegram";
}
else /// if (flags == OptoTelegramFlags.OK / OptoTelegramFlags.OK_TestStart / OptoTelegramFlags.OK_TestEnd)
{
return string.Format("{0}:{1}:{2}.{3}\t{4} :\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}\t{12}\t{13}\t{14}\t{15}\t{16}\t{17}\t{18}\t{19}\t{20}\t{21}\t{22}",
DateTime.Hour.ToString("D2"),
DateTime.Minute.ToString("D2"),
DateTime.Second.ToString("D2"),
DateTime.Millisecond.ToString("D4"),
Counter,
(EmfRaw & 0x00FFFFFF).ToString("X6"),
MagneticFieldRaw.ToString("X4"),
FlowRaw.ToString("X4"),
VolumeRaw.ToString("X6"),
Impedance.ToString("X4"),
Timestamp.ToString("X8"),
CheckSum.ToString("X2"),
EMF().ToString("F4", culture),
MagneticField().ToString("F0", culture),
Flow(scalingFactor).ToString("F2", culture),
Volume(scalingFactor).ToString("F4", culture),
FlipTime().ToString("F0", culture),
TimestampDec().ToString("F4", culture),
(RefFlow * 1000).ToString("F2", culture),
VolumeDelta(scalingFactor, previous).ToString("F4", culture),
TimeDelta().ToString("F3", culture),
scalingFactor.ToString("F1", culture),
Label());
}
}
}
}

View File

@ -0,0 +1,25 @@
using System;
namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol
{
public sealed class IperlHatFrame
{
public byte Start { get; }
public byte Direction { get; }
public byte End { get; }
public byte Length { get; }
public byte[] CommandInformation { get; }
public byte[] Payload { get; }
public IperlHatFrame(byte start, byte direction, byte length, byte[] commandBytes, byte[] payload, byte end)
{
Start = start;
Direction = direction;
Length = length;
CommandInformation = commandBytes ?? Array.Empty<byte>();
Payload = payload ?? Array.Empty<byte>();
End = end;
}
}
}

View File

@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol
{
public sealed class IperlHatFrameBuilder
{
private byte _direction;
private readonly List<byte> _commandBytes = new List<byte>();
private readonly List<byte> _payload = new List<byte>();
public IperlHatFrameBuilder RequestResponse(bool enabled)
{
_direction = enabled ? TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Write : TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Read;
return this;
}
public IperlHatFrameBuilder AddCommand(ProtocolCommand command)
{
_commandBytes.Add((byte)command);
return this;
}
public IperlHatFrameBuilder AddSubCommand(ProtocolCommand subCommand)
{
if (_commandBytes.Count == 0 ||
_commandBytes[0] != (byte)ProtocolCommand.DeviceSpecific)
throw new InvalidOperationException(
"Sub-command is only valid for DeviceSpecific (0xFD) commands.");
_commandBytes.Add((byte)subCommand);
return this;
}
public IperlHatFrameBuilder AddSubCommand(ProtocolStatuses subCommand)
{
if (_commandBytes.Count == 0 ||
_commandBytes[0] != (byte)ProtocolCommand.SetState)
throw new InvalidOperationException(
"Sub-command is only valid for SetState (0xA1) commands.");
_commandBytes.Add((byte)subCommand);
return this;
}
public IperlHatFrameBuilder AddDeviceCommand(
ProtocolDeviceSubCommand subCommand)
{
_commandBytes.Add((byte)ProtocolCommand.DeviceSpecific);
_commandBytes.Add((byte)subCommand);
return this;
}
public IperlHatFrameBuilder SetVersionCommand()
{
_commandBytes.Add((byte)ProtocolCommand.Question);
_payload.AddRange(TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Version);
return this;
}
public IperlHatFrameBuilder AddPayload(byte[] payload)
{
if (payload != null)
_payload.AddRange(payload);
return this;
}
public IperlHatFrameBuilder AddPayload(DiagnosticLedState state)
{
_payload.Add((byte)state);
return this;
}
public IperlHatFrameBuilder AddPayload(byte payload)
{
_payload.Add(payload);
return this;
}
public IperlHatFrameBuilder AddDiagnosticLedState(DiagnosticLedState state)
{
RequestResponse(true);
AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState);
AddPayload((byte)state);
return this;
}
public IperlHatFrameBuilder AddNullTerminatedAscii(string text)
{
if (!string.IsNullOrEmpty(text))
_commandBytes.AddRange(
System.Text.Encoding.ASCII.GetBytes(text));
_commandBytes.Add(0x00);
return this;
}
public IperlHatFrame BuildFrame()
{
if (_commandBytes.Count == 0)
throw new InvalidOperationException("No command specified.");
byte length = (byte)(4 + _commandBytes.Count + _payload.Count); // 4 = START + dirrection + LEN + END
return new IperlHatFrame(
TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start,
_direction,
length,
_commandBytes.ToArray(),
_payload.ToArray(),
TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End);
}
public byte[] BuildBytes()
{
IperlHatFrame frame = BuildFrame();
if (frame.CommandInformation.Length > 0 && frame.CommandInformation[0] == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question)
{
var bytes = new List<byte>
{
frame.Start,
frame.Direction,
};
bytes.AddRange(frame.CommandInformation);
bytes.AddRange(frame.Payload);
bytes.Add(frame.End);
return bytes.ToArray();
}
else
{
var bytes = new List<byte>
{
frame.Start,
frame.Direction,
frame.Length,
};
bytes.AddRange(frame.CommandInformation);
bytes.AddRange(frame.Payload);
bytes.Add(frame.End);
return bytes.ToArray();
}
}
}
}

View File

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
namespace TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol
{
public sealed class IperlHatFrameParser
{
public IperlHatResponse Parse(byte[] data)
{
if (data == null)
throw new ArgumentNullException(nameof(data));
if (data.Length < 5)
throw new FormatException("Frame too short.");
if (data[0] != TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start)
{
//if version parse version
if (data[0] == TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question)
{
//Define Question answer
var prefix = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question };
var end = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End };
if (IsPrefixValid(data, prefix, end))
{
//whole payload may be like "vers: Harry T:B800, V:06.06.01, FW:190215, 7ECE, B1.6.01, HW:4, Serial:0"
prefix = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question };
byte[] payloadVersion = ExtractPayloadUsePrefix(data, prefix, end);
return new IperlHatResponse(TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Question, payloadVersion.Length > 0 ? TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.StatusOk : TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.StatusNok, payloadVersion);
}
}
throw new FormatException("Invalid START byte.");
}
if (data[1] != TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Read)
throw new FormatException("Frame is no Response.");
byte length = data[2];
if (length != data.Length)
throw new FormatException("Length mismatch.");
byte direction = data[1];
byte status = data[3];
var prefixCommand = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.Start,direction,length,status };
var endCommand = new List<byte>{ TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol.IperlHatProtocolConstants.End };
byte[] payload = ExtractPayloadUsePrefix(data,prefixCommand,endCommand);
return new IperlHatResponse(0x00, status, payload);
}
private static byte[] ExtractPayloadUsePrefix(byte[] data, List<byte> prefix, List<byte> end)
{
// payload exists only if frame longer than:
// START + DIRECTION + LEN + CTRL + END = 5 bytes
// OR VERSION_START + VERSION = 5 bytes
if (data.Length <= 5)
return Array.Empty<byte>();
//check prefix is equal
int prefixLength = prefix.Count;
byte[] commandPrefix = new byte[prefixLength];
Buffer.BlockCopy(data, 0, commandPrefix, 0, prefixLength);
if (StartsWithPrefix(end, commandPrefix))
{
return Array.Empty<byte>();
}
int payloadLength = data.Length - (prefix.Count + end.Count);
byte[] payload = new byte[payloadLength];
Buffer.BlockCopy(data, prefix.Count, payload, 0, payloadLength);
return payload;
}
private static bool IsPrefixValid(byte[] data, List<byte> prefix, List<byte> end)
{
int prefixLength = prefix.Count;
// payload exists only if frame longer than:
// OR VERSION_START + VERSION = 5 bytes - "?VERS" version implemented
if (data.Length <= prefixLength) // need be and on END
return false;
//check prefix is equal
byte[] commandPrefix = new byte[prefixLength];
Buffer.BlockCopy(data, 0, commandPrefix, 0, prefixLength);
if (StartsWithPrefix(end, commandPrefix))
{
return false;
}
return true;
}
private static bool StartsWithPrefix(List<byte> data, byte[] prefix)
{
if (data.Count < prefix.Length)
return false;
for (int i = 0; i < prefix.Length; i++)
{
if (data[i] != prefix[i])
return false;
}
return true;
}
private static byte[] ExtractVersionPayload(byte[] data)
{
// payload exists only if frame longer than:
// START + LEN + CTRL + STATUS + CHK_HI + CHK_LO = 6 bytes
if (data.Length <= 5)
return Array.Empty<byte>();
int payloadLength = data.Length - 4;
byte[] payload = new byte[payloadLength];
Buffer.BlockCopy(data, 5, payload, 0, payloadLength);
return payload;
}
}
}

Some files were not shown because too many files have changed in this diff Show More