Add (develop) new component ConductivityMeter, because we have papouch AD4RS converter (4-20mA to modbus) - first correct version for testing

This commit is contained in:
Marek Frniak 2026-07-01 15:57:53 +02:00
parent 88903f3dac
commit 7867044c0a
11 changed files with 1565 additions and 0 deletions

View File

@ -0,0 +1,238 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using log4net;
using Common;
using TBF.Rig.Generic;
namespace TBF.Rig.Modbus.ConductivityMeter
{
public class ConductivityMeter : ComponentBase, IDevice
{
private static readonly ILog log = LogManager.GetLogger(typeof(ConductivityMeter));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
readonly ConductivityMeterCfg cfg;
Common.Modbus modbus;
int ticketNumber;
ushort[] rawRegs;
DateTime lastUpdate;
double receivedCond;
double receivedmA;
bool msrmntAvailable;
byte[] lastTelegram;
public double MeasuredVal { get { return receivedCond; } }
public double MeasuredmA { get { return receivedmA; } }
public bool MsrmntAvailable { get { return msrmntAvailable; } }
public double MsrdValLimLo { get { return cfg.MsrdValLimLo; } }
public double MsrdValLimHi { get { return cfg.MsrdValLimHi; } }
public string MsrdUnit { get { return cfg.MsrdUnit.ToString(); } }
public string MsrdFormat { get { return cfg.MsrdFormat; } }
public ConductivityMeterDiagnostics Diagnostics { get; private set; }
public ConductivityMeter()
{
Diagnostics = new ConductivityMeterDiagnostics();
}
public ConductivityMeter(IComponentCfg cfg, IList<IComponent> components)
: base(cfg)
{
this.cfg = cfg as ConductivityMeterCfg;
ticketNumber = -1;
Diagnostics = new ConductivityMeterDiagnostics();
}
public override void Initialize()
{
int regCount = Math.Max(1, (int)cfg.RegisterCount);
rawRegs = new ushort[regCount];
if (DebugLevel == DebugMode.Normal)
{
modbus = TbfComponents.FindComponent(cfg.ParentName) as Common.Modbus;
if (modbus == null) throw new Exception("Cannot find " + Name + " parent");
modbus.ComponentNames[cfg.ModbusAddress] = Name;
if (cfg.EnablePolling)
ticketNumber = modbus.RegisterForPolling();
log.FatalFormat("{0} initialized: {1}", Name, this);
}
else
{
log.FatalFormat("{0} simulated: {1}", Name, this);
}
}
public void RunDeviceBefore()
{
if (DebugLevel != DebugMode.Normal)
{
msrmntAvailable = true;
receivedmA = 12.0;
receivedCond = ConvertMilliAmpsToConductivity(receivedmA);
return;
}
var queue = modbus.ReceivedTelegrams[cfg.ModbusAddress];
if (queue.Count > 0)
{
lastTelegram = queue.Dequeue();
ParseTelegram(lastTelegram);
}
msrmntAvailable = (DateTime.Now - lastUpdate).TotalMilliseconds <= cfg.FreshnessMs;
if (!msrmntAvailable) return;
int ch = cfg.Channel;
if (ch < 0 || ch >= rawRegs.Length)
{
msrmntAvailable = false;
return;
}
double raw = rawRegs[ch];
receivedmA = ConvertRawToMilliAmps(raw);
receivedCond = ConvertMilliAmpsToConductivity(receivedmA);
float floatValue = 0;
if (rawRegs != null && rawRegs.Length >= 4)
{
floatValue = ModbusFloat(rawRegs[2], rawRegs[3]);
}
Diagnostics.SetResponse(
lastTelegram,
rawRegs,
receivedmA,
receivedCond,
cfg.MsrdUnit.ToString(),
floatValue);
}
public void RunDeviceAfter()
{
if (DebugLevel == DebugMode.Normal && cfg.EnablePolling && modbus.IsMyTurn(ticketNumber))
{
byte func = (byte)((int)cfg.ReadFunction);
Diagnostics.SetRequest(
cfg.ModbusAddress,
func,
cfg.FirstRegister,
cfg.RegisterCount);
modbus.SendMessage(
cfg.ModbusAddress,
func,
cfg.FirstRegister,
cfg.RegisterCount,
Name);
}
}
public void StopDevice() { }
public void StopDevice2() { }
private void ParseTelegram(byte[] telegram)
{
try
{
if (telegram == null || telegram.Length < 5) return;
byte func = telegram[1];
if (func != (byte)((int)cfg.ReadFunction)) return;
int byteCount = telegram[2];
int expectedRegs = rawRegs.Length;
int expectedBytes = expectedRegs * 2;
if (byteCount < expectedBytes) return;
if (telegram.Length < 3 + expectedBytes) return;
for (int i = 0; i < expectedRegs; i++)
{
int ix = 3 + i * 2;
rawRegs[i] = (ushort)((telegram[ix] << 8) | telegram[ix + 1]);
}
lastUpdate = DateTime.Now;
float floatValue = 0;
if (rawRegs.Length >= 4)
{
floatValue = ModbusFloat(rawRegs[2], rawRegs[3]);
}
Diagnostics.SetResponse(
lastTelegram,
rawRegs,
receivedmA,
receivedCond,
cfg.MsrdUnit.ToString(),
floatValue);
}
catch (Exception ex)
{
Diagnostics.SetError(
ex.Message + Environment.NewLine +
"Telegram: " + BitConverter.ToString(telegram));
log.WarnFormat("{0}: Failed to parse telegram. {1}", Name, ex.Message);
Debug.WriteLine(ex);
}
}
private double ConvertRawToMilliAmps(double raw)
{
if (cfg.RawFormat == RawFormat.Milliamps_x1000)
return raw / 1000.0;
double denom = cfg.RawAt20mA - cfg.RawAt4mA;
if (Math.Abs(denom) < 1e-12) return 0;
return 4.0 + (raw - cfg.RawAt4mA) * (16.0 / denom);
}
private double ConvertMilliAmpsToConductivity(double mA)
{
return cfg.CondAt4mA + (mA - 4.0) / 16.0 * (cfg.CondAt20mA - cfg.CondAt4mA);
}
public void ShowDiagnostics()
{
ConductivityMeterDiagnosticsForm form =
new ConductivityMeterDiagnosticsForm(this);
form.Show();
}
private static float ModbusFloat(ushort hi, ushort lo)
{
byte[] bytes =
{
(byte)(hi >> 8),
(byte)hi,
(byte)(lo >> 8),
(byte)lo
};
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToSingle(bytes, 0);
}
}
}

