Refactorization : BenchControl -> Rig

This commit is contained in:
Milan Hanajik
2021-03-05 16:12:24 +01:00
parent 84c8ec26b6
commit 6cf3bd6160
1461 changed files with 6330 additions and 6330 deletions
+262
View File
@@ -0,0 +1,262 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using log4net;
using Common;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Boxes;
namespace TBF.Rig.Network.Comet.Ambient
{
/// <summary>
/// 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.
/// </summary>
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 myCfg;
readonly IPAddress ipAddress;
readonly int tcpPort;
TcpClient tcpClient;
NetworkStream networkStream;
enum State
{
Idle,
WaitingForTemperature,
WaitingForHumidity,
WaitingForPressure,
};
State state;
/// <summary>The state of the measurement</summary>
MsrmntState msrmntState;
///
/// Measured values when MsrmntState == MsrmntState.Valid
///
double temperature; /// [°C]
double pressure; /// [bar]
double humidity; /// [R%]
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
int msrmntTimeStamp;
public Ambient()
{
}
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
/// </summary>
public Ambient(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
myCfg = cfg as AmbientCfg;
if (myCfg == null) throw new ArgumentNullException("No configuration");
ipAddress = IPAddress.Parse(myCfg.IPAddress);
tcpPort = myCfg.TcpPort;
log.Warn(this.ToString());
}
public void Initialize()
{
if (myCfg.DebugLevel == DebugMode.Simulate)
{
temperature = 20.0;
humidity = 40.0;
pressure = 1.0;
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.FatalFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure);
return;
}
tcpClient = new TcpClient();
tcpClient.Connect(ipAddress, tcpPort);
networkStream = tcpClient.GetStream();
state = State.Idle;
msrmntState = MsrmntState.Busy;
log.FatalFormat("Initialization successful: {0}", this.ToString());
}
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
if (myCfg.DebugLevel == DebugMode.Simulate || myCfg.DebugLevel == DebugMode.FailureDuringOperation)
{
msrmntTimeStamp = StateMachine.Time;
return;
}
try
{
int available = tcpClient.Available;
if (available >= 11)
{
byte[] bytes = new byte[available];
networkStream.Read(bytes, 0, available);
log.Debug(Telegram.LogTelegram("Received ", bytes));
int value;
if (available == 11 && bytes[0] == 0 && bytes[2] == 0 && bytes[3] == 0 && bytes[4] == 0
&& bytes[5] == 5 && bytes[6] == 1 && bytes[7] == 3 && bytes[8] == 2)
{
switch (state)
{
case State.WaitingForTemperature:
value = (int)bytes[9] * 256 + (int)bytes[10];
temperature = value / 10.0; /// Conversion to °C
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.InfoFormat("Ambient temperature = {0:F1} C", temperature);
state = State.Idle;
break;
case State.WaitingForHumidity:
value = (int)bytes[9] * 256 + (int)bytes[10];
humidity = value / 10.0; /// Conversion to R%
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.InfoFormat("Ambient humidity = {0:F1} %", humidity);
state = State.Idle;
break;
case State.WaitingForPressure:
value = (int)bytes[9] * 256 + (int)bytes[10];
pressure = value / 10000.0; /// Conversion to bar
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.InfoFormat("Ambient pressure = {0:F0} mbar", 1000 * pressure);
state = State.Idle;
break;
}
}
else
{
state = State.Idle;
}
}
}
catch (Exception e)
{
DebugLevel = DebugMode.FailureDuringOperation;
log.FatalFormat("Ambient: Serail port read failure : {0}", e.Message);
if (e.InnerException != null)
{
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
}
}
}
/// <summary>Run this device</summary>
public void RunDeviceAfter()
{
if (myCfg.DebugLevel == DebugMode.Simulate || myCfg.DebugLevel == DebugMode.FailureDuringOperation)
{
return;
}
try
{
/// 20 seconds cycle
byte[] message = null;
switch (StateMachine.Time % 20)
{
case 0:
state = State.WaitingForTemperature;
message = new byte[12] { 0, 0, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x30, 0, 0x01 };
break;
case 6:
state = State.WaitingForHumidity;
message = new byte[12] { 0, 0x02, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x31, 0, 0x01 };
break;
case 12:
state = State.WaitingForPressure;
message = new byte[12] { 0, 0x03, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x33, 0, 0x01 };
break;
}
if (message != null)
{
log.Debug(Telegram.LogTelegram("Sending ", message));
networkStream.Write(message, 0, message.Length); /// Read request
}
}
catch (Exception e)
{
DebugLevel = DebugMode.FailureDuringOperation;
log.FatalFormat("TCP/IP write error : {0}", e.Message);
if (e.InnerException != null)
{
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
}
}
}
/// <summary>Stop this device</summary>
public void StopDevice()
{
if (myCfg.DebugLevel != DebugMode.Simulate && myCfg.DebugLevel != DebugMode.FailureDuringOperation)
{
networkStream.Close();
tcpClient.Close();
}
}
public void StopDevice2() { }
///
/// Boxes for the operation result
///
DoubleBox tempBox;
DoubleBox pressureBox;
DoubleBox humiBox;
public IOperation ReadAmbientOp(DoubleBox tempBox, DoubleBox pressureBox, DoubleBox humiBox)
{
this.tempBox = tempBox;
this.pressureBox = pressureBox;
this.humiBox = humiBox;
return this;
}
/// <summary>Start this operation</summary>
public void Start()
{
if (tempBox != null) tempBox.Val = temperature;
if (pressureBox != null) pressureBox.Val = pressure;
if (humiBox != null) humiBox.Val = humidity;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (tempBox != null) tempBox.Val = temperature;
if (pressureBox != null) pressureBox.Val = pressure;
if (humiBox != null) humiBox.Val = humidity;
return Event.AmbientDone;
}
/// <summary>Stop this operation</summary>
public void Stop() { }
}
}
@@ -0,0 +1,45 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Net;
using System.Collections.Generic;
using System.Xml.Serialization;
using Config.Entities;
using TBF.Rig.Generic;
namespace TBF.Rig.Network.Comet.Ambient
{
public class AmbientCfg : ComponentCfgBase, IComponentCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(AmbientCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new AmbientCfgCtrl(); }
///
/// Serialized parameters
///
public string IPAddress;
public int TcpPort;
public string SerialNr;
/// Private parameterless constructor invoked by all other (public) constructors
AmbientCfg() { }
public AmbientCfg(string name, IComponentFactory factory)
: this()
{
this.Name = name;
this.Factory = factory;
IPAddress = "192.168.0.123";
TcpPort = 502;
SerialNr = string.Empty;
}
public string ToString(int i)
{
return string.Format("Name={0}, IP={1}, Port={2}, s/n={3}", Name, IPAddress, TcpPort, SerialNr);
}
}
}
+157
View File
@@ -0,0 +1,157 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
namespace TBF.Rig.Network.Comet.Ambient
{
partial class AmbientCfgCtrl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.serialNrTextBox = new System.Windows.Forms.TextBox();
this.serialNrLabel = new System.Windows.Forms.Label();
this.ipAddressLabel = new System.Windows.Forms.Label();
this.ipAddressTextBox = new System.Windows.Forms.TextBox();
this.tcpPortTextBox = new System.Windows.Forms.TextBox();
this.tcpPortLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(140, 43);
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(36, 46);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 1;
this.nameLabel.Text = "Name";
//
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(137, 18);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComonentName";
//
// serialNrTextBox
//
this.serialNrTextBox.Enabled = false;
this.serialNrTextBox.Location = new System.Drawing.Point(140, 121);
this.serialNrTextBox.Name = "serialNrTextBox";
this.serialNrTextBox.Size = new System.Drawing.Size(130, 20);
this.serialNrTextBox.TabIndex = 10;
//
// serialNrLabel
//
this.serialNrLabel.AutoSize = true;
this.serialNrLabel.Location = new System.Drawing.Point(36, 124);
this.serialNrLabel.Name = "serialNrLabel";
this.serialNrLabel.Size = new System.Drawing.Size(71, 13);
this.serialNrLabel.TabIndex = 9;
this.serialNrLabel.Text = "Serial number";
//
// ipAddressLabel
//
this.ipAddressLabel.AutoSize = true;
this.ipAddressLabel.Location = new System.Drawing.Point(36, 72);
this.ipAddressLabel.Name = "ipAddressLabel";
this.ipAddressLabel.Size = new System.Drawing.Size(58, 13);
this.ipAddressLabel.TabIndex = 5;
this.ipAddressLabel.Text = "IP Address";
//
// ipAddressTextBox
//
this.ipAddressTextBox.Enabled = false;
this.ipAddressTextBox.Location = new System.Drawing.Point(140, 69);
this.ipAddressTextBox.Name = "ipAddressTextBox";
this.ipAddressTextBox.Size = new System.Drawing.Size(130, 20);
this.ipAddressTextBox.TabIndex = 6;
//
// tcpPortTextBox
//
this.tcpPortTextBox.Enabled = false;
this.tcpPortTextBox.Location = new System.Drawing.Point(140, 95);
this.tcpPortTextBox.Name = "tcpPortTextBox";
this.tcpPortTextBox.Size = new System.Drawing.Size(130, 20);
this.tcpPortTextBox.TabIndex = 8;
//
// tcpPortLabel
//
this.tcpPortLabel.AutoSize = true;
this.tcpPortLabel.Location = new System.Drawing.Point(36, 98);
this.tcpPortLabel.Name = "tcpPortLabel";
this.tcpPortLabel.Size = new System.Drawing.Size(65, 13);
this.tcpPortLabel.TabIndex = 7;
this.tcpPortLabel.Text = "TCP/IP Port";
//
// AmbientCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.Controls.Add(this.tcpPortTextBox);
this.Controls.Add(this.tcpPortLabel);
this.Controls.Add(this.ipAddressTextBox);
this.Controls.Add(this.ipAddressLabel);
this.Controls.Add(this.serialNrTextBox);
this.Controls.Add(this.serialNrLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Name = "AmbientCfgCtrl";
this.Size = new System.Drawing.Size(400, 254);
this.Load += new System.EventHandler(this.AbbientCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.TextBox serialNrTextBox;
private System.Windows.Forms.Label serialNrLabel;
private System.Windows.Forms.Label ipAddressLabel;
private System.Windows.Forms.TextBox ipAddressTextBox;
private System.Windows.Forms.TextBox tcpPortTextBox;
private System.Windows.Forms.Label tcpPortLabel;
}
}
@@ -0,0 +1,111 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Net;
using System.Windows.Forms;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Resources;
namespace TBF.Rig.Network.Comet.Ambient
{
public partial class AmbientCfgCtrl : UserControl, IComponentCfgCtrl
{
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 AbbientCfgCtrl_Load(object sender, EventArgs e)
{
Localize();
Redraw();
}
void Localize()
{
nameLabel.Text = Strings.Name;
serialNrLabel.Text = Strings.Serial_Number;
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
classNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
ipAddressTextBox.Text = config.IPAddress != null ? config.IPAddress.ToString() : "192.168.0.123";
tcpPortTextBox.Text = config.TcpPort.ToString();
serialNrTextBox.Text = config.SerialNr.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
ipAddressTextBox.Enabled = true;
tcpPortTextBox.Enabled = true;
serialNrTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
IPAddress ip;
if (!IPAddress.TryParse(ipAddressTextBox.Text, out ip))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + string.Format(Strings.Invalid_0, ipAddressLabel.Text);
}
int port;
if (!int.TryParse(tcpPortTextBox.Text, out port) || port < 0 || port > 65535)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + string.Format(Strings.Invalid_0, tcpPortLabel.Text);
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
if (config.Name != nameTextBox.Text ||
config.IPAddress != ipAddressTextBox.Text ||
config.TcpPort.ToString() != tcpPortTextBox.Text ||
config.SerialNr != serialNrTextBox.Text)
{
config.Name = nameTextBox.Text;
config.IPAddress = ipAddressTextBox.Text;
config.TcpPort = int.Parse(tcpPortTextBox.Text);
config.SerialNr = serialNrTextBox.Text;
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
}
return flags;
}
}
}
@@ -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>
+27
View File
@@ -0,0 +1,27 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.Network.Comet.Ambient
{
public class Factory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public void ResetStaticProperties() { Ambient.ResetStaticProperties(); }
public IComponent DummyComponent() { return new Ambient(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Ambient(cfg, components); }
public IComponentCfg DefaultConfig() { return new AmbientCfg(this.GetType().Namespace.Substring(8), this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(AmbientCfg.Serializer, component, this);
}
}
}