diff --git a/TBF/LocalSettings.cs b/TBF/LocalSettings.cs
index d114867bb..38ec2374b 100644
--- a/TBF/LocalSettings.cs
+++ b/TBF/LocalSettings.cs
@@ -227,6 +227,12 @@ namespace TBF
///
public long OptoHeadsEnabled; /// Bit field with opto-head enabled states, used by iPerlCommunicationForm and S640CommForm
+ ///
+ /// Smart-meter reader selection used by SmartCommunicationForm and DataEntry.UNI.
+ /// OptoHeadsEnabled remains for the legacy iPerl and S640 dialogs.
+ ///
+ public SmartReaderSelectionSettings SmartReaderSelections;
+
/// Serial numbers
public string[] LastSNTexts;
[XmlIgnore]
diff --git a/TBF/Rig/DataEntry/Uni/RegisterReaderSelection.cs b/TBF/Rig/DataEntry/Uni/RegisterReaderSelection.cs
index 6099cc574..1ff536526 100644
--- a/TBF/Rig/DataEntry/Uni/RegisterReaderSelection.cs
+++ b/TBF/Rig/DataEntry/Uni/RegisterReaderSelection.cs
@@ -4,6 +4,8 @@ using System.Linq;
using log4net;
using Results.Entities;
using TBF.Rig.GenericDevices;
+using TBF.Rig.Sequences;
+using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
namespace TBF.Rig.DataEntry.Uni
{
@@ -23,21 +25,22 @@ namespace TBF.Rig.DataEntry.Uni
? new IRegReader[0]
: readers.ToArray();
long enabledHeads = Program.LocalSettings.OptoHeadsEnabled;
+ SmartReaderSelection.EnsureConfiguredReaders(Program.LocalSettings, ProcessData.SmartHeadsUni);
IRegReader[] selected = allSlots
- .Where(reader => IsSelectedForDataEntry(reader, waterMeters, enabledHeads))
+ .Where(reader => IsSelectedForDataEntry(reader, waterMeters, Program.LocalSettings, enabledHeads))
.ToArray();
string selectedPositions = string.Join(",", selected.Select(reader => reader.Position));
string skippedPositions = string.Join(",", allSlots
.Where(reader => reader != null &&
- !IsSelectedForDataEntry(reader, waterMeters, enabledHeads))
+ !IsSelectedForDataEntry(reader, waterMeters, Program.LocalSettings, enabledHeads))
.Select(reader => reader.Position));
log.DebugFormat(
- "DATA_ENTRY_READER_FILTER Operation={0}, OptoHeadsEnabled=0x{1:X12}, " +
+ "DATA_ENTRY_READER_FILTER Operation={0}, LegacyOptoHeadsEnabled=0x{1:X12}, " +
"Slots={2}, Readers={3}, Selected={4}, SelectedPositions=[{5}], " +
- "SkippedPositions=[{6}], SelectionRule=SmartMeterMaskOrPrecheckedWaterMeter",
+ "SkippedPositions=[{6}], SelectionRule=SmartReaderFamilySelectionOrPrecheckedWaterMeter",
operation,
enabledHeads,
allSlots.Length,
@@ -56,8 +59,8 @@ namespace TBF.Rig.DataEntry.Uni
reader.GetType().Name,
reader.Position,
reader.DebugLevel,
- IsSelectedForDataEntry(reader, waterMeters, enabledHeads),
- GetSelectionDetails(reader, waterMeters, enabledHeads));
+ IsSelectedForDataEntry(reader, waterMeters, Program.LocalSettings, enabledHeads),
+ GetSelectionDetails(reader, waterMeters, Program.LocalSettings, enabledHeads));
}
return selected;
@@ -67,6 +70,15 @@ namespace TBF.Rig.DataEntry.Uni
IRegReader reader,
IList waterMeters,
long enabledHeads)
+ {
+ return IsSelectedForDataEntry(reader, waterMeters, null, enabledHeads);
+ }
+
+ internal static bool IsSelectedForDataEntry(
+ IRegReader reader,
+ IList waterMeters,
+ LocalSettings settings,
+ long enabledHeads)
{
if (reader == null)
return false;
@@ -87,6 +99,9 @@ namespace TBF.Rig.DataEntry.Uni
if (reader is ISmartMeterReader)
{
+ if (settings != null && settings.SmartReaderSelections != null)
+ return SmartReaderSelection.IsEnabled(settings, reader);
+
int position0 = reader.Position - 1;
return position0 >= 0 && position0 < 63 &&
(enabledHeads & (1L << position0)) != 0;
@@ -115,6 +130,7 @@ namespace TBF.Rig.DataEntry.Uni
private static string GetSelectionDetails(
IRegReader reader,
IList waterMeters,
+ LocalSettings settings,
long enabledHeads)
{
#if IPERL
@@ -136,6 +152,15 @@ namespace TBF.Rig.DataEntry.Uni
#endif
if (reader is ISmartMeterReader)
{
+ if (settings != null && settings.SmartReaderSelections != null)
+ {
+ return string.Format(
+ ", SelectionSource=SmartReaderFamily, Family={0}, ReaderKey={1}, Enabled={2}",
+ SmartReaderSelection.GetFamilyKey(reader),
+ SmartReaderSelection.GetReaderKey(reader),
+ SmartReaderSelection.IsEnabled(settings, reader));
+ }
+
int position0 = reader.Position - 1;
bool maskBit = position0 >= 0 && position0 < 63 &&
(enabledHeads & (1L << position0)) != 0;
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfg.cs b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfg.cs
index de2a8172d..b8a6c78bc 100644
--- a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfg.cs
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfg.cs
@@ -37,7 +37,7 @@ namespace TBF.Rig.RegisterReaders.AllyReader
public IComponentCfgCtrl GetControl(IList cmpntEntities)
{
- return new Configs.ParamsProvider.ComponentCfgCtrl(this, null);
+ return new AllyReaderCfgCtrl();
}
public string ComponentName { get { return Name; } }
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.Designer.cs b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.Designer.cs
new file mode 100644
index 000000000..635400b0e
--- /dev/null
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.Designer.cs
@@ -0,0 +1,51 @@
+namespace TBF.Rig.RegisterReaders.AllyReader
+{
+ partial class AllyReaderCfgCtrl
+ {
+ private System.ComponentModel.IContainer components = null;
+ protected override void Dispose(bool disposing) { if (disposing && components != null) components.Dispose(); base.Dispose(disposing); }
+ private void InitializeComponent()
+ {
+ tabControl1 = new System.Windows.Forms.TabControl(); tabPage1 = new System.Windows.Forms.TabPage(); tabPage2 = new System.Windows.Forms.TabPage();
+ classNameLabel = new System.Windows.Forms.Label(); nameLabel = new System.Windows.Forms.Label(); nameTextBox = new System.Windows.Forms.TextBox();
+ muxBoardNrLabel = new System.Windows.Forms.Label(); muxBoardNrTextBox = new System.Windows.Forms.TextBox(); label3 = new System.Windows.Forms.Label();
+ groupLabel = new System.Windows.Forms.Label(); groupTextBox = new System.Windows.Forms.TextBox(); label4 = new System.Windows.Forms.Label();
+ optoDataGroupBox = new System.Windows.Forms.GroupBox(); radioButton1 = new System.Windows.Forms.RadioButton(); radioButton2 = new System.Windows.Forms.RadioButton();
+ ipAddressLabel = new System.Windows.Forms.Label(); ipAddressTextBox = new System.Windows.Forms.TextBox(); tcpipPortLabel = new System.Windows.Forms.Label(); tcpipPortTextBox = new System.Windows.Forms.TextBox(); optoSerialPortLabel = new System.Windows.Forms.Label(); optoSerialPortTextBox = new System.Windows.Forms.TextBox();
+ groupBox1 = new System.Windows.Forms.GroupBox(); label1 = new System.Windows.Forms.Label(); comboBoxCommunicationInterface = new System.Windows.Forms.ComboBox(); rfidSerialPortNrLabel = new System.Windows.Forms.Label(); rfidPortNrTextBox = new System.Windows.Forms.TextBox();
+ groupBox2 = new System.Windows.Forms.GroupBox(); label2 = new System.Windows.Forms.Label(); headPortNrTextBox = new System.Windows.Forms.TextBox();
+ tabControl1.SuspendLayout(); tabPage1.SuspendLayout(); optoDataGroupBox.SuspendLayout(); groupBox1.SuspendLayout(); groupBox2.SuspendLayout(); SuspendLayout();
+ tabControl1.Controls.Add(tabPage1); tabControl1.Controls.Add(tabPage2); tabControl1.Location = new System.Drawing.Point(3,3); tabControl1.Name="tabControl1"; tabControl1.SelectedIndex=0; tabControl1.Size=new System.Drawing.Size(611,432);
+ tabPage1.Controls.Add(groupBox2); tabPage1.Controls.Add(label4); tabPage1.Controls.Add(label3); tabPage1.Controls.Add(groupBox1); tabPage1.Controls.Add(optoDataGroupBox); tabPage1.Controls.Add(groupTextBox); tabPage1.Controls.Add(groupLabel); tabPage1.Controls.Add(muxBoardNrTextBox); tabPage1.Controls.Add(muxBoardNrLabel); tabPage1.Controls.Add(nameTextBox); tabPage1.Controls.Add(nameLabel); tabPage1.Controls.Add(classNameLabel); tabPage1.Location=new System.Drawing.Point(4,25); tabPage1.Name="tabPage1"; tabPage1.Padding=new System.Windows.Forms.Padding(3); tabPage1.Size=new System.Drawing.Size(603,403); tabPage1.Text="Config"; tabPage1.UseVisualStyleBackColor=true;
+ classNameLabel.AutoSize=true; classNameLabel.Location=new System.Drawing.Point(149,11); classNameLabel.Name="classNameLabel"; classNameLabel.Text="ClassName";
+ nameLabel.AutoSize=true; nameLabel.Location=new System.Drawing.Point(6,44); nameLabel.Name="nameLabel"; nameLabel.Text="Name";
+ nameTextBox.Enabled=false; nameTextBox.Location=new System.Drawing.Point(153,40); nameTextBox.Name="nameTextBox"; nameTextBox.Size=new System.Drawing.Size(160,22);
+ muxBoardNrLabel.AutoSize=true; muxBoardNrLabel.Location=new System.Drawing.Point(6,72); muxBoardNrLabel.Name="muxBoardNrLabel"; muxBoardNrLabel.Text="Group 1 (mux. board)";
+ muxBoardNrTextBox.Enabled=false; muxBoardNrTextBox.Location=new System.Drawing.Point(153,69); muxBoardNrTextBox.Name="muxBoardNrTextBox"; muxBoardNrTextBox.Size=new System.Drawing.Size(44,22);
+ label3.AutoSize=true; label3.Location=new System.Drawing.Point(208,72); label3.Name="label3"; label3.Text="1 .. 4";
+ groupLabel.AutoSize=true; groupLabel.Location=new System.Drawing.Point(6,101); groupLabel.Name="groupLabel"; groupLabel.Text="Group 2";
+ groupTextBox.Enabled=false; groupTextBox.Location=new System.Drawing.Point(153,97); groupTextBox.Name="groupTextBox"; groupTextBox.Size=new System.Drawing.Size(44,22);
+ label4.AutoSize=true; label4.Location=new System.Drawing.Point(208,101); label4.Name="label4"; label4.Text="1 .. 10";
+ optoDataGroupBox.Controls.Add(tcpipPortLabel); optoDataGroupBox.Controls.Add(tcpipPortTextBox); optoDataGroupBox.Controls.Add(ipAddressLabel); optoDataGroupBox.Controls.Add(ipAddressTextBox); optoDataGroupBox.Controls.Add(radioButton1); optoDataGroupBox.Controls.Add(radioButton2); optoDataGroupBox.Controls.Add(optoSerialPortLabel); optoDataGroupBox.Controls.Add(optoSerialPortTextBox); optoDataGroupBox.Location=new System.Drawing.Point(10,131); optoDataGroupBox.Name="optoDataGroupBox"; optoDataGroupBox.Size=new System.Drawing.Size(552,119); optoDataGroupBox.Text="Opto-data";
+ radioButton1.AutoSize=true; radioButton1.Checked=true; radioButton1.Enabled=false; radioButton1.Location=new System.Drawing.Point(29,23); radioButton1.Name="radioButton1"; radioButton1.Text="Use TCP/IP";
+ radioButton2.AutoSize=true; radioButton2.Enabled=false; radioButton2.Location=new System.Drawing.Point(312,23); radioButton2.Name="radioButton2"; radioButton2.Text="Use serial port";
+ ipAddressLabel.AutoSize=true; ipAddressLabel.Location=new System.Drawing.Point(41,59); ipAddressLabel.Name="ipAddressLabel"; ipAddressLabel.Text="IP address. :";
+ ipAddressTextBox.Enabled=false; ipAddressTextBox.Location=new System.Drawing.Point(143,55); ipAddressTextBox.Name="ipAddressTextBox"; ipAddressTextBox.Size=new System.Drawing.Size(129,22);
+ tcpipPortLabel.AutoSize=true; tcpipPortLabel.Location=new System.Drawing.Point(41,87); tcpipPortLabel.Name="tcpipPortLabel"; tcpipPortLabel.Text="Port nr.:";
+ tcpipPortTextBox.Enabled=false; tcpipPortTextBox.Location=new System.Drawing.Point(143,84); tcpipPortTextBox.Name="tcpipPortTextBox"; tcpipPortTextBox.Size=new System.Drawing.Size(51,22);
+ optoSerialPortLabel.AutoSize=true; optoSerialPortLabel.Location=new System.Drawing.Point(321,55); optoSerialPortLabel.Name="optoSerialPortLabel"; optoSerialPortLabel.Text="Serial port nr.:";
+ optoSerialPortTextBox.Enabled=false; optoSerialPortTextBox.Location=new System.Drawing.Point(439,52); optoSerialPortTextBox.Name="optoSerialPortTextBox"; optoSerialPortTextBox.Size=new System.Drawing.Size(44,22);
+ groupBox1.Controls.Add(comboBoxCommunicationInterface); groupBox1.Controls.Add(label1); groupBox1.Controls.Add(rfidPortNrTextBox); groupBox1.Controls.Add(rfidSerialPortNrLabel); groupBox1.Location=new System.Drawing.Point(10,259); groupBox1.Name="groupBox1"; groupBox1.Size=new System.Drawing.Size(552,68); groupBox1.Text="RFID / NFC communication (in case mux. board is not used)";
+ label1.AutoSize=true; label1.Location=new System.Drawing.Point(41,30); label1.Name="label1"; label1.Text="Communication Interface";
+ comboBoxCommunicationInterface.Enabled=false; comboBoxCommunicationInterface.FormattingEnabled=true; comboBoxCommunicationInterface.Location=new System.Drawing.Point(201,27); comboBoxCommunicationInterface.Name="comboBoxCommunicationInterface"; comboBoxCommunicationInterface.Size=new System.Drawing.Size(71,24);
+ rfidSerialPortNrLabel.AutoSize=true; rfidSerialPortNrLabel.Location=new System.Drawing.Point(321,30); rfidSerialPortNrLabel.Name="rfidSerialPortNrLabel"; rfidSerialPortNrLabel.Text="Serial port nr.:";
+ rfidPortNrTextBox.Enabled=false; rfidPortNrTextBox.Location=new System.Drawing.Point(439,26); rfidPortNrTextBox.Name="rfidPortNrTextBox"; rfidPortNrTextBox.Size=new System.Drawing.Size(44,22);
+ groupBox2.Controls.Add(headPortNrTextBox); groupBox2.Controls.Add(label2); groupBox2.Location=new System.Drawing.Point(10,335); groupBox2.Name="groupBox2"; groupBox2.Size=new System.Drawing.Size(552,50); groupBox2.Text="Head Communication";
+ label2.AutoSize=true; label2.Location=new System.Drawing.Point(321,18); label2.Name="label2"; label2.Text="Serial port nr.:";
+ headPortNrTextBox.Enabled=false; headPortNrTextBox.Location=new System.Drawing.Point(439,15); headPortNrTextBox.Name="headPortNrTextBox"; headPortNrTextBox.Size=new System.Drawing.Size(44,22);
+ tabPage2.Location=new System.Drawing.Point(4,25); tabPage2.Name="tabPage2"; tabPage2.Padding=new System.Windows.Forms.Padding(3); tabPage2.Size=new System.Drawing.Size(603,403); tabPage2.Text="Test"; tabPage2.UseVisualStyleBackColor=true;
+ AutoScaleDimensions=new System.Drawing.SizeF(8F,16F); AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font; Controls.Add(tabControl1); Margin=new System.Windows.Forms.Padding(4); Name="AllyReaderCfgCtrl"; Size=new System.Drawing.Size(617,438); tabControl1.ResumeLayout(false); tabPage1.ResumeLayout(false); tabPage1.PerformLayout(); optoDataGroupBox.ResumeLayout(false); optoDataGroupBox.PerformLayout(); groupBox1.ResumeLayout(false); groupBox1.PerformLayout(); groupBox2.ResumeLayout(false); groupBox2.PerformLayout(); ResumeLayout(false);
+ }
+ private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.Label classNameLabel,nameLabel,muxBoardNrLabel,groupLabel,label1,label2,label3,label4,ipAddressLabel,tcpipPortLabel,optoSerialPortLabel,rfidSerialPortNrLabel; private System.Windows.Forms.TextBox nameTextBox,muxBoardNrTextBox,groupTextBox,ipAddressTextBox,tcpipPortTextBox,optoSerialPortTextBox,rfidPortNrTextBox,headPortNrTextBox; private System.Windows.Forms.GroupBox optoDataGroupBox,groupBox1,groupBox2; private System.Windows.Forms.RadioButton radioButton1,radioButton2; private System.Windows.Forms.ComboBox comboBoxCommunicationInterface;
+ }
+}
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.cs b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.cs
new file mode 100644
index 000000000..0c586b416
--- /dev/null
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Globalization;
+using System.Windows.Forms;
+using Common;
+using TBF.Rig.Generic;
+
+namespace TBF.Rig.RegisterReaders.AllyReader
+{
+ public partial class AllyReaderCfgCtrl : UserControl, IComponentCfgCtrl
+ {
+ private AllyReaderCfg config;
+ private readonly AllyReaderManualTestCtrl manualTestControl;
+
+ public AllyReaderCfgCtrl()
+ {
+ InitializeComponent();
+ manualTestControl = new AllyReaderManualTestCtrl { Dock = DockStyle.Fill };
+ tabPage2.Controls.Add(manualTestControl);
+ tabPage1.Text = "Settings";
+ tabPage2.Text = "Manual test";
+ groupBox1.Text = "Touch-Read communication";
+ groupBox2.Text = "Touch-Read settings";
+ muxBoardNrLabel.Text = "Configured meter size";
+ groupLabel.Text = "Meter pulses/liter";
+ label3.Text = label4.Text = string.Empty;
+ ipAddressLabel.Text = "TCP/IP";
+ ipAddressTextBox.Text = "Not supported by ALLY";
+ tcpipPortLabel.Text = "Opto baud rate:";
+ label2.Text = "Baud rate:";
+ comboBoxCommunicationInterface.Items.Clear();
+ comboBoxCommunicationInterface.Items.Add("Touch-Read");
+ comboBoxCommunicationInterface.SelectedIndex = 0;
+ radioButton1.Checked = false;
+ radioButton2.Checked = true;
+ }
+
+ public IComponentCfg Config { get { return config; } set { config = value as AllyReaderCfg; Redraw(); manualTestControl.Config = config; } }
+ public bool ShowMore { get { return false; } }
+ public void Unlock() { nameTextBox.Enabled = muxBoardNrTextBox.Enabled = groupTextBox.Enabled = optoSerialPortTextBox.Enabled = tcpipPortTextBox.Enabled = rfidPortNrTextBox.Enabled = headPortNrTextBox.Enabled = true; }
+
+ public CfgUpdateFlags VerifyCfg(ref string message)
+ {
+ int n; double pulses; AllyMeterSize size;
+ if (config == null || string.IsNullOrWhiteSpace(nameTextBox.Text)) return Invalid(ref message, "Name");
+ if (!Enum.TryParse(muxBoardNrTextBox.Text, out size)) return Invalid(ref message, "Configured meter size");
+ if (!double.TryParse(groupTextBox.Text, NumberStyles.Float, CultureInfo.InvariantCulture, out pulses) || pulses <= 0) return Invalid(ref message, "Meter pulses/liter");
+ if (!int.TryParse(optoSerialPortTextBox.Text, out n) || n <= 0) return Invalid(ref message, "Optical serial port nr.");
+ if (!int.TryParse(tcpipPortTextBox.Text, out n) || n <= 0) return Invalid(ref message, "Optical baud rate");
+ if (!int.TryParse(rfidPortNrTextBox.Text, out n) || n <= 0) return Invalid(ref message, "Touch-Read serial port nr.");
+ if (!int.TryParse(headPortNrTextBox.Text, out n) || n <= 0) return Invalid(ref message, "Touch-Read baud rate");
+ return CfgUpdateFlags.None;
+ }
+ public CfgUpdateFlags UpdateCfg()
+ {
+ if (config == null) return CfgUpdateFlags.Error;
+ config.Name = nameTextBox.Text;
+ config.ConfiguredMeterSize = (AllyMeterSize)Enum.Parse(typeof(AllyMeterSize), muxBoardNrTextBox.Text);
+ config.MeterPulsesPerLiter = double.Parse(groupTextBox.Text, CultureInfo.InvariantCulture);
+ config.OptoComPortNr = int.Parse(optoSerialPortTextBox.Text); config.OptoBaudRate = int.Parse(tcpipPortTextBox.Text);
+ config.CommandComPortNr = int.Parse(rfidPortNrTextBox.Text); config.CommandBaudRate = int.Parse(headPortNrTextBox.Text);
+ return CfgUpdateFlags.RestartRqrd;
+ }
+ public void Closing() { manualTestControl.StopOpticalStream(); }
+ private void Redraw()
+ {
+ if (config == null) return;
+ classNameLabel.Text = config.Factory.ClassName; nameTextBox.Text = config.Name;
+ muxBoardNrTextBox.Text = config.ConfiguredMeterSize.ToString(); groupTextBox.Text = config.MeterPulsesPerLiter.ToString(CultureInfo.InvariantCulture);
+ optoSerialPortTextBox.Text = config.OptoComPortNr.ToString(); tcpipPortTextBox.Text = config.OptoBaudRate.ToString();
+ rfidPortNrTextBox.Text = config.CommandComPortNr.ToString(); headPortNrTextBox.Text = config.CommandBaudRate.ToString();
+ }
+ private static CfgUpdateFlags Invalid(ref string message, string text) { message += Environment.NewLine + "'" + text + "' is not valid"; return CfgUpdateFlags.Error; }
+ }
+}
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.resx b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.resx
new file mode 100644
index 000000000..13913bdda
--- /dev/null
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderCfgCtrl.resx
@@ -0,0 +1,7 @@
+
+
+ text/microsoft-resx
+ 2.0
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.Designer.cs b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.Designer.cs
new file mode 100644
index 000000000..106bc24a8
--- /dev/null
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.Designer.cs
@@ -0,0 +1,22 @@
+namespace TBF.Rig.RegisterReaders.AllyReader
+{
+ partial class AllyReaderManualTestCtrl
+ {
+ private System.ComponentModel.IContainer components = null;
+ protected override void Dispose(bool disposing) { if(disposing && components != null) components.Dispose(); base.Dispose(disposing); }
+ private void InitializeComponent()
+ {
+ optoTestGroupBox=new System.Windows.Forms.GroupBox(); optoListBox=new System.Windows.Forms.ListBox(); RfidTestGroupBox=new System.Windows.Forms.GroupBox(); rfidOutputListBox=new System.Windows.Forms.ListBox(); label2=new System.Windows.Forms.Label(); rfidCommandComboBox=new System.Windows.Forms.ComboBox(); commandTestButton=new System.Windows.Forms.Button();
+ optoTestGroupBox.SuspendLayout(); RfidTestGroupBox.SuspendLayout(); SuspendLayout();
+ optoTestGroupBox.Controls.Add(optoListBox); optoTestGroupBox.Location=new System.Drawing.Point(5,4); optoTestGroupBox.Name="optoTestGroupBox"; optoTestGroupBox.Size=new System.Drawing.Size(591,161); optoTestGroupBox.Text="Opto-data";
+ optoListBox.FormattingEnabled=true; optoListBox.ItemHeight=16; optoListBox.Location=new System.Drawing.Point(7,22); optoListBox.Name="optoListBox"; optoListBox.Size=new System.Drawing.Size(573,132);
+ RfidTestGroupBox.Controls.Add(rfidOutputListBox); RfidTestGroupBox.Controls.Add(label2); RfidTestGroupBox.Controls.Add(rfidCommandComboBox); RfidTestGroupBox.Controls.Add(commandTestButton); RfidTestGroupBox.Location=new System.Drawing.Point(5,171); RfidTestGroupBox.Name="RfidTestGroupBox"; RfidTestGroupBox.Size=new System.Drawing.Size(591,224); RfidTestGroupBox.Text="RFID / NFC data";
+ rfidOutputListBox.FormattingEnabled=true; rfidOutputListBox.ItemHeight=16; rfidOutputListBox.Location=new System.Drawing.Point(5,54); rfidOutputListBox.Name="rfidOutputListBox"; rfidOutputListBox.SelectionMode=System.Windows.Forms.SelectionMode.None; rfidOutputListBox.Size=new System.Drawing.Size(575,164);
+ label2.AutoSize=true; label2.Location=new System.Drawing.Point(2,25); label2.Name="label2"; label2.Text="Command";
+ rfidCommandComboBox.FormattingEnabled=true; rfidCommandComboBox.Location=new System.Drawing.Point(86,19); rfidCommandComboBox.Name="rfidCommandComboBox"; rfidCommandComboBox.Size=new System.Drawing.Size(341,24);
+ commandTestButton.Location=new System.Drawing.Point(449,19); commandTestButton.Name="commandTestButton"; commandTestButton.Size=new System.Drawing.Size(126,24); commandTestButton.Text="Send command"; commandTestButton.UseVisualStyleBackColor=true; commandTestButton.MouseClick += new System.Windows.Forms.MouseEventHandler(CommandTestButtonClick);
+ AutoScaleDimensions=new System.Drawing.SizeF(8F,16F); AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font; Controls.Add(optoTestGroupBox); Controls.Add(RfidTestGroupBox); Name="AllyReaderManualTestCtrl"; Size=new System.Drawing.Size(611,432); optoTestGroupBox.ResumeLayout(false); RfidTestGroupBox.ResumeLayout(false); RfidTestGroupBox.PerformLayout(); ResumeLayout(false);
+ }
+ private System.Windows.Forms.GroupBox optoTestGroupBox,RfidTestGroupBox; private System.Windows.Forms.ListBox optoListBox,rfidOutputListBox; private System.Windows.Forms.Label label2; private System.Windows.Forms.ComboBox rfidCommandComboBox; private System.Windows.Forms.Button commandTestButton;
+ }
+}
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.cs b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.cs
new file mode 100644
index 000000000..ac0123258
--- /dev/null
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Linq;
+using System.Windows.Forms;
+using TBF.Rig.Sequences;
+
+namespace TBF.Rig.RegisterReaders.AllyReader
+{
+ public partial class AllyReaderManualTestCtrl : UserControl
+ {
+ private const int CommandTimeoutMs = 5000;
+ private readonly Timer opticalPollTimer;
+ private AllyReaderCfg config;
+
+ public AllyReaderManualTestCtrl()
+ {
+ InitializeComponent();
+ rfidCommandComboBox.Items.AddRange(new object[] { "Read serial number", "Read version and type", "Set RFID mode", "Set NFC mode", "Read optical data", "Start optical stream", "Stop optical stream" });
+ rfidCommandComboBox.SelectedIndex = 0;
+ opticalPollTimer = new Timer { Interval = 250 };
+ opticalPollTimer.Tick += OpticalPollTimer_Tick;
+ }
+
+ public AllyReaderCfg Config { set { config = value; } }
+ public void StopOpticalStream() { opticalPollTimer.Stop(); AllyMeterReader r=FindReader(); if(r!=null) try { r.StopDataStreamProcessing(); } catch(Exception e) { AddOutput(e.Message); } }
+ private void CommandTestButtonClick(object sender, MouseEventArgs e)
+ {
+ AllyMeterReader r = FindReader(); string cmd = rfidCommandComboBox.SelectedItem as string;
+ if (r == null) { AddOutput("Configured ALLY reader is not initialized on this bench."); return; }
+ try {
+ if (cmd == "Start optical stream") { r.StartDataStreamProcessing(); opticalPollTimer.Start(); AddOutput("Started"); }
+ else if (cmd == "Stop optical stream") { StopOpticalStream(); AddOutput("Stopped"); }
+ else if (cmd == "Read optical data") AddOpto(r.ReadOptoData());
+ else if (cmd == "Read serial number") AddOutput(r.ReadSerialNumber(CommandTimeoutMs));
+ else if (cmd == "Read version and type") AddOutput(r.ReadVersionAndType(CommandTimeoutMs).ToString());
+ else if (cmd == "Set RFID mode") { r.SetRfidInterface(); AddOutput("OK"); }
+ else if (cmd == "Set NFC mode") { r.SetNfcInterface(); AddOutput("OK"); }
+ } catch(Exception x) { AddOutput("Error: " + x.Message); }
+ }
+ private void OpticalPollTimer_Tick(object sender, EventArgs e) { AllyMeterReader r=FindReader(); if(r==null) { opticalPollTimer.Stop(); return; } try { AddOpto(r.ReadOptoData()); } catch(Exception x) { AddOpto("Error: " + x.Message); } }
+ private AllyMeterReader FindReader() { return config == null || ProcessData.SmartHeadsUni == null ? null : ProcessData.SmartHeadsUni.OfType().FirstOrDefault(x => x.Name == config.Name); }
+ private void AddOpto(string text) { if(!string.IsNullOrEmpty(text)) optoListBox.Items.Insert(0,text); }
+ private void AddOutput(string text) { rfidOutputListBox.Items.Insert(0,text ?? string.Empty); }
+ }
+}
diff --git a/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.resx b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.resx
new file mode 100644
index 000000000..b7056c456
--- /dev/null
+++ b/TBF/Rig/RegisterReaders/AllyReader/AllyReaderManualTestCtrl.resx
@@ -0,0 +1 @@
+text/microsoft-resx2.0System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
diff --git a/TBF/Rig/StateMachine.cs b/TBF/Rig/StateMachine.cs
index 685b42a8c..5dd21fab0 100644
--- a/TBF/Rig/StateMachine.cs
+++ b/TBF/Rig/StateMachine.cs
@@ -15,6 +15,7 @@ using TBF.Rig.Sequences;
using Dirichlet.Numerics;
using TBF.Resources;
using TBF.Rig.RegisterReaders.iPerlReaderUNI;
+using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
namespace TBF.Rig
@@ -313,6 +314,11 @@ namespace TBF.Rig
cmpnt.StartChangeHandler(); /// Start handling parameter change events
}
+ // Keep the persisted manual/DataEntry selection aligned with the
+ // actual smart readers configured on this bench. This does not
+ // create placeholder positions for other reader families.
+ SmartReaderSelection.EnsureConfiguredReaders(Program.LocalSettings, ProcessData.SmartHeadsUni);
+
/// Pre-initialize the control board (= buffer the arguments ctrlBrdComponent, tankCapacities)
if (ControlBoardMain == null)
{
diff --git a/TBF/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationForm.cs b/TBF/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationForm.cs
index 1130ce621..b29b3f795 100644
--- a/TBF/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationForm.cs
+++ b/TBF/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationForm.cs
@@ -681,13 +681,14 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
log.Warn("SmartCommunicationForm loaded before LocalSettings were initialized; using default window and checkbox state.");
Left = 150;
Top = 150;
- SetCheckBoxStates(0);
+ SetCheckBoxStates(SmartReaderSelection.GetMask(null, iperlHeads));
}
else
{
Left = (ls.iPerlCommunicationsFormLeft != 0) ? ls.iPerlCommunicationsFormLeft : 150;
Top = (ls.iPerlCommunicationsFormTop != 0) ? ls.iPerlCommunicationsFormTop : 150;
- SetCheckBoxStates(ls.OptoHeadsEnabled);
+ SmartReaderSelection.EnsureConfiguredReaders(ls, ProcessData.SmartHeadsUni);
+ SetCheckBoxStates(SmartReaderSelection.GetMask(ls, iperlHeads));
}
if (!checkBoxesEditMode)
@@ -876,12 +877,30 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
private void saveButton_Click(object sender, EventArgs e)
{
- Program.LocalSettings.OptoHeadsEnabled = GetCheckBoxStates();
- Program.LocalSettings.Save();
+ SaveCurrentFamilySelection();
DialogResult = DialogResult.OK;
Close();
}
+ private void SaveCurrentFamilySelection()
+ {
+ if (Program.LocalSettings == null)
+ return;
+
+ long checkboxStates = GetCheckBoxStates();
+ SmartReaderSelection.SetMask(Program.LocalSettings, iperlHeads, checkboxStates);
+
+ // The dedicated legacy iPerl/S640 dialogs still consume this
+ // bitmask. Do not overwrite it while editing another family.
+ if (iperlHeads != null && iperlHeads.Count > 0 &&
+ SmartReaderSelection.GetFamilyKey(iperlHeads[0]) == "iperl")
+ {
+ Program.LocalSettings.OptoHeadsEnabled = checkboxStates;
+ }
+
+ Program.LocalSettings.Save();
+ }
+
#endregion
private void SmartCommunicationForm_FormClosing(object sender, FormClosingEventArgs e)
@@ -902,16 +921,21 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
long checkboxStates = GetCheckBoxStates();
if (Program.LocalSettings.iPerlCommunicationsFormLeft != Location.X ||
- Program.LocalSettings.iPerlCommunicationsFormTop != Location.Y ||
- Program.LocalSettings.OptoHeadsEnabled != checkboxStates)
+ Program.LocalSettings.iPerlCommunicationsFormTop != Location.Y)
{
/// Update local settings
Program.LocalSettings.iPerlCommunicationsFormLeft = Location.X;
Program.LocalSettings.iPerlCommunicationsFormTop = Location.Y;
- Program.LocalSettings.OptoHeadsEnabled = checkboxStates;
- Program.LocalSettings.Save();
}
+ SmartReaderSelection.SetMask(Program.LocalSettings, iperlHeads, checkboxStates);
+ if (iperlHeads != null && iperlHeads.Count > 0 &&
+ SmartReaderSelection.GetFamilyKey(iperlHeads[0]) == "iperl")
+ {
+ Program.LocalSettings.OptoHeadsEnabled = checkboxStates;
+ }
+ Program.LocalSettings.Save();
+
formCompleted = true;
DialogResult = DialogResult.OK;
@@ -924,6 +948,7 @@ namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
if (initializingMeterTypeItems) return;
ComboBox senderCombo = sender as ComboBox;
if (senderCombo == null) return;
+ SaveCurrentFamilySelection();
SelectedTypeReader = senderCombo.SelectedItem?.ToString();
UpdateHeads();
SmartCommunicationForm_Load(this, EventArgs.Empty);
diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj
index 34a0a1824..693750689 100644
--- a/TBF/TBF.csproj
+++ b/TBF/TBF.csproj
@@ -1633,6 +1633,18 @@
+
+ UserControl
+
+
+ AllyReaderCfgCtrl.cs
+
+
+ UserControl
+
+
+ AllyReaderManualTestCtrl.cs
+
@@ -2571,6 +2583,7 @@
Form
+
SmartCommunicationForm.cs
@@ -2821,6 +2834,7 @@
+
@@ -3858,6 +3872,12 @@
+
+ AllyReaderCfgCtrl.cs
+
+
+ AllyReaderManualTestCtrl.cs
+
IPerlUniCfgCtrl.cs
diff --git a/TBFTests/Rig/DataEntry/Uni/RegisterReaderSelectionTests.cs b/TBFTests/Rig/DataEntry/Uni/RegisterReaderSelectionTests.cs
index 7f272bcec..cd9207b98 100644
--- a/TBFTests/Rig/DataEntry/Uni/RegisterReaderSelectionTests.cs
+++ b/TBFTests/Rig/DataEntry/Uni/RegisterReaderSelectionTests.cs
@@ -2,8 +2,10 @@ using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Results.Entities;
+using TBF;
using TBF.Rig.DataEntry.Uni;
using TBF.Rig.GenericDevices;
+using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication;
namespace TBFTests.Rig.DataEntry.Uni
{
@@ -83,12 +85,42 @@ namespace TBFTests.Rig.DataEntry.Uni
Assert.IsFalse(selected);
}
- private static Mock CreateReader(int position, bool smart = false)
+ [TestMethod]
+ public void SmartReader_PerFamilySelection_IsUsedInsteadOfLegacyPositionMask()
+ {
+ var reader = CreateReader(1, true, "iPerl01");
+ var settings = new LocalSettings
+ {
+ SmartReaderSelections = new SmartReaderSelectionSettings
+ {
+ LegacyOptoHeadsEnabledMigrated = true,
+ Families = new List
+ {
+ new SmartReaderFamilySelection
+ {
+ FamilyKey = "iperl",
+ Readers = new List
+ {
+ new SmartReaderSelectionItem { ReaderKey = "iPerl01", Enabled = false }
+ }
+ }
+ }
+ }
+ };
+
+ bool selected = RegisterReaderSelection.IsSelectedForDataEntry(
+ reader.Object, null, settings, long.MaxValue);
+
+ Assert.IsFalse(selected);
+ }
+
+ private static Mock CreateReader(int position, bool smart = false, string name = null)
{
var reader = new Mock();
if (smart)
reader.As();
reader.SetupGet(item => item.Position).Returns(position);
+ reader.SetupGet(item => item.Name).Returns(name);
return reader;
}
}
diff --git a/TBFTests/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationFormTests.cs b/TBFTests/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationFormTests.cs
index 60329898e..e40e682cf 100644
--- a/TBFTests/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationFormTests.cs
+++ b/TBFTests/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationFormTests.cs
@@ -4,6 +4,8 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using TBF;
using TBF.Rig.RegisterReaders.AllyReader;
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
using TBF.Rig.Sequences;
@@ -124,6 +126,39 @@ namespace TBFTests.Rig.Uni.SharedDialogs.SmartMetersCommunication
});
}
+ [TestMethod]
+ public void SelectionSettings_MigratesLegacyMaskToConfiguredIPerlFamily()
+ {
+ var first = new Mock();
+ first.SetupGet(reader => reader.Name).Returns("iPerl01");
+ first.SetupGet(reader => reader.Position).Returns(1);
+ var second = new Mock();
+ second.SetupGet(reader => reader.Name).Returns("iPerl02");
+ second.SetupGet(reader => reader.Position).Returns(2);
+ var settings = new LocalSettings { OptoHeadsEnabled = 1L << 1 };
+
+ SmartReaderSelection.EnsureConfiguredReaders(
+ settings, new ISmartReader[] { first.Object, second.Object });
+
+ SmartReaderFamilySelection family = settings.SmartReaderSelections.Families.Single();
+ Assert.AreEqual("iperl", family.FamilyKey);
+ Assert.IsFalse(family.Readers.Single(item => item.ReaderKey == "iPerl01").Enabled);
+ Assert.IsTrue(family.Readers.Single(item => item.ReaderKey == "iPerl02").Enabled);
+ }
+
+ [TestMethod]
+ public void SelectionSettings_MigratesLegacyMaskToFirstFamilyWhenIPerlIsNotConfigured()
+ {
+ AllyMeterReader ally = CreateAllyReader();
+ var settings = new LocalSettings { OptoHeadsEnabled = 1L };
+
+ SmartReaderSelection.EnsureConfiguredReaders(settings, new ISmartReader[] { ally });
+
+ SmartReaderFamilySelection family = settings.SmartReaderSelections.Families.Single();
+ Assert.AreEqual("ally", family.FamilyKey);
+ Assert.IsTrue(family.Readers.Single().Enabled);
+ }
+
private static AllyMeterReader CreateAllyReader()
{
return new AllyMeterReader(new AllyReaderCfg(new TBF.Rig.RegisterReaders.AllyReader.Factory()));