View File

@ -0,0 +1,108 @@
using System;
using System.Xml.Serialization;
using Config.Entities;
using TBF.Rig.Generic;
namespace TBF.Rig.Modbus.ConductivityMeter
{
public enum ModbusReadFunction
{
ReadHoldingRegisters_03 = 3,
ReadInputRegisters_04 = 4
}
public enum RawFormat
{
Counts16bit,
Milliamps_x1000
}
public class ConductivityMeterCfg : ComponentCfgBase, Generic.IChildComponentCfg
{
public static XmlSerializer Serializer =
XmlSerializer.FromTypes(new[] { typeof(ConductivityMeterCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(System.Collections.Generic.IList<Component> cmpntEntities)
{
return new ConductivityMeterCfgCtrl();
}
/// Modbus link (parent component is Common.Modbus)
public string ParentName; // Modbus component name
public byte ModbusAddress; // 1..247
public ModbusReadFunction ReadFunction; // 03 or 04
public ushort FirstRegister; // start register address on AD4RS
public ushort RegisterCount; // 1..4 typically
public bool EnablePolling;
/// Which channel to use for conductivity value
public int Channel; // 0..(RegisterCount-1)
/// Raw format and scaling
public RawFormat RawFormat;
public double RawAt4mA; // used when RawFormat == Counts16bit
public double RawAt20mA; // used when RawFormat == Counts16bit
public double CondAt4mA; // e.g. 0 uS/cm
public double CondAt20mA; // e.g. 2000 uS/cm
public string MsrdUnit; // "uS/cm"
public string MsrdFormat; // "{0:0}"
public double MsrdValLimLo;
public double MsrdValLimHi;
public int FreshnessMs;
ConductivityMeterCfg()
{
Name = "ConductivityMeter";
ParentName = "Modbus";
ModbusAddress = 50;
ReadFunction = ModbusReadFunction.ReadInputRegisters_04;
FirstRegister = 0;
RegisterCount = 1;
EnablePolling = true;
Channel = 0;
RawFormat = RawFormat.Counts16bit;
RawAt4mA = 13107;
RawAt20mA = 65535;
CondAt4mA = 0;
CondAt20mA = 2000;
MsrdUnit = "uS/cm";
MsrdFormat = "{0:0}";
MsrdValLimLo = 0;
MsrdValLimHi = 5000;
FreshnessMs = 3000;
}
public ConductivityMeterCfg(IComponentFactory factory) : this()
{
this.Factory = factory;
}
public string ToString(int i)
{
return string.Format(
"{0}: Parent={1}, Addr={2}, Fn={3}, Reg={4}, Cnt={5}, Ch={6}, RawFormat={7}, Cond={8}..{9} {10}",
Name,
string.IsNullOrEmpty(ParentName) ? "-" : ParentName,
ModbusAddress,
(int)ReadFunction,
FirstRegister,
RegisterCount,
Channel,
RawFormat,
CondAt4mA,
CondAt20mA,
MsrdUnit);
}
}
}

View File

@ -0,0 +1,469 @@
// ConductivityMeterCfgCtrl.Designer.cs
namespace TBF.Rig.Modbus.ConductivityMeter
{
partial class ConductivityMeterCfgCtrl
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.Label componentNameLabel;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label parentLabel;
private System.Windows.Forms.ComboBox parentNameComboBox;
private System.Windows.Forms.Label modbusAddressLabel;
private System.Windows.Forms.TextBox modbusAddressTextBox;
private System.Windows.Forms.Label fnLabel;
private System.Windows.Forms.ComboBox fnComboBox;
private System.Windows.Forms.Label firstRegisterLabel;
private System.Windows.Forms.TextBox firstRegisterTextBox;
private System.Windows.Forms.Label registerCountLabel;
private System.Windows.Forms.TextBox registerCountTextBox;
private System.Windows.Forms.CheckBox enablePollingCheckBox;
private System.Windows.Forms.Label channelLabel;
private System.Windows.Forms.TextBox channelTextBox;
private System.Windows.Forms.Label rawFormatLabel;
private System.Windows.Forms.ComboBox rawFormatComboBox;
private System.Windows.Forms.Label raw4Label;
private System.Windows.Forms.TextBox raw4TextBox;
private System.Windows.Forms.Label raw20Label;
private System.Windows.Forms.TextBox raw20TextBox;
private System.Windows.Forms.Label cond4Label;
private System.Windows.Forms.TextBox cond4TextBox;
private System.Windows.Forms.Label cond20Label;
private System.Windows.Forms.TextBox cond20TextBox;
private System.Windows.Forms.Label unitLabel;
private System.Windows.Forms.TextBox unitTextBox;
private System.Windows.Forms.Label formatLabel;
private System.Windows.Forms.TextBox formatTextBox;
private System.Windows.Forms.Label limLoLabel;
private System.Windows.Forms.TextBox limLoTextBox;
private System.Windows.Forms.Label limHiLabel;
private System.Windows.Forms.TextBox limHiTextBox;
private System.Windows.Forms.Label freshnessLabel;
private System.Windows.Forms.TextBox freshnessTextBox;
private System.Windows.Forms.Button diagnosticsButton;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.componentNameLabel = new System.Windows.Forms.Label();
this.nameLabel = new System.Windows.Forms.Label();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.parentLabel = new System.Windows.Forms.Label();
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
this.modbusAddressLabel = new System.Windows.Forms.Label();
this.modbusAddressTextBox = new System.Windows.Forms.TextBox();
this.fnLabel = new System.Windows.Forms.Label();
this.fnComboBox = new System.Windows.Forms.ComboBox();
this.firstRegisterLabel = new System.Windows.Forms.Label();
this.firstRegisterTextBox = new System.Windows.Forms.TextBox();
this.registerCountLabel = new System.Windows.Forms.Label();
this.registerCountTextBox = new System.Windows.Forms.TextBox();
this.enablePollingCheckBox = new System.Windows.Forms.CheckBox();
this.channelLabel = new System.Windows.Forms.Label();
this.channelTextBox = new System.Windows.Forms.TextBox();
this.rawFormatLabel = new System.Windows.Forms.Label();
this.rawFormatComboBox = new System.Windows.Forms.ComboBox();
this.raw4Label = new System.Windows.Forms.Label();
this.raw4TextBox = new System.Windows.Forms.TextBox();
this.raw20Label = new System.Windows.Forms.Label();
this.raw20TextBox = new System.Windows.Forms.TextBox();
this.cond4Label = new System.Windows.Forms.Label();
this.cond4TextBox = new System.Windows.Forms.TextBox();
this.cond20Label = new System.Windows.Forms.Label();
this.cond20TextBox = new System.Windows.Forms.TextBox();
this.unitLabel = new System.Windows.Forms.Label();
this.unitTextBox = new System.Windows.Forms.TextBox();
this.formatLabel = new System.Windows.Forms.Label();
this.formatTextBox = new System.Windows.Forms.TextBox();
this.limLoLabel = new System.Windows.Forms.Label();
this.limLoTextBox = new System.Windows.Forms.TextBox();
this.limHiLabel = new System.Windows.Forms.Label();
this.limHiTextBox = new System.Windows.Forms.TextBox();
this.freshnessLabel = new System.Windows.Forms.Label();
this.freshnessTextBox = new System.Windows.Forms.TextBox();
this.diagnosticsButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// componentNameLabel
//
this.componentNameLabel.AutoSize = true;
this.componentNameLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Bold);
this.componentNameLabel.Location = new System.Drawing.Point(12, 10);
this.componentNameLabel.Name = "componentNameLabel";
this.componentNameLabel.Size = new System.Drawing.Size(120, 15);
this.componentNameLabel.TabIndex = 0;
this.componentNameLabel.Text = "ConductivityMeter";
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(12, 40);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 1;
this.nameLabel.Text = "Name";
//
// nameTextBox
//
this.nameTextBox.Location = new System.Drawing.Point(170, 37);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(220, 20);
this.nameTextBox.TabIndex = 2;
//
// parentLabel
//
this.parentLabel.AutoSize = true;
this.parentLabel.Location = new System.Drawing.Point(12, 66);
this.parentLabel.Name = "parentLabel";
this.parentLabel.Size = new System.Drawing.Size(95, 13);
this.parentLabel.TabIndex = 3;
this.parentLabel.Text = "Parent Component";
//
// parentNameComboBox
//
this.parentNameComboBox.FormattingEnabled = true;
this.parentNameComboBox.Location = new System.Drawing.Point(170, 63);
this.parentNameComboBox.Name = "parentNameComboBox";
this.parentNameComboBox.Size = new System.Drawing.Size(220, 21);
this.parentNameComboBox.TabIndex = 4;
//
// modbusAddressLabel
//
this.modbusAddressLabel.AutoSize = true;
this.modbusAddressLabel.Location = new System.Drawing.Point(12, 93);
this.modbusAddressLabel.Name = "modbusAddressLabel";
this.modbusAddressLabel.Size = new System.Drawing.Size(86, 13);
this.modbusAddressLabel.TabIndex = 5;
this.modbusAddressLabel.Text = "Modbus Address";
//
// modbusAddressTextBox
//
this.modbusAddressTextBox.Location = new System.Drawing.Point(170, 90);
this.modbusAddressTextBox.Name = "modbusAddressTextBox";
this.modbusAddressTextBox.Size = new System.Drawing.Size(80, 20);
this.modbusAddressTextBox.TabIndex = 6;
//
// fnLabel
//
this.fnLabel.AutoSize = true;
this.fnLabel.Location = new System.Drawing.Point(12, 119);
this.fnLabel.Name = "fnLabel";
this.fnLabel.Size = new System.Drawing.Size(92, 13);
this.fnLabel.TabIndex = 7;
this.fnLabel.Text = "Function (03 / 04)";
//
// fnComboBox
//
this.fnComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.fnComboBox.FormattingEnabled = true;
this.fnComboBox.Location = new System.Drawing.Point(170, 116);
this.fnComboBox.Name = "fnComboBox";
this.fnComboBox.Size = new System.Drawing.Size(220, 21);
this.fnComboBox.TabIndex = 8;
//
// firstRegisterLabel
//
this.firstRegisterLabel.AutoSize = true;
this.firstRegisterLabel.Location = new System.Drawing.Point(12, 146);
this.firstRegisterLabel.Name = "firstRegisterLabel";
this.firstRegisterLabel.Size = new System.Drawing.Size(68, 13);
this.firstRegisterLabel.TabIndex = 9;
this.firstRegisterLabel.Text = "First Register";
//
// firstRegisterTextBox
//
this.firstRegisterTextBox.Location = new System.Drawing.Point(170, 143);
this.firstRegisterTextBox.Name = "firstRegisterTextBox";
this.firstRegisterTextBox.Size = new System.Drawing.Size(120, 20);
this.firstRegisterTextBox.TabIndex = 10;
//
// registerCountLabel
//
this.registerCountLabel.AutoSize = true;
this.registerCountLabel.Location = new System.Drawing.Point(12, 172);
this.registerCountLabel.Name = "registerCountLabel";
this.registerCountLabel.Size = new System.Drawing.Size(77, 13);
this.registerCountLabel.TabIndex = 11;
this.registerCountLabel.Text = "Register Count";
//
// registerCountTextBox
//
this.registerCountTextBox.Location = new System.Drawing.Point(170, 169);
this.registerCountTextBox.Name = "registerCountTextBox";
this.registerCountTextBox.Size = new System.Drawing.Size(120, 20);
this.registerCountTextBox.TabIndex = 12;
//
// enablePollingCheckBox
//
this.enablePollingCheckBox.AutoSize = true;
this.enablePollingCheckBox.Location = new System.Drawing.Point(170, 197);
this.enablePollingCheckBox.Name = "enablePollingCheckBox";
this.enablePollingCheckBox.Size = new System.Drawing.Size(93, 17);
this.enablePollingCheckBox.TabIndex = 13;
this.enablePollingCheckBox.Text = "Enable Polling";
this.enablePollingCheckBox.UseVisualStyleBackColor = true;
//
// channelLabel
//
this.channelLabel.AutoSize = true;
this.channelLabel.Location = new System.Drawing.Point(12, 224);
this.channelLabel.Name = "channelLabel";
this.channelLabel.Size = new System.Drawing.Size(46, 13);
this.channelLabel.TabIndex = 14;
this.channelLabel.Text = "Channel";
//
// channelTextBox
//
this.channelTextBox.Location = new System.Drawing.Point(170, 221);
this.channelTextBox.Name = "channelTextBox";
this.channelTextBox.Size = new System.Drawing.Size(80, 20);
this.channelTextBox.TabIndex = 15;
//
// rawFormatLabel
//
this.rawFormatLabel.AutoSize = true;
this.rawFormatLabel.Location = new System.Drawing.Point(12, 250);
this.rawFormatLabel.Name = "rawFormatLabel";
this.rawFormatLabel.Size = new System.Drawing.Size(64, 13);
this.rawFormatLabel.TabIndex = 16;
this.rawFormatLabel.Text = "Raw Format";
//
// rawFormatComboBox
//
this.rawFormatComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.rawFormatComboBox.FormattingEnabled = true;
this.rawFormatComboBox.Location = new System.Drawing.Point(170, 247);
this.rawFormatComboBox.Name = "rawFormatComboBox";
this.rawFormatComboBox.Size = new System.Drawing.Size(220, 21);
this.rawFormatComboBox.TabIndex = 17;
//
// raw4Label
//
this.raw4Label.AutoSize = true;
this.raw4Label.Location = new System.Drawing.Point(12, 277);
this.raw4Label.Name = "raw4Label";
this.raw4Label.Size = new System.Drawing.Size(100, 13);
this.raw4Label.TabIndex = 18;
this.raw4Label.Text = "Raw Value @ 4 mA";
//
// raw4TextBox
//
this.raw4TextBox.Location = new System.Drawing.Point(170, 274);
this.raw4TextBox.Name = "raw4TextBox";
this.raw4TextBox.Size = new System.Drawing.Size(120, 20);
this.raw4TextBox.TabIndex = 19;
//
// raw20Label
//
this.raw20Label.AutoSize = true;
this.raw20Label.Location = new System.Drawing.Point(12, 303);
this.raw20Label.Name = "raw20Label";
this.raw20Label.Size = new System.Drawing.Size(106, 13);
this.raw20Label.TabIndex = 20;
this.raw20Label.Text = "Raw Value @ 20 mA";
//
// raw20TextBox
//
this.raw20TextBox.Location = new System.Drawing.Point(170, 300);
this.raw20TextBox.Name = "raw20TextBox";
this.raw20TextBox.Size = new System.Drawing.Size(120, 20);
this.raw20TextBox.TabIndex = 21;
//
// cond4Label
//
this.cond4Label.AutoSize = true;
this.cond4Label.Location = new System.Drawing.Point(12, 329);
this.cond4Label.Name = "cond4Label";
this.cond4Label.Size = new System.Drawing.Size(106, 13);
this.cond4Label.TabIndex = 22;
this.cond4Label.Text = "Conductivity @ 4 mA";
//
// cond4TextBox
//
this.cond4TextBox.Location = new System.Drawing.Point(170, 326);
this.cond4TextBox.Name = "cond4TextBox";
this.cond4TextBox.Size = new System.Drawing.Size(120, 20);
this.cond4TextBox.TabIndex = 23;
//
// cond20Label
//
this.cond20Label.AutoSize = true;
this.cond20Label.Location = new System.Drawing.Point(12, 355);
this.cond20Label.Name = "cond20Label";
this.cond20Label.Size = new System.Drawing.Size(112, 13);
this.cond20Label.TabIndex = 24;
this.cond20Label.Text = "Conductivity @ 20 mA";
//
// cond20TextBox
//
this.cond20TextBox.Location = new System.Drawing.Point(170, 352);
this.cond20TextBox.Name = "cond20TextBox";
this.cond20TextBox.Size = new System.Drawing.Size(120, 20);
this.cond20TextBox.TabIndex = 25;
//
// unitLabel
//
this.unitLabel.AutoSize = true;
this.unitLabel.Location = new System.Drawing.Point(12, 381);
this.unitLabel.Name = "unitLabel";
this.unitLabel.Size = new System.Drawing.Size(26, 13);
this.unitLabel.TabIndex = 26;
this.unitLabel.Text = "Unit";
//
// unitTextBox
//
this.unitTextBox.Location = new System.Drawing.Point(170, 378);
this.unitTextBox.Name = "unitTextBox";
this.unitTextBox.Size = new System.Drawing.Size(120, 20);
this.unitTextBox.TabIndex = 27;
//
// formatLabel
//
this.formatLabel.AutoSize = true;
this.formatLabel.Location = new System.Drawing.Point(12, 407);
this.formatLabel.Name = "formatLabel";
this.formatLabel.Size = new System.Drawing.Size(76, 13);
this.formatLabel.TabIndex = 28;
this.formatLabel.Text = "Display Format";
//
// formatTextBox
//
this.formatTextBox.Location = new System.Drawing.Point(170, 404);
this.formatTextBox.Name = "formatTextBox";
this.formatTextBox.Size = new System.Drawing.Size(220, 20);
this.formatTextBox.TabIndex = 29;
//
// limLoLabel
//
this.limLoLabel.AutoSize = true;
this.limLoLabel.Location = new System.Drawing.Point(12, 433);
this.limLoLabel.Name = "limLoLabel";
this.limLoLabel.Size = new System.Drawing.Size(51, 13);
this.limLoLabel.TabIndex = 30;
this.limLoLabel.Text = "Low Limit";
//
// limLoTextBox
//
this.limLoTextBox.Location = new System.Drawing.Point(170, 430);
this.limLoTextBox.Name = "limLoTextBox";
this.limLoTextBox.Size = new System.Drawing.Size(120, 20);
this.limLoTextBox.TabIndex = 31;
//
// limHiLabel
//
this.limHiLabel.AutoSize = true;
this.limHiLabel.Location = new System.Drawing.Point(12, 459);
this.limHiLabel.Name = "limHiLabel";
this.limHiLabel.Size = new System.Drawing.Size(53, 13);
this.limHiLabel.TabIndex = 32;
this.limHiLabel.Text = "High Limit";
//
// limHiTextBox
//
this.limHiTextBox.Location = new System.Drawing.Point(170, 456);
this.limHiTextBox.Name = "limHiTextBox";
this.limHiTextBox.Size = new System.Drawing.Size(120, 20);
this.limHiTextBox.TabIndex = 33;
//
// freshnessLabel
//
this.freshnessLabel.AutoSize = true;
this.freshnessLabel.Location = new System.Drawing.Point(12, 485);
this.freshnessLabel.Name = "freshnessLabel";
this.freshnessLabel.Size = new System.Drawing.Size(93, 13);
this.freshnessLabel.TabIndex = 34;
this.freshnessLabel.Text = "Data Timeout (ms)";
//
// freshnessTextBox
//
this.freshnessTextBox.Location = new System.Drawing.Point(170, 482);
this.freshnessTextBox.Name = "freshnessTextBox";
this.freshnessTextBox.Size = new System.Drawing.Size(120, 20);
this.freshnessTextBox.TabIndex = 35;
//
// diagnosticsButton
//
this.diagnosticsButton.Location = new System.Drawing.Point(170, 512);
this.diagnosticsButton.Name = "diagnosticsButton";
this.diagnosticsButton.Size = new System.Drawing.Size(120, 27);
this.diagnosticsButton.TabIndex = 36;
this.diagnosticsButton.Text = "Diagnostics...";
this.diagnosticsButton.UseVisualStyleBackColor = true;
this.diagnosticsButton.Click += new System.EventHandler(this.diagnosticsButton_Click);
//
// ConductivityMeterCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.componentNameLabel);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.parentLabel);
this.Controls.Add(this.parentNameComboBox);
this.Controls.Add(this.modbusAddressLabel);
this.Controls.Add(this.modbusAddressTextBox);
this.Controls.Add(this.fnLabel);
this.Controls.Add(this.fnComboBox);
this.Controls.Add(this.firstRegisterLabel);
this.Controls.Add(this.firstRegisterTextBox);
this.Controls.Add(this.registerCountLabel);
this.Controls.Add(this.registerCountTextBox);
this.Controls.Add(this.enablePollingCheckBox);
this.Controls.Add(this.channelLabel);
this.Controls.Add(this.channelTextBox);
this.Controls.Add(this.rawFormatLabel);
this.Controls.Add(this.rawFormatComboBox);
this.Controls.Add(this.raw4Label);
this.Controls.Add(this.raw4TextBox);
this.Controls.Add(this.raw20Label);
this.Controls.Add(this.raw20TextBox);
this.Controls.Add(this.cond4Label);
this.Controls.Add(this.cond4TextBox);
this.Controls.Add(this.cond20Label);
this.Controls.Add(this.cond20TextBox);
this.Controls.Add(this.unitLabel);
this.Controls.Add(this.unitTextBox);
this.Controls.Add(this.formatLabel);
this.Controls.Add(this.formatTextBox);
this.Controls.Add(this.limLoLabel);
this.Controls.Add(this.limLoTextBox);
this.Controls.Add(this.limHiLabel);
this.Controls.Add(this.limHiTextBox);
this.Controls.Add(this.freshnessLabel);
this.Controls.Add(this.freshnessTextBox);
this.Controls.Add(this.diagnosticsButton);
this.Name = "ConductivityMeterCfgCtrl";
this.Size = new System.Drawing.Size(420, 551);
this.Load += new System.EventHandler(this.ConductivityMeterCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
}
}

View File

@ -0,0 +1,258 @@
using Common;
using Config.Entities;
using System;
using System.Windows.Forms;
using TBF.Rig.Generic;
using TBF.UI.Bench.Components;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace TBF.Rig.Modbus.ConductivityMeter
{
public partial class ConductivityMeterCfgCtrl : UserControl, IComponentCfgCtrl
{
ComponentParametersDlg parent;
public bool ShowMore { get { return false; } }
ConductivityMeterCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as ConductivityMeterCfg;
Redraw();
}
}
public ConductivityMeterCfgCtrl()
{
InitializeComponent();
}
private void ConductivityMeterCfgCtrl_Load(object sender, EventArgs e)
{
parent = ParentForm as ComponentParametersDlg;
if (parent == null) return;
// Parent selection: Modbus component
if (parent.CmpntEntities != null)
{
foreach (var cmpnt in parent.CmpntEntities)
{
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Modbus.Common.Factory)
{
parentNameComboBox.Items.Add(cmpnt.Name);
}
}
}
// Function 03/04
fnComboBox.Items.Add(ModbusReadFunction.ReadHoldingRegisters_03.ToString());
fnComboBox.Items.Add(ModbusReadFunction.ReadInputRegisters_04.ToString());
// Raw format
rawFormatComboBox.Items.Add(RawFormat.Counts16bit.ToString());
rawFormatComboBox.Items.Add(RawFormat.Milliamps_x1000.ToString());
Redraw();
}
public void Closing() { }
void Redraw()
{
if (config == null) return;
componentNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
modbusAddressTextBox.Text = config.ModbusAddress.ToString();
fnComboBox.Text = config.ReadFunction.ToString();
firstRegisterTextBox.Text = config.FirstRegister.ToString();
registerCountTextBox.Text = config.RegisterCount.ToString();
enablePollingCheckBox.Checked = config.EnablePolling;
channelTextBox.Text = config.Channel.ToString();
rawFormatComboBox.Text = config.RawFormat.ToString();
raw4TextBox.Text = config.RawAt4mA.ToString();
raw20TextBox.Text = config.RawAt20mA.ToString();
cond4TextBox.Text = config.CondAt4mA.ToString();
cond20TextBox.Text = config.CondAt20mA.ToString();
unitTextBox.Text = config.MsrdUnit;
formatTextBox.Text = config.MsrdFormat;
limLoTextBox.Text = config.MsrdValLimLo.ToString();
limHiTextBox.Text = config.MsrdValLimHi.ToString();
freshnessTextBox.Text = config.FreshnessMs.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
parentNameComboBox.Enabled = true;
modbusAddressTextBox.Enabled = true;
fnComboBox.Enabled = true;
firstRegisterTextBox.Enabled = true;
registerCountTextBox.Enabled = true;
enablePollingCheckBox.Enabled = true;
channelTextBox.Enabled = true;
rawFormatComboBox.Enabled = true;
raw4TextBox.Enabled = true;
raw20TextBox.Enabled = true;
cond4TextBox.Enabled = true;
cond20TextBox.Enabled = true;
unitTextBox.Enabled = true;
formatTextBox.Enabled = true;
limLoTextBox.Enabled = true;
limHiTextBox.Enabled = true;
freshnessTextBox.Enabled = true;
diagnosticsButton.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int iVal;
double dVal;
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Parent Component'";
}
if (!int.TryParse(modbusAddressTextBox.Text, out iVal) || iVal < 1 || iVal > 247)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Modbus Address' must be between 1 and 247";
}
if (!fnComboBox.Items.Contains(fnComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Function (03/04)'";
}
if (!int.TryParse(firstRegisterTextBox.Text, out iVal) || iVal < 0 || iVal > 65535)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'First Register' must be between 0 and 65535";
}
if (!int.TryParse(registerCountTextBox.Text, out iVal) || iVal < 1 || iVal > 4)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Register Count' must be between 1 and 4";
}
if (!int.TryParse(channelTextBox.Text, out iVal) || iVal < 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Channel'";
}
if (!rawFormatComboBox.Items.Contains(rawFormatComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Raw Format'";
}
if (!double.TryParse(raw4TextBox.Text, out dVal) || !double.TryParse(raw20TextBox.Text, out dVal))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid raw calibration values (Raw @ 4 mA / Raw @ 20 mA)";
}
if (!double.TryParse(cond4TextBox.Text, out dVal) || !double.TryParse(cond20TextBox.Text, out dVal))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid conductivity scaling values (Cond @ 4 mA / Cond @ 20 mA)";
}
if (!int.TryParse(freshnessTextBox.Text, out iVal) || iVal < 100)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Data Timeout (ms)' must be at least 100";
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
if (config == null) return CfgUpdateFlags.Error;
config.Name = nameTextBox.Text;
config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
config.ModbusAddress = (byte)int.Parse(modbusAddressTextBox.Text);
foreach (ModbusReadFunction fn in Enum.GetValues(typeof(ModbusReadFunction)))
{
if (fnComboBox.Text == fn.ToString()) { config.ReadFunction = fn; break; }
}
config.FirstRegister = (ushort)int.Parse(firstRegisterTextBox.Text);
config.RegisterCount = (ushort)int.Parse(registerCountTextBox.Text);
config.EnablePolling = enablePollingCheckBox.Checked;
config.Channel = int.Parse(channelTextBox.Text);
foreach (RawFormat rf in Enum.GetValues(typeof(RawFormat)))
{
if (rawFormatComboBox.Text == rf.ToString()) { config.RawFormat = rf; break; }
}
config.RawAt4mA = double.Parse(raw4TextBox.Text);
config.RawAt20mA = double.Parse(raw20TextBox.Text);
config.CondAt4mA = double.Parse(cond4TextBox.Text);
config.CondAt20mA = double.Parse(cond20TextBox.Text);
config.MsrdUnit = unitTextBox.Text;
config.MsrdFormat = formatTextBox.Text;
config.MsrdValLimLo = double.Parse(limLoTextBox.Text);
config.MsrdValLimHi = double.Parse(limHiTextBox.Text);
config.FreshnessMs = int.Parse(freshnessTextBox.Text);
return CfgUpdateFlags.RestartRqrd;
}
private void diagnosticsButton_Click(object sender, EventArgs e)
{
if (config == null) return;
ConductivityMeter cmpnt =
TbfComponents.FindComponent(config.Name) as ConductivityMeter;
if (cmpnt == null)
{
MessageBox.Show(
"Runtime component was not found. Diagnostics are available only while the component is initialized.",
"Diagnostics",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
cmpnt.ShowDiagnostics();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,164 @@
// ConductivityMeterDiagnostics.cs
using System;
using System.Text;
namespace TBF.Rig.Modbus.ConductivityMeter
{
public class ConductivityMeterDiagnostics
{
public DateTime LastRequestTime { get; private set; }
public DateTime LastResponseTime { get; private set; }
public string LastRequest { get; private set; }
public string LastResponse { get; private set; }
public string LastError { get; private set; }
public int RequestCount { get; private set; }
public int ResponseCount { get; private set; }
public int ErrorCount { get; private set; }
public ConductivityMeterDiagnostics()
{
LastRequest = string.Empty;
LastResponse = string.Empty;
LastError = string.Empty;
}
public void Clear()
{
LastRequestTime = DateTime.MinValue;
LastResponseTime = DateTime.MinValue;
LastRequest = string.Empty;
LastResponse = string.Empty;
LastError = string.Empty;
RequestCount = 0;
ResponseCount = 0;
ErrorCount = 0;
}
public void SetRequest(
byte address,
byte function,
ushort firstRegister,
ushort registerCount)
{
RequestCount++;
LastRequestTime = DateTime.Now;
LastRequest = string.Format(
"TX {0:HH:mm:ss.fff}{1}" +
"Address: {2}{1}" +
"Function: 0x{3:X2}{1}" +
"First register: {4}{1}" +
"Register count: {5}",
LastRequestTime,
Environment.NewLine,
address,
function,
firstRegister,
registerCount);
}
public void SetResponse(
byte[] telegram,
ushort[] rawRegisters,
double milliAmps,
double conductivity,
string unit,
float floatValue)
{
ResponseCount++;
LastResponseTime = DateTime.Now;
var sb = new StringBuilder();
sb.AppendFormat("RX {0:HH:mm:ss.fff}", LastResponseTime);
sb.AppendLine();
sb.Append("Telegram: ");
sb.AppendLine(ToHex(telegram));
if (rawRegisters != null)
{
for (int i = 0; i < rawRegisters.Length; i++)
{
sb.AppendFormat("Raw[{0}]: {1}", i, rawRegisters[i]);
sb.AppendLine();
}
}
sb.AppendFormat("Float value: {0:0.###}", floatValue);
sb.AppendLine();
sb.AppendFormat("Current: {0:0.000} mA", milliAmps);
sb.AppendLine();
sb.AppendFormat("Conductivity: {0:0.###} {1}", conductivity, unit);
LastResponse = sb.ToString();
LastError = string.Empty;
}
public void SetError(string message)
{
ErrorCount++;
LastError = string.Format(
"{0:HH:mm:ss.fff} {1}",
DateTime.Now,
message);
}
public string GetText()
{
var sb = new StringBuilder();
sb.AppendLine("Conductivity Meter Diagnostics");
sb.AppendLine("--------------------------------");
sb.AppendFormat("Requests: {0}", RequestCount);
sb.AppendLine();
sb.AppendFormat("Responses: {0}", ResponseCount);
sb.AppendLine();
sb.AppendFormat("Errors: {0}", ErrorCount);
sb.AppendLine();
sb.AppendLine();
if (!string.IsNullOrEmpty(LastRequest))
{
sb.AppendLine(LastRequest);
sb.AppendLine();
}
if (!string.IsNullOrEmpty(LastResponse))
{
sb.AppendLine(LastResponse);
sb.AppendLine();
}
if (!string.IsNullOrEmpty(LastError))
{
sb.AppendLine("Last error:");
sb.AppendLine(LastError);
}
return sb.ToString();
}
static string ToHex(byte[] data)
{
if (data == null || data.Length == 0)
return string.Empty;
var sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
if (i > 0) sb.Append(" ");
sb.Append(data[i].ToString("X2"));
}
return sb.ToString();
}
}
}

View File

@ -0,0 +1,91 @@
namespace TBF.Rig.Modbus.ConductivityMeter
{
partial class ConductivityMeterDiagnosticsForm
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.TextBox diagnosticsTextBox;
private System.Windows.Forms.Button clearButton;
private System.Windows.Forms.Button closeButton;
private System.Windows.Forms.Timer refreshTimer;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.diagnosticsTextBox = new System.Windows.Forms.TextBox();
this.clearButton = new System.Windows.Forms.Button();
this.closeButton = new System.Windows.Forms.Button();
this.refreshTimer = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// diagnosticsTextBox
//
this.diagnosticsTextBox.Anchor =
((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Bottom) |
System.Windows.Forms.AnchorStyles.Left) |
System.Windows.Forms.AnchorStyles.Right)));
this.diagnosticsTextBox.Font = new System.Drawing.Font("Consolas", 9F);
this.diagnosticsTextBox.Location = new System.Drawing.Point(12, 12);
this.diagnosticsTextBox.Multiline = true;
this.diagnosticsTextBox.Name = "diagnosticsTextBox";
this.diagnosticsTextBox.ReadOnly = true;
this.diagnosticsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.diagnosticsTextBox.Size = new System.Drawing.Size(660, 390);
this.diagnosticsTextBox.TabIndex = 0;
this.diagnosticsTextBox.WordWrap = false;
//
// clearButton
//
this.clearButton.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom |
System.Windows.Forms.AnchorStyles.Left)));
this.clearButton.Location = new System.Drawing.Point(12, 415);
this.clearButton.Name = "clearButton";
this.clearButton.Size = new System.Drawing.Size(90, 27);
this.clearButton.TabIndex = 1;
this.clearButton.Text = "Clear";
this.clearButton.UseVisualStyleBackColor = true;
this.clearButton.Click += new System.EventHandler(this.clearButton_Click);
//
// closeButton
//
this.closeButton.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom |
System.Windows.Forms.AnchorStyles.Right)));
this.closeButton.Location = new System.Drawing.Point(582, 415);
this.closeButton.Name = "closeButton";
this.closeButton.Size = new System.Drawing.Size(90, 27);
this.closeButton.TabIndex = 2;
this.closeButton.Text = "Close";
this.closeButton.UseVisualStyleBackColor = true;
this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
//
// refreshTimer
//
this.refreshTimer.Interval = 500;
this.refreshTimer.Tick += new System.EventHandler(this.refreshTimer_Tick);
//
// ConductivityMeterDiagnosticsForm
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(684, 454);
this.Controls.Add(this.diagnosticsTextBox);
this.Controls.Add(this.clearButton);
this.Controls.Add(this.closeButton);
this.Name = "ConductivityMeterDiagnosticsForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Conductivity Meter - Modbus Diagnostics";
this.Load += new System.EventHandler(this.ConductivityMeterDiagnosticsForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
}
}

