From b54f938bd5c2967bd604332ed74566edc4ffcdce Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Thu, 28 Sep 2017 15:24:10 +0200 Subject: [PATCH] Modbus.CometAmbient component implemented (Comet and Easytherms are connected to the same Modbus), ver. 2.17.678 --- .../Modbus/CometAmbient/Ambient.cs | 176 ++++++++++++++++++ .../Modbus/CometAmbient/AmbientCfg.cs | 45 +++++ .../CometAmbient/AmbientCfgCtrl.Designer.cs | 156 ++++++++++++++++ .../Modbus/CometAmbient/AmbientCfgCtrl.cs | 106 +++++++++++ .../Modbus/CometAmbient/AmbientCfgCtrl.resx | 120 ++++++++++++ .../Modbus/CometAmbient/Factory.cs | 26 +++ .../BenchControl/TbfComponents.cs | 3 +- TestBenchFramework/Properties/AssemblyInfo.cs | 4 +- TestBenchFramework/TBF.csproj | 12 ++ 9 files changed, 645 insertions(+), 3 deletions(-) create mode 100644 TestBenchFramework/BenchControl/Modbus/CometAmbient/Ambient.cs create mode 100644 TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfg.cs create mode 100644 TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.Designer.cs create mode 100644 TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.cs create mode 100644 TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.resx create mode 100644 TestBenchFramework/BenchControl/Modbus/CometAmbient/Factory.cs diff --git a/TestBenchFramework/BenchControl/Modbus/CometAmbient/Ambient.cs b/TestBenchFramework/BenchControl/Modbus/CometAmbient/Ambient.cs new file mode 100644 index 000000000..739bca303 --- /dev/null +++ b/TestBenchFramework/BenchControl/Modbus/CometAmbient/Ambient.cs @@ -0,0 +1,176 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO.Ports; +using System.Text; +using log4net; +using Config.Entities; +using TBF.BenchControl.Generic; +using TBF.Boxes; + +namespace TBF.BenchControl.Modbus.CometAmbient +{ + /// + /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) + /// Connection settings: 9600 Bd 8-bits No-parity 2-stop-bits Flow control: none. + /// + public class Ambient : ComponentBase, IDevice, IOperation, GenericDevices.IAmbient + { + private static readonly ILog log = LogManager.GetLogger(typeof(Ambient)); + public override string ToString() { return string.Format("Ambient({0})", Cfg.ToString(1)); } + + readonly AmbientCfg ambientCfg; + readonly GenericDevices.IModbus modbus; + + /// The state of the measurement + MsrmntState msrmntState; + + /// + /// Measured values when MsrmntState == MsrmntState.Valid + /// + float temperature; /// [deg C] + float pressure; /// [bar] + float humidity; /// [%] + + /// Measurement time stamp when MsrmntState == MsrmntState.Valid + int msrmntTimeStamp; + + public Ambient() + { + } + + /// + /// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232) + /// + public Ambient(Generic.IComponentCfg cfg, IList components) + : base(cfg) + { + ambientCfg = cfg as AmbientCfg; + + modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components); + if (modbus == null) throw new Exception("Cannot find " + Name + " parent"); + + log.Debug(this.ToString()); + } + + public void Initialize() + { + if (ambientCfg.DebugLevel == DebugMode.Simulate) + { + temperature = 20.0f; + humidity = 40.0f; + pressure = 1.0f; + msrmntTimeStamp = StateMachine.Time; + msrmntState = MsrmntState.Valid; + return; + } + + msrmntState = MsrmntState.Busy; + + log.FatalFormat("Successfully initialized device {0}", ToString()); + } + + /// Run this device + public void RunDeviceBefore() + { + if (ambientCfg.DebugLevel == DebugMode.Simulate || + ambientCfg.DebugLevel == DebugMode.FailureDuringOperation) + { + msrmntTimeStamp = StateMachine.Time; + return; + } + + if (modbus.ReceivedTelegrams[ambientCfg.ModbusAddress].Count > 0) + { + byte[] telegram = modbus.ReceivedTelegrams[ambientCfg.ModbusAddress].Dequeue(); + + if (telegram.Length == 13 && telegram[1] == 3 && telegram[2] == 8) + { + int value = (int)telegram[3] * 256 + (int)telegram[4]; + temperature = (float)value / 10.0f; + + value = (int)telegram[5] * 256 + (int)telegram[6]; + humidity = (float)value / 10.0f; + + value = (int)telegram[9] * 256 + (int)telegram[10]; + pressure = (float)value / 10000.0f; + + msrmntTimeStamp = StateMachine.Time; + msrmntState = MsrmntState.Valid; + log.InfoFormat("Ambient: temperature = {0} C, humidity = {1} %, pressure = {2} mbar", temperature.ToString("F1"), humidity.ToString("F1"), (1000 * pressure).ToString("F0")); + } + } + + if ((StateMachine.Time % 10) == (ambientCfg.ModbusAddress % 10)) /// Each 10 seconds + { + /// Read four registers: 0x31, 0x32, 0x33, 0x34 + UInt16 regAddr = 0x0030; /// register addr. = 0x31 (Modbus!) + UInt16 count = 4; + + /// Prepare data to be sent + byte[] msg = new byte[8]; + msg[0] = ambientCfg.ModbusAddress; + msg[1] = 3; /// CMD = Read registers + msg[2] = (byte)(regAddr >> 8); /// Control Word Hi + msg[3] = (byte)(regAddr & 0xFF); /// Control Word Lo + msg[4] = (byte)(count >> 8); /// Serial Com Reference Hi + msg[5] = (byte)(count & 0xFF); /// Serial Com Reference Lo + + modbus.SendMessage(msg); + } + } + + /// Run this device + public void RunDeviceAfter() + { + } + + /// Stop this device + public void StopDevice() + { + } + + /// + /// Boxes for the operation result + /// + FloatBox tempBox; + FloatBox pressureBox; + FloatBox humiBox; + + public IOperation ReadAmbientOp(FloatBox temperature, FloatBox pressure, FloatBox humidity) + { + this.tempBox = temperature; + this.pressureBox = pressure; + this.humiBox = humidity; + return this; + } + + /// Start this operation + public void Start() + { + if (tempBox != null) tempBox.Val = temperature; + if (pressureBox != null) pressureBox.Val = pressure; + if (humiBox != null) humiBox.Val = humidity; + } + + /// Run this operation + /// + /// Event.FlowInDone or Event.FlowOutDone + /// + public Event Run() + { + if (tempBox != null) tempBox.Val = temperature; + if (pressureBox != null) pressureBox.Val = pressure; + if (humiBox != null) humiBox.Val = humidity; + return Event.AmbientDone; + } + + /// Stop this operation + public void Stop() + { + } + } +} diff --git a/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfg.cs b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfg.cs new file mode 100644 index 000000000..126a5aaf5 --- /dev/null +++ b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfg.cs @@ -0,0 +1,45 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Modbus.CometAmbient +{ + public class AmbientCfg : ComponentCfgBase, Generic.IChildComponentCfg + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(AmbientCfg) })[0]; + protected override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() { return new AmbientCfgCtrl(); } + + /// + /// Serialized parameters + /// + public byte ModbusAddress; /// 1..255 + + /// Private parameterless constructor invoked by all other (public) constructors + AmbientCfg() + { + Name = "Ambient"; + ParentName = "Modbus"; + ModbusAddress = 1; + } + + public AmbientCfg(IComponentFactory factory) + : this() + { + this.Factory = factory; + } + + public string ToString(int i) + { + return string.Format("Name={0}, ModbusAddr={1}, Parent={2}", + Name, + ModbusAddress, + (string.IsNullOrEmpty(ParentName) ? "-" : ParentName)); + } + } +} diff --git a/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.Designer.cs b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.Designer.cs new file mode 100644 index 000000000..5649b543a --- /dev/null +++ b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.Designer.cs @@ -0,0 +1,156 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +namespace TBF.BenchControl.Modbus.CometAmbient +{ + partial class AmbientCfgCtrl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.parentNameLabel = new System.Windows.Forms.Label(); + this.nameTextBox = new System.Windows.Forms.TextBox(); + this.nameLabel = new System.Windows.Forms.Label(); + this.componentNameLabel = new System.Windows.Forms.Label(); + this.modbusAddressLabel = new System.Windows.Forms.Label(); + this.modbusAddressTextBox = new System.Windows.Forms.TextBox(); + this.parentNameComboBox = new System.Windows.Forms.ComboBox(); + this.reservoirNrTextBox = new System.Windows.Forms.TextBox(); + this.reservoirNrLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // parentNameLabel + // + this.parentNameLabel.AutoSize = true; + this.parentNameLabel.Location = new System.Drawing.Point(28, 81); + this.parentNameLabel.Name = "parentNameLabel"; + this.parentNameLabel.Size = new System.Drawing.Size(69, 13); + this.parentNameLabel.TabIndex = 3; + this.parentNameLabel.Text = "Parent Name"; + // + // nameTextBox + // + this.nameTextBox.Enabled = false; + this.nameTextBox.Location = new System.Drawing.Point(138, 52); + this.nameTextBox.Name = "nameTextBox"; + this.nameTextBox.Size = new System.Drawing.Size(130, 20); + this.nameTextBox.TabIndex = 2; + // + // nameLabel + // + this.nameLabel.AutoSize = true; + this.nameLabel.Location = new System.Drawing.Point(28, 55); + this.nameLabel.Name = "nameLabel"; + this.nameLabel.Size = new System.Drawing.Size(35, 13); + this.nameLabel.TabIndex = 1; + this.nameLabel.Text = "Name"; + // + // componentNameLabel + // + this.componentNameLabel.AutoSize = true; + this.componentNameLabel.Location = new System.Drawing.Point(135, 28); + this.componentNameLabel.Name = "componentNameLabel"; + this.componentNameLabel.Size = new System.Drawing.Size(83, 13); + this.componentNameLabel.TabIndex = 0; + this.componentNameLabel.Text = "ComonentName"; + // + // modbusAddressLabel + // + this.modbusAddressLabel.AutoSize = true; + this.modbusAddressLabel.Location = new System.Drawing.Point(28, 108); + this.modbusAddressLabel.Name = "modbusAddressLabel"; + this.modbusAddressLabel.Size = new System.Drawing.Size(86, 13); + this.modbusAddressLabel.TabIndex = 7; + this.modbusAddressLabel.Text = "Modbus Address"; + // + // modbusAddressTextBox + // + this.modbusAddressTextBox.Enabled = false; + this.modbusAddressTextBox.Location = new System.Drawing.Point(138, 105); + this.modbusAddressTextBox.Name = "modbusAddressTextBox"; + this.modbusAddressTextBox.Size = new System.Drawing.Size(46, 20); + this.modbusAddressTextBox.TabIndex = 8; + // + // parentNameComboBox + // + this.parentNameComboBox.Enabled = false; + this.parentNameComboBox.FormattingEnabled = true; + this.parentNameComboBox.Location = new System.Drawing.Point(138, 78); + this.parentNameComboBox.Name = "parentNameComboBox"; + this.parentNameComboBox.Size = new System.Drawing.Size(130, 21); + this.parentNameComboBox.TabIndex = 4; + // + // reservoirNrTextBox + // + this.reservoirNrTextBox.Enabled = false; + this.reservoirNrTextBox.Location = new System.Drawing.Point(138, 130); + this.reservoirNrTextBox.Name = "reservoirNrTextBox"; + this.reservoirNrTextBox.Size = new System.Drawing.Size(46, 20); + this.reservoirNrTextBox.TabIndex = 10; + // + // reservoirNrLabel + // + this.reservoirNrLabel.AutoSize = true; + this.reservoirNrLabel.Location = new System.Drawing.Point(28, 133); + this.reservoirNrLabel.Name = "reservoirNrLabel"; + this.reservoirNrLabel.Size = new System.Drawing.Size(67, 13); + this.reservoirNrLabel.TabIndex = 9; + this.reservoirNrLabel.Text = "Reservoir nr."; + // + // EasythermCfgCtrl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.reservoirNrTextBox); + this.Controls.Add(this.reservoirNrLabel); + this.Controls.Add(this.parentNameComboBox); + this.Controls.Add(this.modbusAddressTextBox); + this.Controls.Add(this.modbusAddressLabel); + this.Controls.Add(this.parentNameLabel); + this.Controls.Add(this.nameTextBox); + this.Controls.Add(this.nameLabel); + this.Controls.Add(this.componentNameLabel); + this.Name = "EasythermCfgCtrl"; + this.Size = new System.Drawing.Size(300, 200); + this.Load += new System.EventHandler(this.AmbientCfgCtrl_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label parentNameLabel; + private System.Windows.Forms.TextBox nameTextBox; + private System.Windows.Forms.Label nameLabel; + private System.Windows.Forms.Label componentNameLabel; + private System.Windows.Forms.Label modbusAddressLabel; + private System.Windows.Forms.TextBox modbusAddressTextBox; + private System.Windows.Forms.ComboBox parentNameComboBox; + private System.Windows.Forms.TextBox reservoirNrTextBox; + private System.Windows.Forms.Label reservoirNrLabel; + } +} diff --git a/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.cs b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.cs new file mode 100644 index 000000000..2adaaa328 --- /dev/null +++ b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.cs @@ -0,0 +1,106 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System; +using System.Windows.Forms; +using log4net; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Modbus.CometAmbient +{ + public partial class AmbientCfgCtrl : UserControl, IComponentCfgCtrl + { + static readonly ILog log = LogManager.GetLogger(typeof(AmbientCfgCtrl)); + + ComponentParametersDlg parent; + + public bool ShowMore { get { return false; } } + + AmbientCfg config; + public IComponentCfg Config + { + get { return config as IComponentCfg; } + set + { + config = value as AmbientCfg; + Redraw(); + } + } + + public AmbientCfgCtrl() + { + InitializeComponent(); + } + + private void AmbientCfgCtrl_Load(object sender, EventArgs e) + { + parent = ParentForm as ComponentParametersDlg; + if (parent == null) return; + + if (parent.TbfComponents != null) + { + foreach (var cmpnt in parent.TbfComponents) + { + if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Modbus.Common.Factory) + { + parentNameComboBox.Items.Add(cmpnt.Name); + } + } + } + + Redraw(); + } + + public void Closing() + { + } + + void Redraw() + { + if (config == null) return; /// Control was not loaded, settings were not changed + + componentNameLabel.Text = config.Factory.ClassName; + nameTextBox.Text = config.Name; + parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName; + modbusAddressTextBox.Text = config.ModbusAddress.ToString(); + } + + public void Unlock() + { + nameTextBox.Enabled = true; + parentNameComboBox.Enabled = true; + modbusAddressTextBox.Enabled = true; + } + + public CfgUpdateFlags VerifyCfg(ref string message) + { + CfgUpdateFlags flags = CfgUpdateFlags.None; + + int dummy; + if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text)) + { + flags |= CfgUpdateFlags.Error; + message += Environment.NewLine + "Invalid 'Parent Name'"; + } + if (!int.TryParse(modbusAddressTextBox.Text, out dummy) || dummy < 0 || dummy > 255) + { + flags |= CfgUpdateFlags.Error; + message += Environment.NewLine + "'Modbus Address' should be between 0 and 255"; + } + return flags; + } + + public CfgUpdateFlags UpdateCfg() + { + CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd; + + if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed + + config.Name = nameTextBox.Text; + config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text; + config.ModbusAddress = (byte)int.Parse(modbusAddressTextBox.Text); + + return flags; + } + } +} diff --git a/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.resx b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TestBenchFramework/BenchControl/Modbus/CometAmbient/AmbientCfgCtrl.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/TestBenchFramework/BenchControl/Modbus/CometAmbient/Factory.cs b/TestBenchFramework/BenchControl/Modbus/CometAmbient/Factory.cs new file mode 100644 index 000000000..5c43f92cb --- /dev/null +++ b/TestBenchFramework/BenchControl/Modbus/CometAmbient/Factory.cs @@ -0,0 +1,26 @@ +/// +/// Copyright (c) 2017 Sensus Metering Systems +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.Modbus.CometAmbient +{ + public class Factory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(17); } } + + public void ResetStaticProperties() { Ambient.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new Ambient(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new Ambient(cfg, components); } + + public IComponentCfg DefaultConfig() { return new AmbientCfg(this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(AmbientCfg.Serializer, component, this); + } + } +} diff --git a/TestBenchFramework/BenchControl/TbfComponents.cs b/TestBenchFramework/BenchControl/TbfComponents.cs index 8a20b27e0..710c3bb7e 100644 --- a/TestBenchFramework/BenchControl/TbfComponents.cs +++ b/TestBenchFramework/BenchControl/TbfComponents.cs @@ -74,7 +74,8 @@ namespace TBF.BenchControl Factories.Add(new MettlerToledo.Standard.BalanceOldFactory()); /// MettlerToledoBalanceOld Factories.Add(new MettlerToledo.Standard.BalanceNewFactory()); /// MettlerToledoBalanceSN Factories.Add(new MettlerToledo.Multi.BalanceFactory()); /// MettlerToledo-Multi - Factories.Add(new Modbus.Common.Factory()); /// Modbus + Factories.Add(new Modbus.CometAmbient.Factory()); /// Modbus.CometAmbient.Ambient + Factories.Add(new Modbus.Common.Factory()); /// Modbus Factories.Add(new Modbus.Easytherm.Factory()); /// Modbus.Easytherm Factories.Add(new Modbus.PressureMeter.Meret.Factory()); /// Modbus.PressureMeter.Meret - Meret pressure meter connected via modbus Factories.Add(new Modbus.QuidoRS.Factory()); /// Modbus.QuidoRS diff --git a/TestBenchFramework/Properties/AssemblyInfo.cs b/TestBenchFramework/Properties/AssemblyInfo.cs index e87592da2..5d5e6d386 100644 --- a/TestBenchFramework/Properties/AssemblyInfo.cs +++ b/TestBenchFramework/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.17.677.1")] -[assembly: AssemblyFileVersion("2.17.677.1")] +[assembly: AssemblyVersion("2.17.678.1")] +[assembly: AssemblyFileVersion("2.17.678.1")] diff --git a/TestBenchFramework/TBF.csproj b/TestBenchFramework/TBF.csproj index 4b04ad9da..2fe7b8389 100644 --- a/TestBenchFramework/TBF.csproj +++ b/TestBenchFramework/TBF.csproj @@ -568,6 +568,15 @@ + + + + UserControl + + + AmbientCfgCtrl.cs + + @@ -2092,6 +2101,9 @@ BalanceCfgCtrl.cs + + AmbientCfgCtrl.cs + ModbusCfgCtrl.cs