diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeter.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeter.cs new file mode 100644 index 000000000..b1cc21d16 --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeter.cs @@ -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 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); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfg.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfg.cs new file mode 100644 index 000000000..d0cc4c4e4 --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfg.cs @@ -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 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); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.Designer.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.Designer.cs new file mode 100644 index 000000000..187b4d35c --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.Designer.cs @@ -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(); + + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.cs new file mode 100644 index 000000000..a6072d5cd --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.resx b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterCfgCtrl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnostics.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnostics.cs new file mode 100644 index 000000000..ea5aa849c --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnostics.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnosticsForm.Designer.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnosticsForm.Designer.cs new file mode 100644 index 000000000..b2e4f2688 --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnosticsForm.Designer.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnosticsForm.cs b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnosticsForm.cs new file mode 100644 index 000000000..1b39fe194 --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/ConductivityMeterDiagnosticsForm.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/Modbus/ConductivityMeter/Factory.cs b/TBF/Rig/Modbus/ConductivityMeter/Factory.cs new file mode 100644 index 000000000..34c593fce --- /dev/null +++ b/TBF/Rig/Modbus/ConductivityMeter/Factory.cs @@ -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 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); + } + } +} \ No newline at end of file diff --git a/TBF/Rig/TbfComponents.cs b/TBF/Rig/TbfComponents.cs index fafa75950..38fa3d8c3 100644 --- a/TBF/Rig/TbfComponents.cs +++ b/TBF/Rig/TbfComponents.cs @@ -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(), diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index a98f0bdee..19c5a817b 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -873,6 +873,22 @@ + + + + UserControl + + + ConductivityMeterCfgCtrl.cs + + + + Form + + + ConductivityMeterDiagnosticsForm.cs + + @@ -3577,6 +3593,9 @@ BalanceCfgCtrl.cs + + ConductivityMeterCfgCtrl.cs + PumpCfgCtrl.cs @@ -4499,6 +4518,7 @@ Results +