View File

@ -0,0 +1,61 @@
using System;
using System.Windows.Forms;
namespace TBF.Rig.Modbus.ConductivityMeter
{
public partial class ConductivityMeterDiagnosticsForm : Form
{
readonly ConductivityMeter conductivityMeter;
public ConductivityMeterDiagnosticsForm(ConductivityMeter conductivityMeter)
{
if (conductivityMeter == null)
throw new ArgumentNullException("conductivityMeter");
this.conductivityMeter = conductivityMeter;
InitializeComponent();
}
private void ConductivityMeterDiagnosticsForm_Load(object sender, EventArgs e)
{
refreshTimer.Start();
RefreshDiagnostics();
}
private void refreshTimer_Tick(object sender, EventArgs e)
{
RefreshDiagnostics();
}
private void RefreshDiagnostics()
{
if (conductivityMeter.Diagnostics == null)
{
diagnosticsTextBox.Text = "Diagnostics are not available.";
return;
}
diagnosticsTextBox.Text = conductivityMeter.Diagnostics.GetText();
}
private void clearButton_Click(object sender, EventArgs e)
{
if (conductivityMeter.Diagnostics != null)
conductivityMeter.Diagnostics.Clear();
RefreshDiagnostics();
}
private void closeButton_Click(object sender, EventArgs e)
{
Close();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
refreshTimer.Stop();
base.OnFormClosing(e);
}
}
}

View File

@ -0,0 +1,35 @@
using System.Collections.Generic;
using TBF.Rig.Generic;
using TBF.Rig.Modbus.ConductivityMeter;
namespace TBF.Rig.Modbus.ConductivityMeter
{
public class Factory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public IComponent DummyComponent()
{
return new ConductivityMeter();
}
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components)
{
return new ConductivityMeter(cfg, components);
}
public IComponentCfg DefaultConfig()
{
return new ConductivityMeterCfg(this);
}
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(
ConductivityMeterCfg.Serializer,
component,
this);
}
}
}

View File

@ -80,6 +80,7 @@ namespace TBF.Rig
new Modbus.TempMeter.Meret.Factory(), /// Meret temperature meter connected via a modbus on a PC
new Modbus.UltrasoundLevelMeter.Factory(),
new Modbus.WaterAnalyzer.Factory(),
new Modbus.ConductivityMeter.Factory(),
new Network.Adapter.Factory(),
new Network.AdapterFTP.Factory(),
new Network.AdapterJMS.Factory(),

View File

@ -873,6 +873,22 @@
<Compile Include="Rig\Modbus\Ambient\Comet\AmbientCfg.cs" />
<Compile Include="Rig\Modbus\Ambient\Comet\Factory.cs" />
<Compile Include="Rig\Modbus\Common\TelegramMeno.cs" />
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeter.cs" />
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeterCfg.cs" />
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeterCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeterCfgCtrl.Designer.cs">
<DependentUpon>ConductivityMeterCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeterDiagnostics.cs" />
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeterDiagnosticsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Rig\Modbus\ConductivityMeter\ConductivityMeterDiagnosticsForm.Designer.cs">
<DependentUpon>ConductivityMeterDiagnosticsForm.cs</DependentUpon>
</Compile>
<Compile Include="Rig\Modbus\ConductivityMeter\Factory.cs" />
<Compile Include="Rig\Modbus\Enums.cs" />
<Compile Include="Rig\Modbus\Common\Modbus.cs" />
<Compile Include="Rig\Modbus\Common\ModbusCfg.cs" />
@ -3577,6 +3593,9 @@
<EmbeddedResource Include="Rig\MettlerToledo\Standard\BalanceCfgCtrl.resx">
<DependentUpon>BalanceCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Rig\Modbus\ConductivityMeter\ConductivityMeterCfgCtrl.resx">
<DependentUpon>ConductivityMeterCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Rig\Modbus\PumpFM\DanfossVLT\PumpCfgCtrl.resx">
<DependentUpon>PumpCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
@ -4499,6 +4518,7 @@
<Name>Results</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="Build\CopyGci.targets.xml" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.