Refactorization : BenchControl -> Rig
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Adapter
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Netadapter.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Netadapter(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Netadapter(cfg); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new NetadapterCfg(this.GetType().Namespace.Substring(8), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(NetadapterCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Net;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.Network.Adapter
|
||||
{
|
||||
public class Netadapter : ComponentBase, GenericDevices.INetworkAdapter
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Netadapter));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Component={0} IPAddress={1} NetMask={2} Description={3}", Cfg.Name, IPAddress, NetMask, (Cfg as NetadapterCfg).Description);
|
||||
}
|
||||
|
||||
public bool Running { get { return running; } }
|
||||
bool running;
|
||||
|
||||
readonly NetadapterCfg netadapterCfg;
|
||||
readonly IPAddress ipAddress;
|
||||
readonly IPAddress netMask;
|
||||
readonly IPAddress broadcastAddress;
|
||||
|
||||
public IPAddress IPAddress { get { return ipAddress; } }
|
||||
public IPAddress NetMask { get { return netMask; } }
|
||||
public IPAddress BroadcastAddress { get { return broadcastAddress; } }
|
||||
|
||||
public Netadapter()
|
||||
{
|
||||
}
|
||||
|
||||
public Netadapter(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
netadapterCfg = cfg as NetadapterCfg;
|
||||
AdapterInfo.RefreshNetAdaptersInfo();
|
||||
AdapterInfo netadapter = AdapterInfo.GetNetAdapter(netadapterCfg.Description);
|
||||
ipAddress = netadapter.IPAddress;
|
||||
netMask = netadapter.NetMask;
|
||||
broadcastAddress = netadapter.GetBroadcastAddress();
|
||||
|
||||
running = false;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Adapter
|
||||
{
|
||||
public class NetadapterCfg : ComponentCfgBase, Generic.IComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(NetadapterCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new NetadapterCfgCtrl(); }
|
||||
|
||||
|
||||
public string Description; /// Description string of the selected network adapter
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
NetadapterCfg() {}
|
||||
|
||||
public NetadapterCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, Description={1}", Name, Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Adapter
|
||||
{
|
||||
public partial class NetadapterCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
NetadapterCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as NetadapterCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public NetadapterCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void EntryFormCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (ParentForm == null) return; /// Return is executed when tab page is open in Designer
|
||||
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||
|
||||
Localize();
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void Redraw()
|
||||
{
|
||||
classNameLabel.Text = config.Factory.ClassName;
|
||||
nameTextBox.Text = config.Name;
|
||||
|
||||
AdapterInfo.RefreshNetAdaptersInfo();
|
||||
IList<AdapterInfo> adapters = AdapterInfo.NetAdapters;
|
||||
|
||||
string cfgAdapter = string.Empty;
|
||||
foreach (AdapterInfo ai in adapters)
|
||||
{
|
||||
string record;
|
||||
|
||||
if (ai.IPAddress == null)
|
||||
{
|
||||
/// This happens with network adapters that currently have no IP address,
|
||||
/// for instance not connected wireless or dial-up adapters
|
||||
record = "???.???.???.???";
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Do not consider IPv6 adapters as well as "Any", "Broadcast", "Loopback" or "None" addresses
|
||||
if ((ai.IPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) ||
|
||||
ai.IPAddress.Equals(IPAddress.Any) ||
|
||||
ai.IPAddress.Equals(IPAddress.Broadcast) ||
|
||||
ai.IPAddress.Equals(IPAddress.IPv6Any) ||
|
||||
ai.IPAddress.Equals(IPAddress.IPv6Loopback) ||
|
||||
ai.IPAddress.Equals(IPAddress.IPv6None) ||
|
||||
ai.IPAddress.Equals(IPAddress.Loopback) ||
|
||||
ai.IPAddress.Equals(IPAddress.None))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
record = ai.IPAddress.ToString();
|
||||
}
|
||||
|
||||
record += " - " + ai.Description;
|
||||
int i = adapterComboBox.Items.Add(record);
|
||||
if (ai.Description == config.Description)
|
||||
{
|
||||
/// Select the adapter currently in the configuration
|
||||
adapterComboBox.SelectedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
/// Select the first one if the adapter from the configuration does not exist on the system
|
||||
if (adapterComboBox.SelectedIndex < 0 && adapterComboBox.Items.Count > 0)
|
||||
{
|
||||
adapterComboBox.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Localize()
|
||||
{
|
||||
}
|
||||
|
||||
public void Closing()
|
||||
{
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
adapterComboBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (!adapterComboBox.Items.Contains(adapterComboBox.Text))
|
||||
{
|
||||
flags = CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Parent Name'";
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/// Network adapter
|
||||
string strAdapter = adapterComboBox.Text;
|
||||
int iDash = strAdapter.IndexOf(" - ");
|
||||
config.Description = iDash < 0 ? "" : strAdapter.Substring(iDash + 3);
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Adapter
|
||||
{
|
||||
partial class NetadapterCfgCtrl
|
||||
{
|
||||
/// <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.adapterLabel = new System.Windows.Forms.Label();
|
||||
this.adapterComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(101, 50);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(114, 20);
|
||||
this.nameTextBox.TabIndex = 5;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(9, 53);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 4;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(98, 24);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 3;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// adapterLabel
|
||||
//
|
||||
this.adapterLabel.AutoSize = true;
|
||||
this.adapterLabel.Location = new System.Drawing.Point(9, 80);
|
||||
this.adapterLabel.Name = "adapterLabel";
|
||||
this.adapterLabel.Size = new System.Drawing.Size(44, 13);
|
||||
this.adapterLabel.TabIndex = 6;
|
||||
this.adapterLabel.Text = "Adapter";
|
||||
//
|
||||
// adapterComboBox
|
||||
//
|
||||
this.adapterComboBox.Enabled = false;
|
||||
this.adapterComboBox.Location = new System.Drawing.Point(101, 77);
|
||||
this.adapterComboBox.Name = "adapterComboBox";
|
||||
this.adapterComboBox.Size = new System.Drawing.Size(333, 21);
|
||||
this.adapterComboBox.TabIndex = 7;
|
||||
//
|
||||
// NetadapterCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.adapterComboBox);
|
||||
this.Controls.Add(this.adapterLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "NetadapterCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(450, 300);
|
||||
this.Load += new System.EventHandler(this.EntryFormCfgCtrl_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.Label adapterLabel;
|
||||
private System.Windows.Forms.ComboBox adapterComboBox;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
namespace TBF.Rig.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for the storing information about a network adapter.
|
||||
/// </summary>
|
||||
public class AdapterInfo
|
||||
{
|
||||
public string Description; /// Description of the network adapter.
|
||||
public IPAddress IPAddress; /// IP address of the network adapter.
|
||||
public IPAddress NetMask; /// Mask of the network adapter.
|
||||
|
||||
/// Constructor
|
||||
public AdapterInfo(string description)
|
||||
{
|
||||
Description = description;
|
||||
}
|
||||
|
||||
/// Member function
|
||||
public IPAddress GetBroadcastAddress()
|
||||
{
|
||||
return AdapterInfo.GetBroadcastAddress(IPAddress, NetMask);
|
||||
}
|
||||
|
||||
/// Static function
|
||||
static public IPAddress GetBroadcastAddress(IPAddress ipAddress, IPAddress netMask)
|
||||
{
|
||||
byte[] ipAdressBytes = ipAddress.GetAddressBytes();
|
||||
byte[] subnetMaskBytes = netMask.GetAddressBytes();
|
||||
|
||||
if (ipAdressBytes.Length != subnetMaskBytes.Length)
|
||||
{
|
||||
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
|
||||
}
|
||||
|
||||
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
|
||||
for (int i = 0; i < broadcastAddress.Length; i++)
|
||||
{
|
||||
broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
|
||||
}
|
||||
|
||||
return new IPAddress(broadcastAddress);
|
||||
}
|
||||
|
||||
///------------------------------------------------------
|
||||
/// Static members and functions
|
||||
///------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Private list of the available network adapters.
|
||||
/// </summary>
|
||||
static List<AdapterInfo> netAdapters;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the list of network adapters.
|
||||
/// Never returns 'null', calls RefreshNetAdaptersInfo() the first time it is used.
|
||||
/// If you want to refresh the list of the network adapters later, explicitly call
|
||||
/// the RefreshNetAdaptersInfo() method.
|
||||
/// </summary>
|
||||
public static List<AdapterInfo> NetAdapters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (netAdapters == null) RefreshNetAdaptersInfo();
|
||||
return netAdapters;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the information about network adapters stored in the netAdapters list.
|
||||
/// </summary>
|
||||
public static void RefreshNetAdaptersInfo()
|
||||
{
|
||||
if (netAdapters == null) netAdapters = new List<AdapterInfo>();
|
||||
else netAdapters.Clear();
|
||||
|
||||
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
|
||||
foreach (NetworkInterface adapter in nics)
|
||||
{
|
||||
AdapterInfo info = new AdapterInfo(adapter.Description);
|
||||
netAdapters.Add(info);
|
||||
|
||||
IPInterfaceProperties properties = adapter.GetIPProperties();
|
||||
if (properties == null)
|
||||
continue;
|
||||
UnicastIPAddressInformationCollection uniCast = properties.UnicastAddresses;
|
||||
if (uniCast == null)
|
||||
continue;
|
||||
foreach (UnicastIPAddressInformation uni in uniCast)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
info = new AdapterInfo(adapter.Description);
|
||||
netAdapters.Add(info);
|
||||
}
|
||||
info.IPAddress = uni.Address;
|
||||
if (uni.IPv4Mask != null) info.NetMask = uni.IPv4Mask;
|
||||
info = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the loopback network adapter.
|
||||
/// </summary>
|
||||
public static AdapterInfo LoopbackAdapter
|
||||
{
|
||||
get
|
||||
{
|
||||
List<AdapterInfo> adapters = NetAdapters;
|
||||
foreach (AdapterInfo a in adapters)
|
||||
{
|
||||
if (a.IPAddress != null && a.IPAddress.Equals(IPAddress.Loopback)) return a;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default network adapter - the first one which his not a loopback adapter.
|
||||
/// Network adapters with IP address have preference, adapters without IP address
|
||||
/// (like an unconnected wireless adapter) are used just when there is no adapter with IP.
|
||||
///
|
||||
/// Default adapter is used when none was specified in the configuration file
|
||||
/// and it is used to initialize Options-General dialog-tab.
|
||||
/// </summary>
|
||||
public static AdapterInfo DefaultAdapter
|
||||
{
|
||||
get
|
||||
{
|
||||
List<AdapterInfo> adapters = NetAdapters; /// Make a copy to avoid interference
|
||||
AdapterInfo adapterWithoutIP = null; /// Use this one if there is no other better adapter
|
||||
foreach (AdapterInfo a in adapters)
|
||||
{
|
||||
if (!a.IPAddress.Equals(IPAddress.Loopback))
|
||||
{
|
||||
if (a.IPAddress != null) return a;
|
||||
else if (adapterWithoutIP == null) adapterWithoutIP = a;
|
||||
}
|
||||
}
|
||||
return adapterWithoutIP == null ? LoopbackAdapter : adapterWithoutIP;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get network adapter info from the description string.
|
||||
/// </summary>
|
||||
/// <param name="description">Description</param>
|
||||
/// <returns>AdapterInfo object reference</returns>
|
||||
public static AdapterInfo GetNetAdapter(string description)
|
||||
{
|
||||
List<AdapterInfo> adapters = NetAdapters;
|
||||
|
||||
foreach (AdapterInfo a in adapters)
|
||||
{
|
||||
if (a.Description != description ||
|
||||
a.IPAddress == null ||
|
||||
a.IPAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 ||
|
||||
a.IPAddress.Equals(IPAddress.Loopback) ||
|
||||
a.NetMask == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
return DefaultAdapter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the given string as URL parameter.
|
||||
/// </summary>
|
||||
/// <param name="pathToEncode">String to be encoded.</param>
|
||||
/// <returns>String encoded as the URL parameter.</returns>
|
||||
public static string UrlPathEncode(string pathToEncode)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(pathToEncode.Length * 3);
|
||||
|
||||
sb.Append(pathToEncode);
|
||||
|
||||
// % must be first!!!
|
||||
sb.Replace("%", "%" + Convert.ToInt32('%').ToString("X2"));
|
||||
// ?, & and / are not convertable by HttpUtility.UrlPathEncode
|
||||
sb.Replace("?", "%" + Convert.ToInt32('?').ToString("X2"));
|
||||
sb.Replace("&", "%" + Convert.ToInt32('&').ToString("X2"));
|
||||
sb.Replace("/", "%" + Convert.ToInt32('/').ToString("X2"));
|
||||
// Additional chars. E.g.: # didn't work in the path passed to the Uri class. "c:\\sour#ce\\my # proj".
|
||||
sb.Replace("#", "%" + Convert.ToInt32('#').ToString("X2"));
|
||||
// Backslash must be removed because it is not accepted by Uri class when passing path into it. E.g.: "C:%5Csource" is not acceptable.
|
||||
//sb.Replace("\\", "%" + Convert.ToInt32('\\').ToString("X2"));
|
||||
//// I removed following chars because I do not know if it is good idea to replace them (see previous line with '\\' char).
|
||||
sb.Replace("\r", "%" + Convert.ToInt32('\r').ToString("X2"));
|
||||
sb.Replace("\n", "%" + Convert.ToInt32('\n').ToString("X2"));
|
||||
sb.Replace("\t", "%" + Convert.ToInt32('\t').ToString("X2"));
|
||||
|
||||
string s = sb.ToString();
|
||||
s = HttpUtility.UrlPathEncode(s);
|
||||
//sb.Length = 0;
|
||||
//sb.Append(HttpUtility.UrlPathEncode(s));
|
||||
//for (int i = 0; i < sb.Length; i += 3)
|
||||
//{
|
||||
// char c = sb[i];
|
||||
// if (c == '%')
|
||||
// continue;
|
||||
// sb[i] = '%';
|
||||
// sb.Insert(i + 1, Convert.ToUInt64(c).ToString("X2"));
|
||||
//}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,839 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Timers;
|
||||
using log4net;
|
||||
using Renci.SshNet;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Network.Telnet;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements: (1) Camera device, (2) Measurement operation
|
||||
/// </summary>
|
||||
public class Camera : ComponentBase, GenericDevices.ICamera, Generic.IDevice, IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Camera));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}: Name={1}, Addr={2}, IP={3}, s/n={4}, SD={5}",
|
||||
this.GetType().Namespace.Substring(8),
|
||||
CameraCfg.Name,
|
||||
CameraCfg.HardwareAddress,
|
||||
CameraCfg.DebugLevel == DebugMode.Simulate ? "simulated" : ((ipAddress == null) ? "not detected" : ipAddress.ToString()),
|
||||
CameraCfg.DebugLevel == DebugMode.Simulate ? "simulated" : (string.IsNullOrEmpty(cpuSerialNr) ? "not detected" : cpuSerialNr),
|
||||
CameraCfg.DebugLevel == DebugMode.Simulate ? "simulated" : (string.IsNullOrEmpty(sdCardVer) ? "not detected" : sdCardVer));
|
||||
}
|
||||
|
||||
|
||||
string ClpUserName = string.Empty; /// Either "tbf" or "pi" after a successful detection
|
||||
const string ClpPassword = "C1ern4V0d4";
|
||||
|
||||
private static Object fileUploadLock = new Object();
|
||||
|
||||
|
||||
///
|
||||
/// Properties
|
||||
///
|
||||
public readonly CameraCfg CameraCfg;
|
||||
public readonly GenericDevices.INetworkAdapter NetAdapter;
|
||||
|
||||
public IPAddress IPAddress { get { return ipAddress; } }
|
||||
IPAddress ipAddress;
|
||||
|
||||
public string CpuHardware { get { return cpuHardware; } }
|
||||
string cpuHardware;
|
||||
|
||||
public string CpuRevision { get { return cpuRevision; } }
|
||||
string cpuRevision;
|
||||
|
||||
public string CpuSerialNr { get { return cpuSerialNr; } }
|
||||
string cpuSerialNr;
|
||||
|
||||
public string SDCardVer { get { return sdCardVer; } }
|
||||
string sdCardVer;
|
||||
|
||||
public bool Running { get { return running; } }
|
||||
bool running;
|
||||
|
||||
public int CameraIdx { get { return cameraIdx; } }
|
||||
int cameraIdx;
|
||||
///
|
||||
static int nextCameraIdx = 0;
|
||||
static int GetCameraIdx() { return nextCameraIdx++; } /// Used in Initialize()
|
||||
public static new void ResetStaticProperties() { nextCameraIdx = 0; }
|
||||
|
||||
///
|
||||
/// Telnet support
|
||||
///
|
||||
const string TelnetPrompt = "$ ";
|
||||
const bool TelnetSkipFirstLine = true;
|
||||
public Telnet.TelnetClient Telnet;
|
||||
private TerminalDlg terminalDlg;
|
||||
string sha1sumResponse;
|
||||
bool sha1sumResponseProcessed;
|
||||
|
||||
///
|
||||
/// scp support
|
||||
///
|
||||
Thread scpThread;
|
||||
PasswordConnectionInfo connectionInfo;
|
||||
bool scpConnected;
|
||||
bool stopScpThreadFlag;
|
||||
string scpRemoteFileName; /// Camera file name
|
||||
string scpLocalFileName; /// Local PC file name
|
||||
enum ScpCommand
|
||||
{
|
||||
None,
|
||||
Get,
|
||||
Put,
|
||||
}
|
||||
ScpCommand scpCommand;
|
||||
|
||||
|
||||
const int UdpPortBase = 20000; /// Port base for all UDP protocols
|
||||
|
||||
///
|
||||
/// MJpeg RTP protocol support
|
||||
///
|
||||
int rtpUdpLocalPort;
|
||||
UdpClient rtpUdpClient;
|
||||
Thread rtpListenerThread;
|
||||
static bool stopRtpListenerFlag;
|
||||
|
||||
///
|
||||
/// RTCP protocol (reserved)
|
||||
///
|
||||
int rtcpUdpLocalPort;
|
||||
|
||||
///
|
||||
/// Measurement results protocol
|
||||
///
|
||||
int msrmntUdpLocalPort;
|
||||
UdpClient msrmntUdpClient; /// If != null msrmntListenerThread
|
||||
Thread msrmntListenerThread;
|
||||
static bool stopMsrmntListenerFlag;
|
||||
|
||||
|
||||
///
|
||||
/// ROI related parameters
|
||||
///
|
||||
RoisAndResults roisAndResults;
|
||||
///
|
||||
public void ClearRoiParams() { roisAndResults.ClearRoiParams(); }
|
||||
public int RegisterRoi(string roiParams) { return roisAndResults.RegisterRoi(roiParams); }
|
||||
public int GetResult(int roiHandle, out long timeMs) { return roisAndResults.GetResult(roiHandle, out timeMs); }
|
||||
|
||||
|
||||
public Camera() {}
|
||||
|
||||
|
||||
public Camera(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
CameraCfg = cfg as CameraCfg;
|
||||
NetAdapter = TbfComponents.FindComponent(cfg.ParentName, components) as GenericDevices.INetworkAdapter;
|
||||
if (NetAdapter == null) throw new ArgumentNullException("no network adapter");
|
||||
|
||||
Telnet = null;
|
||||
terminalDlg = null;
|
||||
|
||||
roisAndResults = new RoisAndResults(); /// object for measurement results, writes/reads to/from this object are locked
|
||||
|
||||
running = false;
|
||||
}
|
||||
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
cameraIdx = GetCameraIdx();
|
||||
|
||||
if (CameraCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
UiBridge.Bridge.OnCameraInfo(this.cameraIdx, string.Format("{0} s/n {1} si simulated", Name, CameraCfg.HardwareAddress));
|
||||
return;
|
||||
}
|
||||
|
||||
/// Detect a camera
|
||||
bool cameraDetected = DetectCamera(CameraCfg.HardwareAddress % 100, ref ipAddress, true,
|
||||
out cpuHardware, out cpuRevision, out cpuSerialNr, out sdCardVer);
|
||||
|
||||
if (CameraCfg.DebugLevel == DebugMode.AutoDetect)
|
||||
{
|
||||
CameraCfg.DebugLevel = cameraDetected ? DebugMode.DetectedOn : DebugMode.DetectedOff;
|
||||
}
|
||||
else if (!cameraDetected)
|
||||
{
|
||||
throw new Exception(string.Format("{0}={1}", Strings.Address, CameraCfg.HardwareAddress));
|
||||
}
|
||||
|
||||
if (cameraDetected)
|
||||
{
|
||||
UiBridge.Bridge.OnCameraInfo(this.cameraIdx, string.Format("{0} ver.{1} {2} s/n {3}", Name, sdCardVer, ipAddress, CameraCfg.HardwareAddress));
|
||||
|
||||
ClpUserName = (sdCardVer.Length > 0 && sdCardVer[0] == '1') ? "tbf" : "pi";
|
||||
|
||||
rtpUdpLocalPort = UdpPortBase + 4 * cameraIdx;
|
||||
rtcpUdpLocalPort = UdpPortBase + 4 * cameraIdx + 1;
|
||||
msrmntUdpLocalPort = UdpPortBase + 4 * cameraIdx + 2;
|
||||
|
||||
StartRtpListener(NetAdapter.IPAddress, rtpUdpLocalPort);
|
||||
StartMsrmntListener(NetAdapter.IPAddress, msrmntUdpLocalPort);
|
||||
|
||||
connectionInfo = new PasswordConnectionInfo(IPAddress.ToString(), ClpUserName, ClpPassword);
|
||||
|
||||
/// Open telnet clint and start the log-in process
|
||||
Telnet = new Telnet.TelnetClient(this, CameraCfg.Name, ClpUserName, ClpPassword, TelnetPrompt, TelnetSkipFirstLine, CameraCfg.DisplayTerminal);
|
||||
|
||||
Telnet.promptReceivedHandler += delegate(object sndr, PromptReceivedEventArgs a)
|
||||
{
|
||||
OnPromptReceived(sndr, a);
|
||||
};
|
||||
|
||||
if (CameraCfg.DisplayTerminal)
|
||||
{
|
||||
terminalDlg = new TerminalDlg(CameraCfg.Name, Telnet);
|
||||
terminalDlg.Show();
|
||||
}
|
||||
|
||||
Telnet.Enqueue(new Telnet.Command(Network.Telnet.CmdAction.CONNECT, ipAddress.ToString(), 10, 30));
|
||||
Telnet.Enqueue(new Telnet.Command(Network.Telnet.CmdAction.CLEAR_RESPONSE));
|
||||
Telnet.Enqueue(new Telnet.Command(Network.Telnet.CmdAction.SEND_COMMAND, "sha1sum clp/*"));
|
||||
|
||||
log.FatalFormat("'{0}' with address {1} detected, IP = {2}, SD = {3}", Name, CameraCfg.HardwareAddress, ipAddress, sdCardVer);
|
||||
}
|
||||
else
|
||||
{
|
||||
UiBridge.Bridge.OnCameraInfo(this.cameraIdx, string.Format("{0} s/n {1} was not detected", Name, CameraCfg.HardwareAddress));
|
||||
log.FatalFormat("'{0}' with address {1} not detected", Name, CameraCfg.HardwareAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopDevice()
|
||||
{
|
||||
if ((CameraCfg.DebugLevel != DebugMode.Simulate) && (CameraCfg.DebugLevel != DebugMode.DetectedOff))
|
||||
{
|
||||
running = false;
|
||||
|
||||
stopScpThreadFlag = true;
|
||||
stopRtpListenerFlag = true;
|
||||
stopMsrmntListenerFlag = true;
|
||||
|
||||
if (Telnet != null)
|
||||
{
|
||||
Telnet.Dispose();
|
||||
Telnet = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void StopDevice2()
|
||||
{
|
||||
if ((CameraCfg.DebugLevel != DebugMode.Simulate) && (CameraCfg.DebugLevel != DebugMode.DetectedOff))
|
||||
{
|
||||
if (scpThread != null) scpThread.Join(50);
|
||||
if (rtpListenerThread != null) rtpListenerThread.Join(50);
|
||||
if (msrmntListenerThread != null) msrmntListenerThread.Join(50);
|
||||
|
||||
if (rtpUdpClient != null)
|
||||
{
|
||||
rtpUdpClient.Close();
|
||||
rtpUdpClient = null;
|
||||
}
|
||||
|
||||
if (msrmntUdpClient != null)
|
||||
{
|
||||
msrmntUdpClient.Close();
|
||||
msrmntUdpClient = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if ((CameraCfg.DebugLevel != DebugMode.Simulate) && (CameraCfg.DebugLevel != DebugMode.DetectedOff))
|
||||
{
|
||||
if (sha1sumResponse != null && !sha1sumResponseProcessed)
|
||||
{
|
||||
scpThread = new Thread(new ThreadStart(ScpWorker));
|
||||
scpThread.Start();
|
||||
|
||||
sha1sumResponseProcessed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void RunDeviceAfter() { }
|
||||
|
||||
|
||||
void OnPromptReceived(object sndr, PromptReceivedEventArgs a)
|
||||
{
|
||||
if (sha1sumResponse == null)
|
||||
{
|
||||
sha1sumResponse = a.Response;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Configuration Change Handling
|
||||
|
||||
public static void OnCfgChange(object sender, CfgChangeArgs args)
|
||||
{
|
||||
if (CfgChangeHandler == null) return;
|
||||
try { CfgChangeHandler(sender, args); }
|
||||
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
|
||||
}
|
||||
|
||||
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
|
||||
|
||||
public override void StartChangeHandler()
|
||||
{
|
||||
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
|
||||
{
|
||||
CameraCfg tmpcfg = args.Cfg as CameraCfg;
|
||||
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
|
||||
{
|
||||
if (args.Command == CfgChangeCmd.CfgChange)
|
||||
{
|
||||
CameraCfg.TestImagesMode = tmpcfg.TestImagesMode;
|
||||
CameraCfg.TestImagesCount = tmpcfg.TestImagesCount;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Configuration Change Handling
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Detect the camera with specified hardware address (DIP switches).
|
||||
/// Optionally set camera date and time.
|
||||
/// </summary>
|
||||
/// <param name="hwAddress">Hardware address (DIP switches)</param>
|
||||
/// <param name="setDateTime">true = Broadcast 'SetDateTime' to all cameras</param>
|
||||
/// <param name="ipAddress">Detected IP address</param>
|
||||
/// <param name="hardware">Detected hardware</param>
|
||||
/// <param name="revision">Detected HW revision</param>
|
||||
/// <param name="serial">Detected serial number</param>
|
||||
/// <param name="sdCardVer">Detected OS image</param>
|
||||
/// <returns>true when camera detected successfully</returns>
|
||||
bool DetectCamera(int hwAddress, ref IPAddress ipAddress, bool setDateTime, out string hardware, out string revision, out string serial, out string sdCardVer)
|
||||
{
|
||||
for (int trials = 1; trials <= 3; trials++)
|
||||
{
|
||||
UdpClient udpClient = new UdpClient();
|
||||
|
||||
try
|
||||
{
|
||||
if (setDateTime)
|
||||
{
|
||||
SetDateTime(udpClient, DateTime.Now);
|
||||
}
|
||||
|
||||
///
|
||||
/// Send a request for camera information
|
||||
///
|
||||
DateTime detectionStart = DateTime.Now;
|
||||
CameraInfoRequest(udpClient, hwAddress);
|
||||
|
||||
///
|
||||
/// Receive a response or timeout
|
||||
///
|
||||
IAsyncResult asyncRslt = udpClient.BeginReceive(null, null);
|
||||
if (asyncRslt.AsyncWaitHandle.WaitOne(500))
|
||||
{
|
||||
/// Response received within time limit
|
||||
IPEndPoint cameraIPEndpoint = new IPEndPoint(IPAddress.Any, 1852);
|
||||
byte[] inputBuffer = udpClient.EndReceive(asyncRslt, ref cameraIPEndpoint);
|
||||
|
||||
double duration_ms = (DateTime.Now - detectionStart).TotalMilliseconds;
|
||||
ipAddress = cameraIPEndpoint.Address;
|
||||
|
||||
udpClient.Close();
|
||||
|
||||
string response = Encoding.ASCII.GetString(inputBuffer, 0, inputBuffer.Length);
|
||||
string[] strArr = response.Split(new char[] { ' ', '=' });
|
||||
if (strArr.Length == 10 && strArr[0] == "Address" && strArr[2] == "Hardware" &&
|
||||
strArr[4] == "Revision" && strArr[6] == "Serial" && strArr[8] == "Image")
|
||||
{
|
||||
hardware = strArr[3];
|
||||
revision = strArr[5];
|
||||
serial = strArr[7];
|
||||
sdCardVer = strArr[9];
|
||||
}
|
||||
else if (strArr.Length == 8 && strArr[0] == "Address" && strArr[2] == "Hardware" &&
|
||||
strArr[4] == "Revision" && strArr[6] == "Serial")
|
||||
{
|
||||
hardware = strArr[3];
|
||||
revision = strArr[5];
|
||||
serial = strArr[7];
|
||||
sdCardVer = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string msg = string.Format("Camera {0} detected in {1} ms: HWAddress={2} IPAddress={3} {4}",
|
||||
CameraCfg.Name,
|
||||
duration_ms,
|
||||
CameraCfg.HardwareAddress,
|
||||
ipAddress == null ? "not detected" : ipAddress.ToString(),
|
||||
response);
|
||||
log.Debug(msg);
|
||||
Console.WriteLine(msg);
|
||||
|
||||
return true; /// Camera detected
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
log.ErrorFormat("Camera {0} with HWAddress={1} not detected : {2}", CameraCfg.Name, CameraCfg.HardwareAddress, exc.Message);
|
||||
}
|
||||
|
||||
udpClient.Close();
|
||||
}
|
||||
|
||||
ipAddress = null;
|
||||
hardware = null;
|
||||
revision = null;
|
||||
serial = null;
|
||||
sdCardVer = null;
|
||||
return false; /// No camera detected
|
||||
}
|
||||
|
||||
void CameraInfoRequest(UdpClient udpClient, int hardwareAddress)
|
||||
{
|
||||
string strToSend = string.Format("getinfo {0}", hardwareAddress);
|
||||
byte[] dataToSend = Encoding.ASCII.GetBytes(strToSend);
|
||||
udpClient.Send(dataToSend, dataToSend.Length, new IPEndPoint(NetAdapter.BroadcastAddress, 1852));
|
||||
}
|
||||
|
||||
void SetDateTime(UdpClient udpClient, DateTime dateTime)
|
||||
{
|
||||
string strToSend = string.Format("setdatetime {0:yyMMddHHmmss}", dateTime);
|
||||
byte[] dataToSend = Encoding.ASCII.GetBytes(strToSend);
|
||||
udpClient.Send(dataToSend, dataToSend.Length, new IPEndPoint(NetAdapter.BroadcastAddress, 1852));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ScpWorker()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var scpClient = new ScpClient(connectionInfo))
|
||||
{
|
||||
scpClient.Connect();
|
||||
|
||||
DirectoryInfo dirInfo = null;
|
||||
if (sdCardVer.Length > 0)
|
||||
{
|
||||
switch (sdCardVer[0])
|
||||
{
|
||||
case '1':
|
||||
dirInfo = new DirectoryInfo(Path.Combine(System.Windows.Forms.Application.StartupPath, "CameraBinaryFiles"));
|
||||
break;
|
||||
case '2':
|
||||
dirInfo = new DirectoryInfo(Path.Combine(System.Windows.Forms.Application.StartupPath, "CameraBinaryFiles2"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirInfo != null)
|
||||
{
|
||||
///
|
||||
/// Synchronize files in camera /home/tbf/clp directory with the files in "TBF/CameraBinaryFiles" project folder
|
||||
///
|
||||
using (var sshClient = new SshClient(connectionInfo))
|
||||
{
|
||||
sshClient.Connect();
|
||||
|
||||
SHA1 sha1calculator = SHA1.Create();
|
||||
StringBuilder sha1str = new StringBuilder();
|
||||
|
||||
FileInfo[] fileInfos = dirInfo.GetFiles();
|
||||
foreach (FileInfo fi in fileInfos)
|
||||
{
|
||||
lock (fileUploadLock)
|
||||
{
|
||||
FileStream fs = fi.Open(FileMode.Open);
|
||||
fs.Position = 0;
|
||||
byte[] sha1 = sha1calculator.ComputeHash(fs);
|
||||
fs.Close();
|
||||
|
||||
sha1str.Clear();
|
||||
foreach (var b in sha1) sha1str.Append(b.ToString("x2"));
|
||||
|
||||
if (!sha1sumResponse.Contains(string.Format("{0} clp/{1}", sha1str, fi.Name)))
|
||||
{
|
||||
/// Copy a file to the camera if SHA1 sum is different of the file is missing
|
||||
log.InfoFormat("{0}, IP={1}, Uploading file {2}", Name, IPAddress, fi.Name);
|
||||
scpClient.Upload(fi, string.Format("~/clp/{0}", fi.Name));
|
||||
}
|
||||
}
|
||||
|
||||
if (!sha1sumResponse.Contains(fi.Name))
|
||||
{
|
||||
/// Change file properties if it was a new file
|
||||
string command = string.Format("chmod 755 ~/clp/{0}", fi.Name);
|
||||
log.InfoFormat("{0}, IP={1}, Executing command '{2}'", Name, IPAddress, command);
|
||||
sshClient.CreateCommand(command).Execute();
|
||||
|
||||
//if (fi.Name.Equals("runmeonce"))
|
||||
//{
|
||||
// log.InfoFormat("{0}, IP={1}, Executing command 'sudo clp/runmeonce'", Name, IPAddress);
|
||||
// sshClient.CreateCommand("sudo clp/runmeonce").Execute();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scpConnected = scpClient.IsConnected;
|
||||
running = true;
|
||||
|
||||
///
|
||||
/// Run SCP command loop
|
||||
///
|
||||
while (scpConnected && !stopScpThreadFlag)
|
||||
{
|
||||
switch (scpCommand)
|
||||
{
|
||||
case ScpCommand.Get:
|
||||
scpCommand = ScpCommand.None;
|
||||
scpClient.Download(scpRemoteFileName, new System.IO.FileInfo(scpLocalFileName));
|
||||
break;
|
||||
|
||||
case ScpCommand.Put:
|
||||
scpCommand = ScpCommand.None;
|
||||
scpClient.Upload(new System.IO.FileInfo(scpLocalFileName), scpRemoteFileName);
|
||||
break;
|
||||
|
||||
default:
|
||||
Thread.Sleep(250);
|
||||
break;
|
||||
}
|
||||
|
||||
scpConnected = scpClient.IsConnected;
|
||||
}
|
||||
|
||||
running = false;
|
||||
scpClient.Disconnect();
|
||||
scpConnected = false;
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
log.ErrorFormat( "Exception in {0} ScpWorker(): {1}", Name, exc.Message);
|
||||
if (exc.InnerException != null)
|
||||
{
|
||||
log.ErrorFormat(" Inner exception: {0}", exc.InnerException.Message);
|
||||
}
|
||||
|
||||
scpConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download a file from the camera via SCP
|
||||
/// </summary>
|
||||
/// <param name="srcFileName"></param>
|
||||
/// <returns>0 (success), -1 (busy), -2 (no session)</returns>
|
||||
public int DownloadFile(string srcFileName, string dstFileName)
|
||||
{
|
||||
if (!scpConnected) return -2;
|
||||
if (scpCommand != ScpCommand.None) return -1;
|
||||
|
||||
scpRemoteFileName = srcFileName;
|
||||
scpLocalFileName = dstFileName;
|
||||
scpCommand = ScpCommand.Get;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload a file to the camera via SCP
|
||||
/// </summary>
|
||||
/// <param name="srcFileName"></param>
|
||||
/// <returns>0 (success), -1 (busy), -2 (no session)</returns>
|
||||
public int UploadFile(string srcFileName, string dstFileName)
|
||||
{
|
||||
if (!scpConnected) return -2;
|
||||
if (scpCommand != ScpCommand.None) return -1;
|
||||
|
||||
scpLocalFileName = srcFileName;
|
||||
scpRemoteFileName = dstFileName;
|
||||
scpCommand = ScpCommand.Put;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private void StartRtpListener(IPAddress localIP, int localPort)
|
||||
{
|
||||
rtpUdpClient = new UdpClient(new IPEndPoint(localIP, localPort));
|
||||
rtpListenerThread = new Thread(new ThreadStart(RtpListener));
|
||||
rtpListenerThread.Start();
|
||||
}
|
||||
|
||||
void RtpListener()
|
||||
{
|
||||
JpegFrame jpegFrame = new JpegFrame();
|
||||
bool synced = false;
|
||||
|
||||
while (!stopRtpListenerFlag)
|
||||
{
|
||||
try
|
||||
{
|
||||
IPEndPoint endpoint = null;
|
||||
Byte[] data = rtpUdpClient.Receive(ref endpoint);
|
||||
|
||||
if (data.Length > 20)
|
||||
{
|
||||
/// Process the packet
|
||||
RtpPacket newPacket = new RtpPacket(data);
|
||||
if (synced)
|
||||
{
|
||||
/// Sychronized: process the new packet
|
||||
switch (jpegFrame.AddPacket(newPacket))
|
||||
{
|
||||
case RtpFrame.STATE.Complete:
|
||||
UiBridge.Bridge.OnImage(this.cameraIdx, jpegFrame.ToImage());
|
||||
jpegFrame.Clear();
|
||||
break;
|
||||
case RtpFrame.STATE.Error:
|
||||
jpegFrame.Clear();
|
||||
synced = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (newPacket.Mark)
|
||||
{
|
||||
/// Synchronize when a packet with Mark occurs, process the next packet
|
||||
jpegFrame.Clear();
|
||||
synced = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Stay unsynchronized
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
string msg = string.Format("Exception in MJpeg RTP listener thread: {0}", exc.Message);
|
||||
log.Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void StartMsrmntListener(IPAddress localIP, int localPort)
|
||||
{
|
||||
msrmntUdpClient = new UdpClient(new IPEndPoint(localIP, localPort));
|
||||
msrmntListenerThread = new Thread(new ThreadStart(MsrmntListener));
|
||||
msrmntListenerThread.Start();
|
||||
}
|
||||
|
||||
void MsrmntListener()
|
||||
{
|
||||
StringBuilder toBeProcessed = new StringBuilder();
|
||||
int[] angles = new int[RoisAndResults.MaxRegisteredRois];
|
||||
|
||||
while (!stopMsrmntListenerFlag)
|
||||
{
|
||||
try
|
||||
{
|
||||
IPEndPoint endpoint = null;
|
||||
Byte[] data = msrmntUdpClient.Receive(ref endpoint);
|
||||
|
||||
toBeProcessed.Append(Encoding.ASCII.GetString(data, 0, data.Length));
|
||||
log.DebugFormat("MeasurementUdpListener() ... toBeProcessed = {0}", toBeProcessed);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int from = toBeProcessed.ToString().IndexOf('[');
|
||||
if (from < 0) break;
|
||||
|
||||
int len = toBeProcessed.ToString(from + 1, toBeProcessed.Length - from - 1).IndexOf(']');
|
||||
if (len < 0) break;
|
||||
|
||||
string[] pulsesArr = toBeProcessed.ToString(from + 1, len).Split(new char[] { ';' });
|
||||
|
||||
bool fmtError = false;
|
||||
long timeMs;
|
||||
if ((pulsesArr.Length >= 2) &&
|
||||
(pulsesArr.Length <= RoisAndResults.MaxRegisteredRois + 1) &&
|
||||
long.TryParse(pulsesArr[0], out timeMs))
|
||||
{
|
||||
for (int i = 1; i < pulsesArr.Length; i++)
|
||||
{
|
||||
int val;
|
||||
if (int.TryParse(pulsesArr[i], out val))
|
||||
{
|
||||
angles[i - 1] = Math.Abs(val); /// TODO: pozerat CW/CCW a podla toho dat +/-
|
||||
}
|
||||
else
|
||||
{
|
||||
fmtError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fmtError) roisAndResults.SetResults(timeMs, angles);
|
||||
}
|
||||
|
||||
toBeProcessed.Remove(0, from + len + 2);
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
string msg = string.Format("Exception in the measurement listener thread: {0}", exc.Message);
|
||||
log.Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//public void OnMeasurementDataReceived(object sender, MeasuredDataEventArgs msrmtData)
|
||||
//{
|
||||
// string[] pulsesArr = msrmtData.MeasuredData.Split(new char[] { ';' });
|
||||
|
||||
// uint uiVal;
|
||||
// if (result != null && result.Length + 1 == pulsesArr.Length && uint.TryParse(pulsesArr[0], out uiVal))
|
||||
// {
|
||||
// cameraTimeMs = (long)uiVal;
|
||||
|
||||
// for (int i = 0; i < result.Length; i++)
|
||||
// {
|
||||
// int val;
|
||||
// if (int.TryParse(pulsesArr[i + 1], out val))
|
||||
// {
|
||||
// result[i] = Math.Abs(val);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
public IOperation LiveStreamOp(bool hiRes)
|
||||
{
|
||||
int wid = hiRes ? 1280 : 640;
|
||||
int hgh = hiRes ? 960 : 480;
|
||||
string command = string.Format("/opt/vc/bin/raspivid -t 0 -cd MJPEG -w {0} -h {1} -fps 30 -b 8000000 -o - | gst-launch-1.0 fdsrc ! \"image/jpeg,framerate=30/1\" ! jpegparse ! rtpjpegpay ! udpsink host={2} port={3}",
|
||||
wid, hgh, NetAdapter.IPAddress, rtpUdpLocalPort);
|
||||
//string command = string.Format("~/userland/build/bin/raspivid -t 0 -cd MJPEG -w {0} -h {1} -fps 30 -b 8000000 -o - | gst-launch-1.0 fdsrc ! \"image/jpeg,framerate=30/1\" ! jpegparse ! rtpjpegpay ! udpsink host={2} port={3}",
|
||||
// wid, hgh, NetAdapter.IPAddress, rtpUdpLocalPort);
|
||||
|
||||
return new LiveStreamOp(this, Telnet, command);
|
||||
}
|
||||
|
||||
|
||||
public IOperation GrabImagesOp(string[] imgFileNames, bool blackAndWhite, bool lowResolution, ImageRotation imageRotation)
|
||||
{
|
||||
return new GrabImagesOp(this, imgFileNames, blackAndWhite, lowResolution, imageRotation);
|
||||
}
|
||||
|
||||
|
||||
public IOperation MeasurementOp()
|
||||
{
|
||||
if (Telnet != null)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
string command;
|
||||
bool measurementCommandSent;
|
||||
|
||||
|
||||
public void Start()
|
||||
{
|
||||
/// Prepare the telent command
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; i <= roisAndResults.RegisteredRoisCount; i++)
|
||||
{
|
||||
sb.Append(" ");
|
||||
sb.Append(roisAndResults.GetRoiParams(i));
|
||||
}
|
||||
|
||||
int logImagesArg;
|
||||
switch (CameraCfg.TestImagesMode)
|
||||
{
|
||||
default:
|
||||
case TestImagesMode.None:
|
||||
case TestImagesMode.LoadImages:
|
||||
logImagesArg = 0;
|
||||
break;
|
||||
case TestImagesMode.SaveFirstImages:
|
||||
logImagesArg = CameraCfg.TestImagesCount;
|
||||
break;
|
||||
case TestImagesMode.SaveLastImages:
|
||||
logImagesArg = -CameraCfg.TestImagesCount;
|
||||
break;
|
||||
}
|
||||
|
||||
command = string.Format("clp/Measurement -udp {0} {1}{2}{3} 1 7 0 0 {4}",
|
||||
NetAdapter.IPAddress,
|
||||
msrmntUdpLocalPort,
|
||||
(CameraCfg.TestImagesMode == TestImagesMode.LoadImages) ? (" -l " + CameraCfg.TestImagesCount.ToString()) : string.Empty,
|
||||
sb,
|
||||
logImagesArg);
|
||||
|
||||
measurementCommandSent = false;
|
||||
|
||||
/// If ready send (=enqueue) the command
|
||||
if (Telnet.State == TelnetClient.TelnetState.Inactive)
|
||||
{
|
||||
log.WarnFormat("{0} SEND_MSRMNT_CMD: {1}", Name, command);
|
||||
Telnet.Enqueue(new Telnet.Command(CmdAction.SEND_MSRMNT_CMD, command));
|
||||
measurementCommandSent = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Event Run()
|
||||
{
|
||||
if (!measurementCommandSent)
|
||||
{
|
||||
/// When ready send (=enqueue) the command
|
||||
if (Telnet.State == TelnetClient.TelnetState.Inactive)
|
||||
{
|
||||
log.WarnFormat("{0} SEND_MSRMNT_CMD: {1}", Name, command);
|
||||
Telnet.Enqueue(new Telnet.Command(CmdAction.SEND_MSRMNT_CMD, command));
|
||||
measurementCommandSent = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (measurementCommandSent)
|
||||
{
|
||||
log.WarnFormat("{0} SEND_COMMAND: CTRL-Q", Name);
|
||||
Telnet.Enqueue(new Telnet.Command(CmdAction.SEND_COMMAND, TelnetClient.Q_Command));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public enum TestImagesMode
|
||||
{
|
||||
None,
|
||||
SaveFirstImages,
|
||||
SaveLastImages,
|
||||
LoadImages,
|
||||
Count,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
public class CameraCfg : ComponentCfgBase, IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(CameraCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new CameraCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int HardwareAddress;
|
||||
public bool DisplayTerminal;
|
||||
|
||||
[XmlIgnore]
|
||||
public TestImagesMode TestImagesMode;
|
||||
|
||||
[XmlIgnore]
|
||||
public int TestImagesCount;
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
CameraCfg() { }
|
||||
|
||||
public CameraCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = "Network.Adapter";
|
||||
HardwareAddress = 1;
|
||||
TestImagesMode = TestImagesMode.None;
|
||||
TestImagesCount = 3000;
|
||||
DebugLevel = Config.Entities.DebugMode.AutoDetect;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, s/n={1}, Terminal={2}, TestImagesMode={3}, TestImagesCount={4}, Parent={5}",
|
||||
Name,
|
||||
HardwareAddress,
|
||||
DisplayTerminal ? Strings.yes : Strings.no,
|
||||
TestImagesMode,
|
||||
TestImagesCount,
|
||||
ParentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public partial class CameraCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
CameraCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as CameraCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public CameraCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PumpCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
Localize();
|
||||
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
foreach (var cmpnt in parent.CmpntEntities)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is TBF.Rig.Network.Adapter.Factory)
|
||||
{
|
||||
parentNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (TestImagesMode mode = 0; mode < TestImagesMode.Count; mode++)
|
||||
{
|
||||
testImagesModeComboBox.Items.Add(mode.ToString());
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void Localize()
|
||||
{
|
||||
nameLabel.Text = Strings.Name;
|
||||
parentNameLabel.Text = Strings.Parent_name;
|
||||
hwAddressLabel.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;
|
||||
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
|
||||
hwAddressTextBox.Text = config.HardwareAddress.ToString();
|
||||
displayTerminalCheckBox.Checked = config.DisplayTerminal;
|
||||
testImagesModeComboBox.Text = config.TestImagesMode.ToString();
|
||||
testImagesCountTextBox.Text = config.TestImagesCount.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
hwAddressTextBox.Enabled = true;
|
||||
displayTerminalCheckBox.Enabled = true;
|
||||
testImagesModeComboBox.Enabled = true;
|
||||
testImagesCountTextBox.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 + string.Format(Strings.Invalid_0, parentNameLabel.Text);
|
||||
}
|
||||
|
||||
if (!int.TryParse(hwAddressTextBox.Text, out dummy) || dummy % 100 > 63)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, hwAddressLabel.Text);
|
||||
}
|
||||
|
||||
TestImagesMode newTestImagesMode = TestImagesMode.Invalid;
|
||||
for (TestImagesMode mode = 0; mode < TestImagesMode.Count; mode++)
|
||||
{
|
||||
if (testImagesModeComboBox.Text == mode.ToString()) newTestImagesMode = mode;
|
||||
}
|
||||
if (newTestImagesMode == TestImagesMode.Invalid)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, testImagesModeLabel.Text);
|
||||
}
|
||||
|
||||
if (!int.TryParse(testImagesCountTextBox.Text, out dummy) || dummy < 0 || dummy > 3000
|
||||
|| ((dummy == 0) && (newTestImagesMode != TestImagesMode.None)))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, testImagesCountLabel.Text);
|
||||
}
|
||||
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
string newParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
|
||||
int newHWAddress = int.Parse(hwAddressTextBox.Text);
|
||||
TestImagesMode newTestImagesMode = 0;
|
||||
for (TestImagesMode mode = 0; mode < TestImagesMode.Count; mode++)
|
||||
{
|
||||
if (testImagesModeComboBox.Text == mode.ToString()) newTestImagesMode = mode;
|
||||
}
|
||||
int newTestImagesCount = int.Parse(testImagesCountTextBox.Text);
|
||||
|
||||
|
||||
if (config.Name != nameTextBox.Text ||
|
||||
config.ParentName != newParentName ||
|
||||
config.HardwareAddress != newHWAddress ||
|
||||
config.DisplayTerminal != displayTerminalCheckBox.Checked)
|
||||
{
|
||||
config.Name = nameTextBox.Text;
|
||||
config.ParentName = newParentName;
|
||||
config.HardwareAddress = newHWAddress;
|
||||
config.DisplayTerminal = displayTerminalCheckBox.Checked;
|
||||
|
||||
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
|
||||
if (config.TestImagesMode != newTestImagesMode ||
|
||||
config.TestImagesCount != newTestImagesCount)
|
||||
{
|
||||
config.TestImagesMode = newTestImagesMode;
|
||||
config.TestImagesCount = newTestImagesCount;
|
||||
|
||||
flags |= (CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.VolatileChange);
|
||||
}
|
||||
|
||||
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
||||
{
|
||||
Camera.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
partial class CameraCfgCtrl
|
||||
{
|
||||
/// <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.hwAddressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.hwAddressLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.displayTerminalCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.testImagesCountTextBox = new System.Windows.Forms.TextBox();
|
||||
this.testImagesCountLabel = new System.Windows.Forms.Label();
|
||||
this.testImagesModeComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.testImagesModeLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// hwAddressTextBox
|
||||
//
|
||||
this.hwAddressTextBox.Enabled = false;
|
||||
this.hwAddressTextBox.Location = new System.Drawing.Point(132, 92);
|
||||
this.hwAddressTextBox.Name = "hwAddressTextBox";
|
||||
this.hwAddressTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.hwAddressTextBox.TabIndex = 6;
|
||||
//
|
||||
// hwAddressLabel
|
||||
//
|
||||
this.hwAddressLabel.AutoSize = true;
|
||||
this.hwAddressLabel.Location = new System.Drawing.Point(28, 95);
|
||||
this.hwAddressLabel.Name = "hwAddressLabel";
|
||||
this.hwAddressLabel.Size = new System.Drawing.Size(71, 13);
|
||||
this.hwAddressLabel.TabIndex = 5;
|
||||
this.hwAddressLabel.Text = "Serial number";
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(28, 69);
|
||||
this.parentNameLabel.Name = "parentNameLabel";
|
||||
this.parentNameLabel.Size = new System.Drawing.Size(67, 13);
|
||||
this.parentNameLabel.TabIndex = 3;
|
||||
this.parentNameLabel.Text = "Parent name";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(132, 41);
|
||||
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, 44);
|
||||
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(129, 17);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// parentNameComboBox
|
||||
//
|
||||
this.parentNameComboBox.Enabled = false;
|
||||
this.parentNameComboBox.FormattingEnabled = true;
|
||||
this.parentNameComboBox.Location = new System.Drawing.Point(132, 66);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.parentNameComboBox.TabIndex = 4;
|
||||
//
|
||||
// displayTerminalCheckBox
|
||||
//
|
||||
this.displayTerminalCheckBox.AutoSize = true;
|
||||
this.displayTerminalCheckBox.Enabled = false;
|
||||
this.displayTerminalCheckBox.Location = new System.Drawing.Point(133, 122);
|
||||
this.displayTerminalCheckBox.Name = "displayTerminalCheckBox";
|
||||
this.displayTerminalCheckBox.Size = new System.Drawing.Size(99, 17);
|
||||
this.displayTerminalCheckBox.TabIndex = 7;
|
||||
this.displayTerminalCheckBox.Text = "Display terminal";
|
||||
this.displayTerminalCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// testImagesCountTextBox
|
||||
//
|
||||
this.testImagesCountTextBox.Enabled = false;
|
||||
this.testImagesCountTextBox.Location = new System.Drawing.Point(132, 174);
|
||||
this.testImagesCountTextBox.Name = "testImagesCountTextBox";
|
||||
this.testImagesCountTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.testImagesCountTextBox.TabIndex = 12;
|
||||
//
|
||||
// testImagesCountLabel
|
||||
//
|
||||
this.testImagesCountLabel.AutoSize = true;
|
||||
this.testImagesCountLabel.Location = new System.Drawing.Point(28, 177);
|
||||
this.testImagesCountLabel.Name = "testImagesCountLabel";
|
||||
this.testImagesCountLabel.Size = new System.Drawing.Size(94, 13);
|
||||
this.testImagesCountLabel.TabIndex = 11;
|
||||
this.testImagesCountLabel.Text = "Test images count";
|
||||
//
|
||||
// testImagesModeComboBox
|
||||
//
|
||||
this.testImagesModeComboBox.Enabled = false;
|
||||
this.testImagesModeComboBox.FormattingEnabled = true;
|
||||
this.testImagesModeComboBox.Location = new System.Drawing.Point(132, 148);
|
||||
this.testImagesModeComboBox.Name = "testImagesModeComboBox";
|
||||
this.testImagesModeComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.testImagesModeComboBox.TabIndex = 14;
|
||||
//
|
||||
// testImagesModeLabel
|
||||
//
|
||||
this.testImagesModeLabel.AutoSize = true;
|
||||
this.testImagesModeLabel.Location = new System.Drawing.Point(28, 151);
|
||||
this.testImagesModeLabel.Name = "testImagesModeLabel";
|
||||
this.testImagesModeLabel.Size = new System.Drawing.Size(93, 13);
|
||||
this.testImagesModeLabel.TabIndex = 13;
|
||||
this.testImagesModeLabel.Text = "Test images mode";
|
||||
//
|
||||
// CameraCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.testImagesModeComboBox);
|
||||
this.Controls.Add(this.testImagesModeLabel);
|
||||
this.Controls.Add(this.hwAddressTextBox);
|
||||
this.Controls.Add(this.hwAddressLabel);
|
||||
this.Controls.Add(this.testImagesCountTextBox);
|
||||
this.Controls.Add(this.testImagesCountLabel);
|
||||
this.Controls.Add(this.displayTerminalCheckBox);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "CameraCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(402, 254);
|
||||
this.Load += new System.EventHandler(this.PumpCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox hwAddressTextBox;
|
||||
private System.Windows.Forms.Label hwAddressLabel;
|
||||
private System.Windows.Forms.Label parentNameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.ComboBox parentNameComboBox;
|
||||
private System.Windows.Forms.CheckBox displayTerminalCheckBox;
|
||||
private System.Windows.Forms.TextBox testImagesCountTextBox;
|
||||
private System.Windows.Forms.Label testImagesCountLabel;
|
||||
private System.Windows.Forms.ComboBox testImagesModeComboBox;
|
||||
private System.Windows.Forms.Label testImagesModeLabel;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Camera.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Camera(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Camera(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new CameraCfg(this.GetType().Namespace.Substring(8), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(CameraCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Network.Telnet;
|
||||
using System.IO;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public class GrabImagesOp : IOperation
|
||||
{
|
||||
/// TODO: Implement support for grabbing multiple images, now imgFileNames.Lenght should be 1
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(GrabImagesOp));
|
||||
public override string ToString() { return string.Format("GrabImageOp()"); }
|
||||
|
||||
readonly Camera camera;
|
||||
readonly Telnet.TelnetClient telnet;
|
||||
readonly string[] imgFileNames;
|
||||
readonly bool blackAndWhite;
|
||||
readonly bool lowResolution;
|
||||
readonly ImageRotation imageRotation;
|
||||
|
||||
string command;
|
||||
bool grabImageCommandSent;
|
||||
string response;
|
||||
bool grabPassed;
|
||||
bool grabFailed;
|
||||
bool transferringGrabbedImage;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Events: Event.None or Event.Error
|
||||
/// </summary>
|
||||
/// <param name="camera">CLP1611.Camera reference</param>
|
||||
public GrabImagesOp(Camera camera, string[] imgFileNames, bool blackAndWhite, bool lowResolution, ImageRotation imageRotation)
|
||||
{
|
||||
/// TODO: Implement support for grabbing multiple images, now imgFileNames.Lenght should be 1
|
||||
|
||||
this.camera = camera;
|
||||
this.telnet = camera.Telnet;
|
||||
this.imgFileNames = imgFileNames;
|
||||
this.blackAndWhite = blackAndWhite;
|
||||
this.lowResolution = lowResolution;
|
||||
this.imageRotation = imageRotation;
|
||||
|
||||
grabImageCommandSent = false;
|
||||
transferringGrabbedImage = false;
|
||||
|
||||
if (camera.DebugLevel == DebugMode.Normal || camera.DebugLevel == DebugMode.DetectedOn)
|
||||
{
|
||||
telnet.promptReceivedHandler += delegate(object sndr, PromptReceivedEventArgs a)
|
||||
{
|
||||
OnPromptReceived(sndr, a);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void OnPromptReceived(object sndr, PromptReceivedEventArgs a)
|
||||
{
|
||||
response = a.Response;
|
||||
/// TODO
|
||||
}
|
||||
|
||||
|
||||
public void Start()
|
||||
{
|
||||
grabImageCommandSent = false;
|
||||
transferringGrabbedImage = false;
|
||||
|
||||
if ((imgFileNames != null) && (imgFileNames.Length > 0) && File.Exists(imgFileNames[0]))
|
||||
{
|
||||
///
|
||||
/// An image specified, (1) delete previous image, (2) check if this is a simulation
|
||||
///
|
||||
File.Delete(imgFileNames[0]);
|
||||
|
||||
if (camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.Simulate || camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.DetectedOff)
|
||||
{
|
||||
///
|
||||
/// Camera is in simulation mode => create a simulated image
|
||||
///
|
||||
File.Copy(string.Format("{0}\\Pictures\\sample.jpg", Program.ExecutableDir), imgFileNames[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Event Run()
|
||||
{
|
||||
if ((imgFileNames == null) || (imgFileNames.Length < 1) || (imgFileNames[0] == null))
|
||||
{
|
||||
///
|
||||
/// No images to be grabbed => Done
|
||||
///
|
||||
return Event.GrabPassed;
|
||||
}
|
||||
else if (camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.Simulate ||
|
||||
camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.DetectedOff)
|
||||
{
|
||||
///
|
||||
/// Camera is in simulation mode => create a simulated image and complete
|
||||
///
|
||||
return Event.GrabPassed;
|
||||
}
|
||||
else if (!grabImageCommandSent)
|
||||
{
|
||||
///
|
||||
/// Normal operation, no command sent yet => (1) wait until telnet state = Inactive, (2) send a command
|
||||
///
|
||||
if (camera.Running && (telnet.State == TelnetClient.TelnetState.Inactive))
|
||||
{
|
||||
///
|
||||
/// State variables
|
||||
///
|
||||
response = null;
|
||||
|
||||
///
|
||||
/// Prepare a command
|
||||
///
|
||||
int rotation = 0;
|
||||
if (imageRotation == ImageRotation.Deg90)
|
||||
rotation = 90;
|
||||
else if (imageRotation == ImageRotation.Deg180)
|
||||
rotation = 180;
|
||||
else if (imageRotation == ImageRotation.Deg270)
|
||||
rotation = 270;
|
||||
|
||||
command = string.Format("clp/GrabImage {0} {1} -r {2} {3} -n 1 {4}",
|
||||
blackAndWhite ? "-bmp" : "-bmp", /// 0 ... file format and quality
|
||||
blackAndWhite ? "-y8" : "-rgb", /// 1 ... B&W / color
|
||||
rotation.ToString(), /// 2 ... roration
|
||||
lowResolution ? "-lr" : "-hr", /// 4 ... resolution
|
||||
"grabbed.bmp"); /// 5 ... filename
|
||||
|
||||
//
|
||||
// Send (or enqueue) command
|
||||
//
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.CLEAR_RESPONSE));
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_COMMAND, command));
|
||||
grabImageCommandSent = true;
|
||||
log.WarnFormat("{0} IP={1} command={2}", camera.Name, camera.IPAddress, command);
|
||||
}
|
||||
return Event.CameraBusy;
|
||||
}
|
||||
else if (grabPassed)
|
||||
{
|
||||
///
|
||||
/// Normal operation, grab passed => transfer/transferring the image
|
||||
///
|
||||
if (transferringGrabbedImage)
|
||||
{
|
||||
/// Grab passed and image transfer is in progress
|
||||
return Event.GrabPassed;
|
||||
}
|
||||
else if (0 == camera.DownloadFile(blackAndWhite ? "grabbed.jpg" : "grabbed.bmp", imgFileNames[0]))
|
||||
{
|
||||
/// File transfer successfully started
|
||||
transferringGrabbedImage = true;
|
||||
return Event.GrabPassed;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Wait until the previous image transfer completes
|
||||
return Event.CameraBusy;
|
||||
}
|
||||
}
|
||||
else if (grabFailed)
|
||||
{
|
||||
///
|
||||
/// Normal operation, grab failed => there in no image to transfer
|
||||
///
|
||||
return Event.GrabFailed;
|
||||
}
|
||||
else if (response != null)
|
||||
{
|
||||
///
|
||||
/// Normal operation
|
||||
///
|
||||
if (response.Contains("completed"))
|
||||
{
|
||||
grabPassed = true;
|
||||
|
||||
///
|
||||
/// Start the file transfer
|
||||
///
|
||||
if (0 == camera.DownloadFile(blackAndWhite ? "grabbed.jpg" : "grabbed.bmp", imgFileNames[0]))
|
||||
{
|
||||
/// File transfer successfully started
|
||||
transferringGrabbedImage = true;
|
||||
return Event.GrabPassed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.CameraBusy; /// File transfer not started yet
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grabFailed = true;
|
||||
return Event.GrabFailed;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.CameraBusy;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.Simulate) return;
|
||||
|
||||
if (grabImageCommandSent)
|
||||
{
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_COMMAND, Telnet.TelnetClient.CtrlCCommand));
|
||||
log.WarnFormat("{0} IP={1} command=CTRL-C", camera.Name, camera.IPAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using log4net;
|
||||
using TBF.Rig.Network.Telnet;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public class LiveStreamOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(LiveStreamOp));
|
||||
|
||||
readonly Camera camera;
|
||||
readonly Telnet.TelnetClient telnet;
|
||||
readonly string command;
|
||||
|
||||
bool liveStreamCommandSent;
|
||||
|
||||
/// <summary>
|
||||
/// Events: Event.None or Event.Error
|
||||
/// </summary>
|
||||
/// <param name="camera">CLP1611.Camera reference</param>
|
||||
public LiveStreamOp(Camera camera, Telnet.TelnetClient telnet, string command)
|
||||
{
|
||||
this.camera = camera;
|
||||
this.telnet = telnet;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
|
||||
public void Start()
|
||||
{
|
||||
liveStreamCommandSent = false;
|
||||
}
|
||||
|
||||
public Event Run()
|
||||
{
|
||||
if (camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.Simulate) return Event.None;
|
||||
|
||||
log.DebugFormat("Run(): telnet.State = {0}, liveStreamCommandSent = {1}", telnet.State, liveStreamCommandSent);
|
||||
|
||||
if (!liveStreamCommandSent)
|
||||
{
|
||||
if (camera.Running && (telnet.State == TelnetClient.TelnetState.Inactive))
|
||||
{
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_STRING, command));
|
||||
liveStreamCommandSent = true;
|
||||
log.WarnFormat("{0} IP={1} command={2}", camera.Name, camera.IPAddress, command);
|
||||
}
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (camera.CameraCfg.DebugLevel == Config.Entities.DebugMode.Simulate) return;
|
||||
|
||||
log.DebugFormat("Stop(): telnet.State = {0}, liveStreamCommandSent = {1}", telnet.State, liveStreamCommandSent);
|
||||
|
||||
if (liveStreamCommandSent)
|
||||
{
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_COMMAND, Telnet.TelnetClient.CtrlCCommand));
|
||||
log.WarnFormat("{0} IP={1} command=CTRL-C", camera.Name, camera.IPAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.Network.Camera
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements RFC2435
|
||||
/// </summary>
|
||||
public class JpegFrame : RtpFrame
|
||||
{
|
||||
static readonly ILog log = LogManager.GetLogger(typeof(TBF.UI.MainWnd));
|
||||
|
||||
#region Statics
|
||||
|
||||
static byte[] CreateStartOfInformation()
|
||||
{
|
||||
return new byte[] { 0xff, 0xd8 };
|
||||
}
|
||||
|
||||
static byte[] CreateJFIFHeader(uint type, uint width, uint height, ArraySegment<byte> tables, uint dri)
|
||||
{
|
||||
List<byte> result = new List<byte>();
|
||||
result.AddRange(CreateStartOfInformation());
|
||||
|
||||
result.Add(0xff);
|
||||
result.Add(0xe0);//AppFirst
|
||||
result.Add(0x00);
|
||||
result.Add(0x10);//length
|
||||
result.Add((byte)'J');
|
||||
result.Add((byte)'F');
|
||||
result.Add((byte)'I');
|
||||
result.Add((byte)'F');
|
||||
result.Add(0x00);
|
||||
|
||||
result.Add(0x01);//Version Major
|
||||
result.Add(0x01);//Version Minor
|
||||
|
||||
result.Add(0x00);//Units
|
||||
|
||||
result.Add(0x00);//Horizontal
|
||||
result.Add(0x01);
|
||||
|
||||
result.Add(0x00);//Vertical
|
||||
result.Add(0x01);
|
||||
|
||||
result.Add(0x00);//No thumb
|
||||
result.Add(0x00);
|
||||
|
||||
if (dri > 0)
|
||||
{
|
||||
result.AddRange(CreateDataRestartIntervalMarker(dri));
|
||||
}
|
||||
|
||||
result.AddRange(CreateQuantizationTablesMarker(tables));
|
||||
|
||||
result.Add(0xff);
|
||||
result.Add(0xc0);//SOF
|
||||
result.Add(0x00);
|
||||
result.Add(0x11);
|
||||
result.Add(0x08);
|
||||
result.Add((byte)(height >> 8));
|
||||
result.Add((byte)height);
|
||||
result.Add((byte)(width >> 8));
|
||||
result.Add((byte)width);
|
||||
|
||||
result.Add(0x03);
|
||||
result.Add(0x01);
|
||||
result.Add((byte)(type > 0 ? 0x22 : 0x21));
|
||||
result.Add(0x00);
|
||||
|
||||
result.Add(0x02);
|
||||
result.Add(0x11);
|
||||
result.Add(0x01);
|
||||
|
||||
result.Add(0x03);
|
||||
result.Add(0x11);
|
||||
result.Add(0x01);
|
||||
|
||||
//Huffman Tables
|
||||
result.AddRange(CreateHuffmanTableMarker(lum_dc_codelens, lum_dc_symbols, 0, 0));
|
||||
result.AddRange(CreateHuffmanTableMarker(lum_ac_codelens, lum_ac_symbols, 0, 1));
|
||||
result.AddRange(CreateHuffmanTableMarker(chm_dc_codelens, chm_dc_symbols, 1, 0));
|
||||
result.AddRange(CreateHuffmanTableMarker(chm_ac_codelens, chm_ac_symbols, 1, 1));
|
||||
|
||||
result.Add(0xff);
|
||||
result.Add(0xda);//Marker SOS
|
||||
result.Add(0x00);
|
||||
result.Add(0x0c);
|
||||
result.Add(0x03);
|
||||
result.Add(0x01);
|
||||
result.Add(0x00);
|
||||
result.Add(0x02);
|
||||
result.Add(0x11);
|
||||
result.Add(0x03);
|
||||
result.Add(0x11);
|
||||
result.Add(0x00);
|
||||
result.Add(0x3f);
|
||||
result.Add(0x00);
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
// The default 'luma' and 'chroma' quantizer tables, in zigzag order:
|
||||
static byte[] defaultQuantizers = new byte[]
|
||||
{
|
||||
// luma table:
|
||||
16, 11, 12, 14, 12, 10, 16, 14,
|
||||
13, 14, 18, 17, 16, 19, 24, 40,
|
||||
26, 24, 22, 22, 24, 49, 35, 37,
|
||||
29, 40, 58, 51, 61, 60, 57, 51,
|
||||
56, 55, 64, 72, 92, 78, 64, 68,
|
||||
87, 69, 55, 56, 80, 109, 81, 87,
|
||||
95, 98, 103, 104, 103, 62, 77, 113,
|
||||
121, 112, 100, 120, 92, 101, 103, 99,
|
||||
// chroma table:
|
||||
17, 18, 18, 24, 21, 24, 47, 26,
|
||||
26, 47, 99, 66, 56, 66, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99,
|
||||
99, 99, 99, 99, 99, 99, 99, 99
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Luma and Chroma Table using the default quantizer
|
||||
/// </summary>
|
||||
/// <param name="Q">The quality</param>
|
||||
/// <returns>64 luma bytes and 64 chroma</returns>
|
||||
static byte[] CreateQuantizationTables(uint Q)
|
||||
{
|
||||
int factor = (int)Q;
|
||||
int q;
|
||||
|
||||
if (Q < 1) factor = 1;
|
||||
else if (Q > 99) factor = 99;
|
||||
|
||||
if (Q < 50)
|
||||
{
|
||||
q = 5000 / factor;
|
||||
}
|
||||
else
|
||||
{
|
||||
q = 200 - factor * 2;
|
||||
}
|
||||
byte[] resultTables = new byte[128];
|
||||
for (int i = 0; i < 128; ++i)
|
||||
{
|
||||
int newVal = (defaultQuantizers[i] * q + 50) / 100;
|
||||
if (newVal < 1) newVal = 1;
|
||||
else if (newVal > 255) newVal = 255;
|
||||
resultTables[i] = (byte)newVal;
|
||||
}
|
||||
return resultTables;
|
||||
}
|
||||
|
||||
static byte[] CreateQuantizationTablesMarker(ArraySegment<byte> tables)
|
||||
{
|
||||
List<byte> result = new List<byte>();
|
||||
|
||||
int tableSize = tables.Count / 2;
|
||||
|
||||
//Luma
|
||||
|
||||
result.Add(0xff);
|
||||
result.Add(0xdb);
|
||||
|
||||
result.Add(0x00);
|
||||
result.Add((byte)(tableSize + 3));
|
||||
result.Add(0x00);
|
||||
|
||||
for (int i = 0, e = tableSize; i < e; ++i)
|
||||
{
|
||||
result.Add(tables.Array[tables.Offset + i]);
|
||||
}
|
||||
|
||||
//Chroma
|
||||
|
||||
result.Add(0xff);
|
||||
result.Add(0xdb);
|
||||
|
||||
result.Add(0x00);
|
||||
result.Add((byte)(tableSize + 3));
|
||||
result.Add(0x01);
|
||||
|
||||
for (int i = tableSize, e = tables.Count; i < e; ++i)
|
||||
{
|
||||
result.Add(tables.Array[tables.Offset + i]);
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
|
||||
}
|
||||
|
||||
static byte[] lum_dc_codelens = { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static byte[] lum_dc_symbols = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||
|
||||
static byte[] lum_ac_codelens = { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d, };
|
||||
|
||||
static byte[] lum_ac_symbols = {
|
||||
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
|
||||
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
|
||||
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
|
||||
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
|
||||
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
|
||||
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
|
||||
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
||||
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
|
||||
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
|
||||
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
|
||||
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
|
||||
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
|
||||
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
|
||||
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
|
||||
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
|
||||
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
|
||||
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
|
||||
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa,
|
||||
};
|
||||
|
||||
static byte[] chm_dc_codelens = { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
|
||||
|
||||
static byte[] chm_dc_symbols = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
|
||||
|
||||
static byte[] chm_ac_codelens = { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
|
||||
|
||||
static byte[] chm_ac_symbols = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
|
||||
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
|
||||
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
|
||||
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
|
||||
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
|
||||
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
|
||||
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
|
||||
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
|
||||
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
|
||||
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
|
||||
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
|
||||
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
|
||||
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
|
||||
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
|
||||
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
|
||||
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
|
||||
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
|
||||
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
|
||||
0xf9, 0xfa,
|
||||
};
|
||||
|
||||
static byte[] CreateHuffmanTableMarker(byte[] codeLens, byte[] symbols, int tableNo, int tableClass)
|
||||
{
|
||||
List<byte> result = new List<byte>();
|
||||
result.Add(0xff);
|
||||
result.Add(0xc4);
|
||||
result.Add(0x00);
|
||||
result.Add((byte)(3 + codeLens.Length + symbols.Length));
|
||||
result.Add((byte)((tableClass << 4) | tableNo));
|
||||
result.AddRange(codeLens);
|
||||
result.AddRange(symbols);
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
static byte[] CreateDataRestartIntervalMarker(uint dri)
|
||||
{
|
||||
return new byte[] { 0xff, 0xdd, 0x00, 0x04, (byte)(dri >> 8), (byte)(dri) };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public JpegFrame() : base(26) { }
|
||||
|
||||
/// <summary>
|
||||
/// Writes packets to a memory stream and created the default header and quantization tables if necessary.
|
||||
/// </summary>
|
||||
void ProcessPackets(System.IO.MemoryStream buffer)
|
||||
{
|
||||
ArraySegment<byte> tables = default(ArraySegment<byte>);
|
||||
uint FragmentOffset, TypeSpecific, Type, Quality, Width, Height, DataRestartInterval = 0;
|
||||
|
||||
for (int i = 0, e = this.Packets.Count, last = e - 1; i < e; ++i)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
RtpPacket packet = this.Packets[i];
|
||||
|
||||
TypeSpecific = (uint)(packet.Payload[offset++]);
|
||||
|
||||
//FragmentOffset = (uint)(packet.Payload[offset++] | packet.Payload[offset++] << 8 | packet.Payload[offset++] << 16);
|
||||
FragmentOffset = (uint)(packet.Payload[offset++] << 16 | packet.Payload[offset++] << 8 | packet.Payload[offset++]);
|
||||
|
||||
//Ensure start packet
|
||||
if (i == 0 && FragmentOffset != 0) continue;
|
||||
|
||||
Type = (uint)(packet.Payload[offset++]);
|
||||
Quality = (uint)packet.Payload[offset++];
|
||||
Width = (uint)(packet.Payload[offset++] * 8);
|
||||
Height = (uint)(packet.Payload[offset++] * 8);
|
||||
|
||||
//Only occur in the first packet
|
||||
if (FragmentOffset == 0)
|
||||
{
|
||||
//If There is already a StartOfInformation present just copy
|
||||
if (packet.Payload[offset] == 0xff && packet.Payload[offset + 1] == 0xd8)
|
||||
{
|
||||
goto WritePacket;
|
||||
}
|
||||
|
||||
//Get the restart interval is present
|
||||
if (Type > 63)
|
||||
{
|
||||
DataRestartInterval = (uint)(packet.Payload[offset++] << 8 | packet.Payload[offset++]);
|
||||
}
|
||||
|
||||
//Get the Q Tables if present
|
||||
if (Quality > 127)
|
||||
{
|
||||
uint MBZ = (uint)(packet.Payload[offset++]);//Should only proceed if MBZ > 0?
|
||||
uint Precision = (uint)(packet.Payload[offset++]);//Wasted read
|
||||
uint Length = (uint)(packet.Payload[offset++] << 8 | packet.Payload[offset++]);
|
||||
if(Length > 0)
|
||||
{
|
||||
tables = new ArraySegment<byte>(packet.Payload, offset, (int)Length);
|
||||
offset += (int)Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
tables = new ArraySegment<byte>(CreateQuantizationTables(Quality));
|
||||
}
|
||||
}
|
||||
|
||||
//Write the header to the buffer
|
||||
byte[] header = CreateJFIFHeader(Type, Width, Height, tables, DataRestartInterval);
|
||||
buffer.Write(header, 0, header.Length);
|
||||
|
||||
}
|
||||
|
||||
WritePacket: //Copy rest of data to buffer
|
||||
buffer.Write(packet.Payload, offset, packet.Payload.Length - offset);
|
||||
|
||||
//Check to see if EOI is present or needs to be added on the last packet
|
||||
if (i == last && packet.Payload[packet.Payload.Length - 2] != 0xff && packet.Payload[packet.Payload.Length - 1] != 0xd9)
|
||||
{
|
||||
buffer.WriteByte(0xff);
|
||||
buffer.WriteByte(0xd9);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Go back to the beginning
|
||||
buffer.Seek(0, System.IO.SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a image from the processed packets in the memory stream
|
||||
/// </summary>
|
||||
/// <returns>The image created from the packets</returns>
|
||||
public System.Drawing.Image ToImage()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (System.IO.MemoryStream buffer = new System.IO.MemoryStream())
|
||||
{
|
||||
ProcessPackets(buffer);
|
||||
return System.Drawing.Image.FromStream(buffer, false, true);
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
log.ErrorFormat("Exception in ToImage(): {0}", exc.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public class RoisAndResults
|
||||
{
|
||||
public const int MaxRegisteredRois = 4; /// Max. count of registered (and measured) ROI-s
|
||||
|
||||
public long CameraTimeMs;
|
||||
public int[] Angles;
|
||||
|
||||
private IList<string> roiParams;
|
||||
public int RegisteredRoisCount { get { return roiParams.Count; } }
|
||||
|
||||
|
||||
public RoisAndResults()
|
||||
{
|
||||
Angles = new int[MaxRegisteredRois];
|
||||
roiParams = new List<string>();
|
||||
}
|
||||
|
||||
|
||||
public void ClearRoiParams()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
roiParams.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public int RegisterRoi(string roiParam)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (this.roiParams.Count >= MaxRegisteredRois) return 0;
|
||||
|
||||
this.roiParams.Add(roiParam);
|
||||
return this.roiParams.Count; /// return a handle 1 .. MaxRegisteredRois
|
||||
}
|
||||
}
|
||||
|
||||
public string GetRoiParams(int roiHandle)
|
||||
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (roiHandle > 0 && roiHandle <= roiParams.Count)
|
||||
{
|
||||
return roiParams[roiHandle - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetResults(long timeMs, int[] angles)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
CameraTimeMs = timeMs;
|
||||
for (int i = 0; i < Math.Min(angles.Length, Angles.Length); i++)
|
||||
{
|
||||
Angles[i] = angles[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetResult(int roiHandle, out long timeMs)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (roiHandle > 0 && roiHandle <= roiParams.Count)
|
||||
{
|
||||
timeMs = CameraTimeMs;
|
||||
return Angles[roiHandle - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
timeMs = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace TBF.Rig.Network.Camera
|
||||
{
|
||||
public class RtpFrame
|
||||
{
|
||||
public enum STATE
|
||||
{
|
||||
Empty, /// Initial state after being constructed
|
||||
OK, /// The frame is not empty, but it's not complete yet. It's without any error
|
||||
Error, /// An error occured
|
||||
Complete, /// The frame is complete, consequent AddPacket() calls will be ignored
|
||||
}
|
||||
|
||||
public readonly int PayloadType;
|
||||
public IList<RtpPacket> Packets;
|
||||
public STATE State { get { return state; } }
|
||||
STATE state;
|
||||
|
||||
|
||||
public RtpFrame(int payloadType)
|
||||
{
|
||||
PayloadType = payloadType;
|
||||
Packets = new List<RtpPacket>();
|
||||
state = STATE.Empty;
|
||||
}
|
||||
|
||||
public STATE AddPacket(RtpPacket packet)
|
||||
{
|
||||
if (state == STATE.Error || packet.PayloadType != PayloadType)
|
||||
{
|
||||
return (state = STATE.Error); /// Already in error or wrong payload type
|
||||
}
|
||||
else if (state == STATE.Complete)
|
||||
{
|
||||
return STATE.Complete; /// Already complete
|
||||
}
|
||||
else if (state != STATE.Empty && packet.SequenceNumber != Packets.Last<RtpPacket>().SequenceNumber + 1)
|
||||
{
|
||||
return (state = STATE.Error); /// Packet out of order
|
||||
}
|
||||
|
||||
/// Going to add a new packet previous ones
|
||||
Packets.Add(packet);
|
||||
|
||||
if (packet.Mark)
|
||||
{
|
||||
return (state = STATE.Complete); /// Complete now
|
||||
}
|
||||
else
|
||||
{
|
||||
return (state = STATE.OK); /// OK, not complete yet
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Packets.Clear();
|
||||
state = STATE.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
|
||||
namespace TBF.Rig.Network.Camera
|
||||
{
|
||||
public class RtpPacket
|
||||
{
|
||||
public readonly int Version;
|
||||
public readonly bool P;
|
||||
public readonly bool X;
|
||||
public readonly int CC;
|
||||
public readonly bool Mark;
|
||||
public readonly int PayloadType;
|
||||
public readonly int SequenceNumber;
|
||||
public readonly int Timestamp;
|
||||
public readonly int SsrcId;
|
||||
public readonly Byte[] Payload; /// Data without RTP header
|
||||
|
||||
public RtpPacket(Byte[] data)
|
||||
{
|
||||
if (data.Length < 12) throw new Exception("Packet too short");
|
||||
|
||||
Version = (data[0] >> 6) & 0x02; /// 1 RTP Version
|
||||
P = ((data[0] & 0x20) != 0); /// 2 RTP P
|
||||
X = ((data[0] & 0x10) != 0); /// 3 RTP X
|
||||
CC = (data[0] & 0x0F); /// 4 RTP CC
|
||||
Mark = ((data[1] & 0x80) != 0); /// 5 RTP M
|
||||
PayloadType = (data[1] & 0x7F); /// 6 RTP PT
|
||||
SequenceNumber = data[2] * 256 + data[3]; /// 7 RTP Seq#
|
||||
Timestamp = ((data[4] * 256 + data[5]) * 256 + data[6]) * 256 + data[7]; /// 8 RTP Timestamp
|
||||
SsrcId = ((data[8] * 256 + data[9]) * 256 + data[10]) * 256 + data[11]; /// 9 RTP SSRC Id
|
||||
|
||||
int ExtensionHeaderSize = 0;
|
||||
if (X && data.Length >= 16 + 4*CC)
|
||||
{
|
||||
ExtensionHeaderSize = data[14 + 4*CC] * 256 + data[15 + 4*CC] + 4;
|
||||
}
|
||||
|
||||
int payloadDataOffset = 12 + 4 * CC + ExtensionHeaderSize;
|
||||
int payloadDataCount = data.Length - 12 - 4 * CC - ExtensionHeaderSize;
|
||||
|
||||
if (payloadDataCount < 0) throw new Exception("Invalid packet");
|
||||
|
||||
Payload = new byte[payloadDataCount];
|
||||
Array.Copy(data, payloadDataOffset, Payload, 0, payloadDataCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
partial class TerminalDlg
|
||||
{
|
||||
/// <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 Windows Form 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.vtTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// vtTextBox
|
||||
//
|
||||
this.vtTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.vtTextBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.vtTextBox.Multiline = true;
|
||||
this.vtTextBox.Name = "vtTextBox";
|
||||
this.vtTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||
this.vtTextBox.Size = new System.Drawing.Size(737, 437);
|
||||
this.vtTextBox.TabIndex = 0;
|
||||
//
|
||||
// TerminalDlg
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(737, 437);
|
||||
this.Controls.Add(this.vtTextBox);
|
||||
this.Name = "TerminalDlg";
|
||||
this.Text = "Terminal";
|
||||
this.Load += new System.EventHandler(this.Terminal_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox vtTextBox;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using TBF.Rig.Network.Telnet;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.CLP1611
|
||||
{
|
||||
public partial class TerminalDlg : Form
|
||||
{
|
||||
TelnetClient telnet;
|
||||
bool dlgLoaded;
|
||||
|
||||
public TerminalDlg()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public TerminalDlg(string name, TelnetClient telnet)
|
||||
{
|
||||
InitializeComponent();
|
||||
Text = name;
|
||||
this.telnet = telnet;
|
||||
}
|
||||
|
||||
private void Terminal_Load(object sender, EventArgs e)
|
||||
{
|
||||
telnet.vtTextChangedHandler += delegate(object sndr, VtTextChangedEventArgs args)
|
||||
{
|
||||
if (InvokeRequired) { Invoke(new EventHandler<VtTextChangedEventArgs>(OnTextChanged), sndr, args); }
|
||||
else OnTextChanged(sndr, args);
|
||||
};
|
||||
dlgLoaded = true;
|
||||
}
|
||||
|
||||
void OnTextChanged(object sndr, VtTextChangedEventArgs args)
|
||||
{
|
||||
vtTextBox.Text = args.VtText;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,153 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
public class Display : ComponentBase, IOperation, ICameraDisplay
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Display));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}({1})", this.GetType().Namespace.Substring(8), Cfg.ToString(1));
|
||||
}
|
||||
|
||||
|
||||
public readonly DisplayCfg DisplayCfg;
|
||||
///
|
||||
public Display()
|
||||
{
|
||||
}
|
||||
///
|
||||
public Display(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
DisplayCfg = cfg as DisplayCfg;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public bool[] SelectedImages { get { return selectedImages; } }
|
||||
bool[] selectedImages;
|
||||
|
||||
|
||||
|
||||
public enum CurrentOp
|
||||
{
|
||||
None,
|
||||
StaticImage,
|
||||
LiveStream,
|
||||
}
|
||||
CurrentOp currentOp;
|
||||
DialogResult result;
|
||||
|
||||
string title;
|
||||
string[] imageFileNames;
|
||||
|
||||
|
||||
|
||||
DisplayForm displayForm;
|
||||
///
|
||||
delegate void DisplayFormDlgt(Display myRef);
|
||||
///
|
||||
void OpenStaticImageDisplay(Display myRef)
|
||||
{
|
||||
myRef.displayForm = new DisplayForm(imageFileNames, title);
|
||||
displayForm.Show();
|
||||
}
|
||||
///
|
||||
void OpenLiveStreamDisplay(Display myRef)
|
||||
{
|
||||
myRef.displayForm = new DisplayForm(imageFileNames, title);
|
||||
displayForm.Show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <returns>Reference to the operation</returns>
|
||||
public IOperation ShowStaticImageOp(string[] imageFileNames, string title)
|
||||
{
|
||||
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
|
||||
|
||||
this.imageFileNames = imageFileNames;
|
||||
this.title = title;
|
||||
currentOp = CurrentOp.StaticImage;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <returns>Reference to the operation</returns>
|
||||
public IOperation ShowLiveStreamOp(string[] imageFileNames, string title)
|
||||
{
|
||||
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
|
||||
|
||||
this.imageFileNames = imageFileNames;
|
||||
this.title = title;
|
||||
currentOp = CurrentOp.LiveStream;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
result = DialogResult.None;
|
||||
|
||||
switch (currentOp)
|
||||
{
|
||||
case CurrentOp.StaticImage:
|
||||
Program.MainWnd.Invoke(new DisplayFormDlgt(OpenStaticImageDisplay), this);
|
||||
break;
|
||||
|
||||
case CurrentOp.LiveStream:
|
||||
Program.MainWnd.Invoke(new DisplayFormDlgt(OpenLiveStreamDisplay), this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>Event.None</returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (!displayForm.Completed)
|
||||
{
|
||||
return Event.ModelessFormIsOpen;
|
||||
}
|
||||
|
||||
if (result == DialogResult.None)
|
||||
{
|
||||
/// Save the result (once)
|
||||
selectedImages = displayForm.SelectedImages;
|
||||
result = displayForm.Result;
|
||||
displayForm = null;
|
||||
}
|
||||
|
||||
if (result == DialogResult.OK) return Event.OK;
|
||||
else if (result == DialogResult.Retry) return Event.Retry;
|
||||
else if (result == DialogResult.Abort) return Event.Abort;
|
||||
else return Event.None; /// Should never happen
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (displayForm != null)
|
||||
{
|
||||
displayForm.CloseForm(this, null);
|
||||
displayForm = null;
|
||||
}
|
||||
currentOp = CurrentOp.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
public class DisplayCfg : ComponentCfgBase, IComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(DisplayCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new DisplayCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
DisplayCfg() {}
|
||||
|
||||
public DisplayCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
public partial class DisplayCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
DisplayCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as DisplayCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public DisplayCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PumpCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
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.Name = nameTextBox.Text;
|
||||
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
partial class DisplayCfgCtrl
|
||||
{
|
||||
/// <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.label1 = new System.Windows.Forms.Label();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(99, 34);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(174, 20);
|
||||
this.nameTextBox.TabIndex = 1;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(13, 37);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 0;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(96, 11);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(114, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComponentClassName";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(-211, -147);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(57, 13);
|
||||
this.label1.TabIndex = 5;
|
||||
this.label1.Text = "Arguments";
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Enabled = false;
|
||||
this.textBox1.Location = new System.Drawing.Point(-125, -150);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(372, 20);
|
||||
this.textBox1.TabIndex = 6;
|
||||
//
|
||||
// DisplayCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "DisplayCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(500, 300);
|
||||
this.Load += new System.EventHandler(this.PumpCfgCtrl_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.Label label1;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,197 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
using TBF.Resources;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
public partial class DisplayForm : Form, GenericDevices.IHasCompleted
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(DisplayForm));
|
||||
|
||||
#region Closing this display from another thread
|
||||
|
||||
/// <summary>
|
||||
/// Called from the state machine when an operation forces a modeless dialog close.
|
||||
/// </summary>
|
||||
public void CloseForm(object sender, EventArgs args)
|
||||
{
|
||||
if (CloseFormHandler == null) return;
|
||||
try { CloseFormHandler(sender, null); }
|
||||
catch (Exception e) { log.Error("CloseFormHandler(...) failed", e); }
|
||||
}
|
||||
public event EventHandler<EventArgs> CloseFormHandler;
|
||||
|
||||
public void StartCloseFormHandler()
|
||||
{
|
||||
CloseFormHandler += delegate(object sender, EventArgs args)
|
||||
{
|
||||
if (InvokeRequired) { Invoke(new EventHandler<EventArgs>(OnCloseForm), sender, args); }
|
||||
else OnCloseForm(sender, args);
|
||||
};
|
||||
}
|
||||
|
||||
private void OnCloseForm(object sender, EventArgs args)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary> Number of text boxes for serial numbers </summary>
|
||||
readonly string[] imageFileNames;
|
||||
readonly int imagesCount;
|
||||
|
||||
readonly GroupBox[] groupBoxes;
|
||||
readonly PictureBox[] pictureBoxes;
|
||||
readonly CheckBox[] checkBoxes;
|
||||
readonly int boxesCount;
|
||||
|
||||
Timer myTimer;
|
||||
|
||||
|
||||
public bool[] SelectedImages;
|
||||
public DialogResult Result; /// DialogResult.None OK Retry or Cancel
|
||||
|
||||
|
||||
/// Set to 'true' when the form closes
|
||||
public bool Completed { get { return completed; } }
|
||||
bool completed;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
|
||||
public DisplayForm(string[] imageFileNames, string title)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.imageFileNames = imageFileNames;
|
||||
this.imagesCount = (imageFileNames == null) ? 0 : imageFileNames.Length;
|
||||
|
||||
groupBoxes = new GroupBox[] { groupBox1, groupBox2, groupBox3, groupBox4, groupBox5, groupBox6,
|
||||
groupBox7, groupBox8, groupBox9, groupBox10, groupBox11, groupBox12 };
|
||||
|
||||
pictureBoxes = new PictureBox[] { pictureBox1, pictureBox2, pictureBox3, pictureBox4, pictureBox5, pictureBox6,
|
||||
pictureBox7, pictureBox8, pictureBox9, pictureBox10, pictureBox11, pictureBox12 };
|
||||
|
||||
checkBoxes = new CheckBox[] { checkBox1, checkBox2, checkBox3, checkBox4, checkBox5, checkBox6,
|
||||
checkBox7, checkBox8, checkBox9, checkBox10, checkBox11, checkBox12 };
|
||||
|
||||
boxesCount = pictureBoxes.Length;
|
||||
|
||||
Text = title;
|
||||
|
||||
int lastVisibleGroupBoxIx = 0;
|
||||
for (int i = 0; i < boxesCount; i++)
|
||||
{
|
||||
if (i < imagesCount && !string.IsNullOrEmpty(imageFileNames[i]))
|
||||
{
|
||||
groupBoxes[i].Text = string.Format("{0} {1}", Strings.Water_Meter, i + 1);
|
||||
checkBoxes[i].Checked = true;
|
||||
checkBoxes[i].Text = Strings.Retry;
|
||||
lastVisibleGroupBoxIx = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
groupBoxes[i].Visible = false;
|
||||
checkBoxes[i].Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
SelectedImages = new bool[imagesCount];
|
||||
|
||||
if (lastVisibleGroupBoxIx < 4)
|
||||
Height = 321;
|
||||
else if (lastVisibleGroupBoxIx < 8)
|
||||
Height = 616;
|
||||
|
||||
Result = DialogResult.None;
|
||||
completed = false;
|
||||
StartCloseFormHandler();
|
||||
}
|
||||
|
||||
/// <summary> Parameterless constructor for all watermeters </summary>
|
||||
public DisplayForm()
|
||||
: this(null, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
private void CycleBeginningForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
okButton.Text = Strings.OkBtnText;
|
||||
retryButton.Text = Strings.Retry;
|
||||
abortButton.Text = Strings.Abort;
|
||||
|
||||
myTimer = new Timer();
|
||||
myTimer.Interval = (500);
|
||||
myTimer.Tick += new EventHandler(MyTimer_Tick);
|
||||
myTimer.Start();
|
||||
}
|
||||
|
||||
private void MyTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
for (int i = 0; i < Math.Min(imagesCount, boxesCount); i++)
|
||||
{
|
||||
if (imageFileNames[i] != null && System.IO.File.Exists(imageFileNames[i]) &&
|
||||
pictureBoxes[i] != null && pictureBoxes[i].Image == null)
|
||||
{
|
||||
pictureBoxes[i].Image = Image.FromFile(imageFileNames[i]);
|
||||
checkBoxes[i].Checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void okButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
log.Warn("OK clicked");
|
||||
Result = DialogResult.OK;
|
||||
CloseAfterButtonClick();
|
||||
}
|
||||
|
||||
private void abortButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
log.Warn("Abort clicked");
|
||||
Result = DialogResult.Abort;
|
||||
CloseAfterButtonClick();
|
||||
}
|
||||
|
||||
private void retryButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
log.Warn("Retry clicked");
|
||||
Result = DialogResult.Retry;
|
||||
CloseAfterButtonClick();
|
||||
}
|
||||
|
||||
void CloseAfterButtonClick()
|
||||
{
|
||||
if (myTimer != null) myTimer.Stop();
|
||||
UpdateData();
|
||||
completed = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
void UpdateData()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append("1 ");
|
||||
for (int i = 0; i < Math.Min(imagesCount, boxesCount); i++)
|
||||
{
|
||||
SelectedImages[i] = checkBoxes[i].Checked;
|
||||
sb.AppendFormat("{0}", checkBoxes[i].Checked ? "x" : "-");
|
||||
}
|
||||
sb.AppendFormat(" {0}", Math.Min(imagesCount, boxesCount));
|
||||
|
||||
log.WarnFormat("Data updated: {0}", sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
partial class DisplayForm
|
||||
{
|
||||
/// <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 Windows Form 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()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DisplayForm));
|
||||
this.okButton = new System.Windows.Forms.Button();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox1 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox2 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox2 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox3 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox3 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox4 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox4 = new System.Windows.Forms.PictureBox();
|
||||
this.retryButton = new System.Windows.Forms.Button();
|
||||
this.abortButton = new System.Windows.Forms.Button();
|
||||
this.groupBox5 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox5 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox5 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox6 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox6 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox6 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox7 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox7 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox7 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox8 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox8 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox8 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox9 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox9 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox9 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox10 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox10 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox10 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox11 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox11 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox11 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox12 = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox12 = new System.Windows.Forms.CheckBox();
|
||||
this.pictureBox12 = new System.Windows.Forms.PictureBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.groupBox2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
|
||||
this.groupBox3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit();
|
||||
this.groupBox4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).BeginInit();
|
||||
this.groupBox5.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).BeginInit();
|
||||
this.groupBox6.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox6)).BeginInit();
|
||||
this.groupBox7.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox7)).BeginInit();
|
||||
this.groupBox8.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox8)).BeginInit();
|
||||
this.groupBox9.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox9)).BeginInit();
|
||||
this.groupBox10.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox10)).BeginInit();
|
||||
this.groupBox11.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox11)).BeginInit();
|
||||
this.groupBox12.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox12)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// okButton
|
||||
//
|
||||
resources.ApplyResources(this.okButton, "okButton");
|
||||
this.okButton.ForeColor = System.Drawing.Color.Black;
|
||||
this.okButton.Name = "okButton";
|
||||
this.okButton.UseVisualStyleBackColor = true;
|
||||
this.okButton.Click += new System.EventHandler(this.okButton_Click);
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.checkBox1);
|
||||
this.groupBox1.Controls.Add(this.pictureBox1);
|
||||
resources.ApplyResources(this.groupBox1, "groupBox1");
|
||||
this.groupBox1.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.TabStop = false;
|
||||
//
|
||||
// checkBox1
|
||||
//
|
||||
resources.ApplyResources(this.checkBox1, "checkBox1");
|
||||
this.checkBox1.Name = "checkBox1";
|
||||
this.checkBox1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox1, "pictureBox1");
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.TabStop = false;
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.checkBox2);
|
||||
this.groupBox2.Controls.Add(this.pictureBox2);
|
||||
resources.ApplyResources(this.groupBox2, "groupBox2");
|
||||
this.groupBox2.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.TabStop = false;
|
||||
//
|
||||
// checkBox2
|
||||
//
|
||||
resources.ApplyResources(this.checkBox2, "checkBox2");
|
||||
this.checkBox2.Name = "checkBox2";
|
||||
this.checkBox2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox2
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox2, "pictureBox2");
|
||||
this.pictureBox2.Name = "pictureBox2";
|
||||
this.pictureBox2.TabStop = false;
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this.checkBox3);
|
||||
this.groupBox3.Controls.Add(this.pictureBox3);
|
||||
resources.ApplyResources(this.groupBox3, "groupBox3");
|
||||
this.groupBox3.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox3.Name = "groupBox3";
|
||||
this.groupBox3.TabStop = false;
|
||||
//
|
||||
// checkBox3
|
||||
//
|
||||
resources.ApplyResources(this.checkBox3, "checkBox3");
|
||||
this.checkBox3.Name = "checkBox3";
|
||||
this.checkBox3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox3
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox3, "pictureBox3");
|
||||
this.pictureBox3.Name = "pictureBox3";
|
||||
this.pictureBox3.TabStop = false;
|
||||
//
|
||||
// groupBox4
|
||||
//
|
||||
this.groupBox4.Controls.Add(this.checkBox4);
|
||||
this.groupBox4.Controls.Add(this.pictureBox4);
|
||||
resources.ApplyResources(this.groupBox4, "groupBox4");
|
||||
this.groupBox4.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox4.Name = "groupBox4";
|
||||
this.groupBox4.TabStop = false;
|
||||
//
|
||||
// checkBox4
|
||||
//
|
||||
resources.ApplyResources(this.checkBox4, "checkBox4");
|
||||
this.checkBox4.Name = "checkBox4";
|
||||
this.checkBox4.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox4
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox4, "pictureBox4");
|
||||
this.pictureBox4.Name = "pictureBox4";
|
||||
this.pictureBox4.TabStop = false;
|
||||
//
|
||||
// retryButton
|
||||
//
|
||||
resources.ApplyResources(this.retryButton, "retryButton");
|
||||
this.retryButton.ForeColor = System.Drawing.Color.Black;
|
||||
this.retryButton.Name = "retryButton";
|
||||
this.retryButton.UseVisualStyleBackColor = true;
|
||||
this.retryButton.Click += new System.EventHandler(this.retryButton_Click);
|
||||
//
|
||||
// abortButton
|
||||
//
|
||||
resources.ApplyResources(this.abortButton, "abortButton");
|
||||
this.abortButton.ForeColor = System.Drawing.Color.Black;
|
||||
this.abortButton.Name = "abortButton";
|
||||
this.abortButton.UseVisualStyleBackColor = true;
|
||||
this.abortButton.Click += new System.EventHandler(this.abortButton_Click);
|
||||
//
|
||||
// groupBox5
|
||||
//
|
||||
this.groupBox5.Controls.Add(this.checkBox5);
|
||||
this.groupBox5.Controls.Add(this.pictureBox5);
|
||||
resources.ApplyResources(this.groupBox5, "groupBox5");
|
||||
this.groupBox5.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox5.Name = "groupBox5";
|
||||
this.groupBox5.TabStop = false;
|
||||
//
|
||||
// checkBox5
|
||||
//
|
||||
resources.ApplyResources(this.checkBox5, "checkBox5");
|
||||
this.checkBox5.Name = "checkBox5";
|
||||
this.checkBox5.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox5
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox5, "pictureBox5");
|
||||
this.pictureBox5.Name = "pictureBox5";
|
||||
this.pictureBox5.TabStop = false;
|
||||
//
|
||||
// groupBox6
|
||||
//
|
||||
this.groupBox6.Controls.Add(this.checkBox6);
|
||||
this.groupBox6.Controls.Add(this.pictureBox6);
|
||||
resources.ApplyResources(this.groupBox6, "groupBox6");
|
||||
this.groupBox6.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox6.Name = "groupBox6";
|
||||
this.groupBox6.TabStop = false;
|
||||
//
|
||||
// checkBox6
|
||||
//
|
||||
resources.ApplyResources(this.checkBox6, "checkBox6");
|
||||
this.checkBox6.Name = "checkBox6";
|
||||
this.checkBox6.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox6
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox6, "pictureBox6");
|
||||
this.pictureBox6.Name = "pictureBox6";
|
||||
this.pictureBox6.TabStop = false;
|
||||
//
|
||||
// groupBox7
|
||||
//
|
||||
this.groupBox7.Controls.Add(this.checkBox7);
|
||||
this.groupBox7.Controls.Add(this.pictureBox7);
|
||||
resources.ApplyResources(this.groupBox7, "groupBox7");
|
||||
this.groupBox7.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox7.Name = "groupBox7";
|
||||
this.groupBox7.TabStop = false;
|
||||
//
|
||||
// checkBox7
|
||||
//
|
||||
resources.ApplyResources(this.checkBox7, "checkBox7");
|
||||
this.checkBox7.Name = "checkBox7";
|
||||
this.checkBox7.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox7
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox7, "pictureBox7");
|
||||
this.pictureBox7.Name = "pictureBox7";
|
||||
this.pictureBox7.TabStop = false;
|
||||
//
|
||||
// groupBox8
|
||||
//
|
||||
this.groupBox8.Controls.Add(this.checkBox8);
|
||||
this.groupBox8.Controls.Add(this.pictureBox8);
|
||||
resources.ApplyResources(this.groupBox8, "groupBox8");
|
||||
this.groupBox8.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox8.Name = "groupBox8";
|
||||
this.groupBox8.TabStop = false;
|
||||
//
|
||||
// checkBox8
|
||||
//
|
||||
resources.ApplyResources(this.checkBox8, "checkBox8");
|
||||
this.checkBox8.Name = "checkBox8";
|
||||
this.checkBox8.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox8
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox8, "pictureBox8");
|
||||
this.pictureBox8.Name = "pictureBox8";
|
||||
this.pictureBox8.TabStop = false;
|
||||
//
|
||||
// groupBox9
|
||||
//
|
||||
this.groupBox9.Controls.Add(this.checkBox9);
|
||||
this.groupBox9.Controls.Add(this.pictureBox9);
|
||||
resources.ApplyResources(this.groupBox9, "groupBox9");
|
||||
this.groupBox9.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox9.Name = "groupBox9";
|
||||
this.groupBox9.TabStop = false;
|
||||
//
|
||||
// checkBox9
|
||||
//
|
||||
resources.ApplyResources(this.checkBox9, "checkBox9");
|
||||
this.checkBox9.Name = "checkBox9";
|
||||
this.checkBox9.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox9
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox9, "pictureBox9");
|
||||
this.pictureBox9.Name = "pictureBox9";
|
||||
this.pictureBox9.TabStop = false;
|
||||
//
|
||||
// groupBox10
|
||||
//
|
||||
this.groupBox10.Controls.Add(this.checkBox10);
|
||||
this.groupBox10.Controls.Add(this.pictureBox10);
|
||||
resources.ApplyResources(this.groupBox10, "groupBox10");
|
||||
this.groupBox10.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox10.Name = "groupBox10";
|
||||
this.groupBox10.TabStop = false;
|
||||
//
|
||||
// checkBox10
|
||||
//
|
||||
resources.ApplyResources(this.checkBox10, "checkBox10");
|
||||
this.checkBox10.Name = "checkBox10";
|
||||
this.checkBox10.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox10
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox10, "pictureBox10");
|
||||
this.pictureBox10.Name = "pictureBox10";
|
||||
this.pictureBox10.TabStop = false;
|
||||
//
|
||||
// groupBox11
|
||||
//
|
||||
this.groupBox11.Controls.Add(this.checkBox11);
|
||||
this.groupBox11.Controls.Add(this.pictureBox11);
|
||||
resources.ApplyResources(this.groupBox11, "groupBox11");
|
||||
this.groupBox11.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox11.Name = "groupBox11";
|
||||
this.groupBox11.TabStop = false;
|
||||
//
|
||||
// checkBox11
|
||||
//
|
||||
resources.ApplyResources(this.checkBox11, "checkBox11");
|
||||
this.checkBox11.Name = "checkBox11";
|
||||
this.checkBox11.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox11
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox11, "pictureBox11");
|
||||
this.pictureBox11.Name = "pictureBox11";
|
||||
this.pictureBox11.TabStop = false;
|
||||
//
|
||||
// groupBox12
|
||||
//
|
||||
this.groupBox12.Controls.Add(this.checkBox12);
|
||||
this.groupBox12.Controls.Add(this.pictureBox12);
|
||||
resources.ApplyResources(this.groupBox12, "groupBox12");
|
||||
this.groupBox12.ForeColor = System.Drawing.Color.Black;
|
||||
this.groupBox12.Name = "groupBox12";
|
||||
this.groupBox12.TabStop = false;
|
||||
//
|
||||
// checkBox12
|
||||
//
|
||||
resources.ApplyResources(this.checkBox12, "checkBox12");
|
||||
this.checkBox12.Name = "checkBox12";
|
||||
this.checkBox12.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// pictureBox12
|
||||
//
|
||||
resources.ApplyResources(this.pictureBox12, "pictureBox12");
|
||||
this.pictureBox12.Name = "pictureBox12";
|
||||
this.pictureBox12.TabStop = false;
|
||||
//
|
||||
// DisplayForm
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.DarkGray;
|
||||
this.Controls.Add(this.groupBox12);
|
||||
this.Controls.Add(this.groupBox11);
|
||||
this.Controls.Add(this.groupBox10);
|
||||
this.Controls.Add(this.groupBox9);
|
||||
this.Controls.Add(this.groupBox8);
|
||||
this.Controls.Add(this.groupBox7);
|
||||
this.Controls.Add(this.groupBox6);
|
||||
this.Controls.Add(this.groupBox5);
|
||||
this.Controls.Add(this.abortButton);
|
||||
this.Controls.Add(this.retryButton);
|
||||
this.Controls.Add(this.groupBox4);
|
||||
this.Controls.Add(this.groupBox3);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.okButton);
|
||||
this.ForeColor = System.Drawing.Color.Black;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
|
||||
this.Name = "DisplayForm";
|
||||
this.TopMost = true;
|
||||
this.Load += new System.EventHandler(this.CycleBeginningForm_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
|
||||
this.groupBox3.ResumeLayout(false);
|
||||
this.groupBox3.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit();
|
||||
this.groupBox4.ResumeLayout(false);
|
||||
this.groupBox4.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox4)).EndInit();
|
||||
this.groupBox5.ResumeLayout(false);
|
||||
this.groupBox5.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox5)).EndInit();
|
||||
this.groupBox6.ResumeLayout(false);
|
||||
this.groupBox6.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox6)).EndInit();
|
||||
this.groupBox7.ResumeLayout(false);
|
||||
this.groupBox7.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox7)).EndInit();
|
||||
this.groupBox8.ResumeLayout(false);
|
||||
this.groupBox8.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox8)).EndInit();
|
||||
this.groupBox9.ResumeLayout(false);
|
||||
this.groupBox9.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox9)).EndInit();
|
||||
this.groupBox10.ResumeLayout(false);
|
||||
this.groupBox10.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox10)).EndInit();
|
||||
this.groupBox11.ResumeLayout(false);
|
||||
this.groupBox11.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox11)).EndInit();
|
||||
this.groupBox12.ResumeLayout(false);
|
||||
this.groupBox12.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox12)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button okButton;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.GroupBox groupBox2;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
private System.Windows.Forms.GroupBox groupBox4;
|
||||
private System.Windows.Forms.Button retryButton;
|
||||
private System.Windows.Forms.Button abortButton;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
private System.Windows.Forms.PictureBox pictureBox2;
|
||||
private System.Windows.Forms.PictureBox pictureBox3;
|
||||
private System.Windows.Forms.PictureBox pictureBox4;
|
||||
private System.Windows.Forms.GroupBox groupBox5;
|
||||
private System.Windows.Forms.PictureBox pictureBox5;
|
||||
private System.Windows.Forms.GroupBox groupBox6;
|
||||
private System.Windows.Forms.PictureBox pictureBox6;
|
||||
private System.Windows.Forms.CheckBox checkBox1;
|
||||
private System.Windows.Forms.CheckBox checkBox2;
|
||||
private System.Windows.Forms.CheckBox checkBox3;
|
||||
private System.Windows.Forms.CheckBox checkBox4;
|
||||
private System.Windows.Forms.CheckBox checkBox5;
|
||||
private System.Windows.Forms.CheckBox checkBox6;
|
||||
private System.Windows.Forms.GroupBox groupBox7;
|
||||
private System.Windows.Forms.CheckBox checkBox7;
|
||||
private System.Windows.Forms.PictureBox pictureBox7;
|
||||
private System.Windows.Forms.GroupBox groupBox8;
|
||||
private System.Windows.Forms.CheckBox checkBox8;
|
||||
private System.Windows.Forms.PictureBox pictureBox8;
|
||||
private System.Windows.Forms.GroupBox groupBox9;
|
||||
private System.Windows.Forms.CheckBox checkBox9;
|
||||
private System.Windows.Forms.PictureBox pictureBox9;
|
||||
private System.Windows.Forms.GroupBox groupBox10;
|
||||
private System.Windows.Forms.CheckBox checkBox10;
|
||||
private System.Windows.Forms.PictureBox pictureBox10;
|
||||
private System.Windows.Forms.GroupBox groupBox11;
|
||||
private System.Windows.Forms.CheckBox checkBox11;
|
||||
private System.Windows.Forms.PictureBox pictureBox11;
|
||||
private System.Windows.Forms.GroupBox groupBox12;
|
||||
private System.Windows.Forms.CheckBox checkBox12;
|
||||
private System.Windows.Forms.PictureBox pictureBox12;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Display
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Display.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Display(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Display(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new DisplayCfg(this.GetType().Namespace.Substring(8), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(DisplayCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Roi.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Roi(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Roi(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new RoiCfg(this.GetType().Namespace.Substring(8), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(RoiCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
public class ProcedureParams : ProcedureParamsBase, IParamsProvider, IProcedureParams
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ProcedureParams) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public double PulsesPerLtr; /// [l^-1]
|
||||
public int DetectionImagesCount;
|
||||
public int DetectionPeriod1;
|
||||
public int DetectionPeriod2;
|
||||
public string RoiParams;
|
||||
|
||||
public override void InitializeAll()
|
||||
{
|
||||
PulsesPerLtr = 1.0;
|
||||
DetectionImagesCount = 10;
|
||||
DetectionPeriod1 = 1;
|
||||
DetectionPeriod2 = 19;
|
||||
RoiParams = "160 160 79 79 20 79 0 0 360 360 1 50 0 0 50 0";
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
Strings.PulsesPerLtr,
|
||||
"Images count",
|
||||
"Period1",
|
||||
"Period2",
|
||||
"Parameters"
|
||||
};
|
||||
public override string ParamName(int i) { return paramNames[i]; }
|
||||
public override int ParamsCount() { return paramNames.Length; }
|
||||
|
||||
public override string ToString(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: return PulsesPerLtr.ToString();
|
||||
case 1: return DetectionImagesCount.ToString();
|
||||
case 2: return DetectionPeriod1.ToString();
|
||||
case 3: return DetectionPeriod2.ToString();
|
||||
case 4: return RoiParams;
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves parameters from UI controls
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: PulsesPerLtr = Utils.ParseUDouble(strValue); return CfgUpdateFlags.None;
|
||||
case 1: DetectionImagesCount = int.Parse(strValue); return CfgUpdateFlags.None;
|
||||
case 2: DetectionPeriod1 = int.Parse(strValue); return CfgUpdateFlags.None;
|
||||
case 3: DetectionPeriod2 = int.Parse(strValue); return CfgUpdateFlags.None;
|
||||
case 4: RoiParams = strValue; return CfgUpdateFlags.None;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies whether strings in UI controls represent valid parameters
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
|
||||
double dummy;
|
||||
int idummy;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (Utils.TryParseUDouble(strValue, out dummy)) return true;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
if (int.TryParse(strValue, out idummy) && idummy >= 1 && idummy <= 50) return true;
|
||||
break;
|
||||
case 4:
|
||||
return true;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(ProcedureParams prms)
|
||||
{
|
||||
prms.PulsesPerLtr = this.PulsesPerLtr;
|
||||
prms.DetectionImagesCount = this.DetectionImagesCount;
|
||||
prms.DetectionPeriod1 = this.DetectionPeriod1;
|
||||
prms.DetectionPeriod2 = this.DetectionPeriod2;
|
||||
prms.RoiParams = this.RoiParams;
|
||||
}
|
||||
|
||||
public IParamsProvider Clone()
|
||||
{
|
||||
ProcedureParams pars = new ProcedureParams();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public override void UpdateFromDbEntity(ComponentProcedure dbEntity)
|
||||
{
|
||||
if (dbEntity == null) return;
|
||||
try
|
||||
{
|
||||
ProcedureParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcedureParams;
|
||||
|
||||
procedureParamsEntity = dbEntity;
|
||||
componentName = dbEntity.CmpntName;
|
||||
procedure = dbEntity.Procedure;
|
||||
|
||||
if (tmp != null) tmp.CopyContentTo(this);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public ProcedureParams() { }
|
||||
|
||||
public ProcedureParams(bool initialize)
|
||||
{
|
||||
if (initialize) InitializeAll();
|
||||
}
|
||||
|
||||
public ProcedureParams(ComponentProcedure procedureParamsEntity, string componentName, Procedure procedure)
|
||||
{
|
||||
this.procedureParamsEntity = procedureParamsEntity;
|
||||
this.componentName = componentName;
|
||||
this.procedure = procedure;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
public class Roi : ComponentBase, GenericDevices.IRegReaderLiveCamera, IOperation
|
||||
{
|
||||
/// TODO: Implement support for sharing one camera by multiple ROI-s
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Roi));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}({1})", this.GetType().Namespace.Substring(8), Cfg.ToString(1));
|
||||
}
|
||||
|
||||
///
|
||||
/// Cfg
|
||||
///
|
||||
public readonly RoiCfg RoiCfg;
|
||||
|
||||
public readonly CLP1611.Camera NetCamera;
|
||||
public readonly Roi PreviousRoi;
|
||||
|
||||
///
|
||||
/// ICamera interface functions
|
||||
///
|
||||
public GenericDevices.ICamera Camera { get { return NetCamera as GenericDevices.ICamera; } }
|
||||
|
||||
public int Position
|
||||
{
|
||||
get
|
||||
{
|
||||
int firstDigitPos = Name.IndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' });
|
||||
int position;
|
||||
return (firstDigitPos < 0) ? 0 : (int.TryParse(Name.Substring(firstDigitPos), out position) ? position : 0);
|
||||
}
|
||||
}
|
||||
public Config.Entities.RegisterReaderType RegisterReaderType { get { return Config.Entities.RegisterReaderType.Camera; } }
|
||||
public double PulsesPerLtr { get { return RoiCfg.ProcParams.PulsesPerLtr; } }
|
||||
public double LtrsPerPulse { get { return (PulsesPerLtr <= float.Epsilon) ? 1.0 : (1 / PulsesPerLtr); } }
|
||||
|
||||
int cameraPulses;
|
||||
int pulsesDelta; /// = (WMPulses - cameraPulses) ... WMPulses = cameraPulses + pulsesDelta, Clear() calculates pulsesDelta
|
||||
public int WMPulses { get { return cameraPulses + pulsesDelta; } }
|
||||
|
||||
long cameraTime;
|
||||
long timeDelta; /// = (WMTestTime - cameraTime) ... WMTestTime = cameraTime + timeDelta, Clear() calculates timeDelta
|
||||
public double WMTestTime { get { return (cameraTime + timeDelta) / 1000.0; } }
|
||||
|
||||
int wmRefPulses;
|
||||
public int WMRefPulses { get { return wmRefPulses; } }
|
||||
|
||||
public double WMVolume { get { return LtrsPerPulse * (double)WMPulses; } }
|
||||
|
||||
public double BeginWMState { get { return 0; } } /// Always 0
|
||||
public double EndWMState { get { return WMVolume; } } /// Derived from WMVolume
|
||||
|
||||
|
||||
double volumeStart;
|
||||
public double VolumeStart { get { return volumeStart; } } /// in l
|
||||
|
||||
double volumeEnd;
|
||||
public double VolumeEnd { get { return volumeEnd; } } /// in l
|
||||
|
||||
double timestampStart;
|
||||
public double TimestampStart { get { return timestampStart; } } /// in s
|
||||
|
||||
double timestampEnd;
|
||||
public double TimestampEnd { get { return timestampEnd; } } /// in s
|
||||
|
||||
///
|
||||
/// Roi specific
|
||||
///
|
||||
public bool Detected { get { return detected; } }
|
||||
bool detected;
|
||||
///
|
||||
public Boxes.IntBox RoiX;
|
||||
public Boxes.IntBox RoiY;
|
||||
public Boxes.IntBox RoiWid;
|
||||
public Boxes.IntBox RoiHgh;
|
||||
///
|
||||
public void ClearRoi()
|
||||
{
|
||||
detected = false;
|
||||
}
|
||||
///
|
||||
public void SetRoi(int x, int y, int wid, int hgh)
|
||||
{
|
||||
RoiX.Val = x;
|
||||
RoiY.Val = y;
|
||||
RoiWid.Val = wid;
|
||||
RoiHgh.Val = hgh;
|
||||
detected = true;
|
||||
}
|
||||
///
|
||||
public string ImageFileNamePrefix { get { return imgFileNamePrefix; } }
|
||||
string imgFileNamePrefix;
|
||||
///
|
||||
private int roiHandle;
|
||||
///
|
||||
public void RegisterRoiToCamera()
|
||||
{
|
||||
if (RoiCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
roiHandle = Camera.RegisterRoi(string.Format("-roi 1 300 200 134 134 66 66 20 66 0 0 360 360 1 50 0 0 270 0 bkgnd.bmp"));
|
||||
}
|
||||
else
|
||||
{
|
||||
roiHandle = Camera.RegisterRoi(string.Format("-roi 1 {0} {1} {2} bkgnd.bmp", RoiX.Val, RoiY.Val, RoiCfg.RoiParams));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Roi()
|
||||
{
|
||||
}
|
||||
|
||||
public Roi(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
RoiCfg = cfg as RoiCfg;
|
||||
NetCamera = TbfComponents.FindComponent(cfg.ParentName, components) as CLP1611.Camera;
|
||||
|
||||
PreviousRoi = TbfComponents.FindComponent(RoiCfg.PreviousRoi, components) as Roi;
|
||||
|
||||
detected = false;
|
||||
RoiX = new Boxes.IntBox();
|
||||
RoiY = new Boxes.IntBox();
|
||||
RoiWid = new Boxes.IntBox();
|
||||
RoiHgh = new Boxes.IntBox();
|
||||
|
||||
Clear();
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
#region Configuration Change Handling
|
||||
|
||||
public static void OnCfgChange(object sender, CfgChangeArgs args)
|
||||
{
|
||||
if (CfgChangeHandler == null) return;
|
||||
try { CfgChangeHandler(sender, args); }
|
||||
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
|
||||
}
|
||||
|
||||
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
|
||||
|
||||
public override void StartChangeHandler()
|
||||
{
|
||||
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
|
||||
{
|
||||
RoiCfg tmpcfg = args.Cfg as RoiCfg;
|
||||
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
|
||||
{
|
||||
if (args.Command == CfgChangeCmd.CfgChange)
|
||||
{
|
||||
RoiCfg.LoadImages = tmpcfg.LoadImages;
|
||||
RoiCfg.SaveImages = tmpcfg.SaveImages;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Configuration Change Handling
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
pulsesDelta = -cameraPulses;
|
||||
timeDelta = -cameraTime;
|
||||
wmRefPulses = 0;
|
||||
}
|
||||
|
||||
|
||||
public IOperation RoiDetectionOp()
|
||||
{
|
||||
if (NetCamera != null && RoiCfg.DebugLevel != DebugMode.Simulate)
|
||||
{
|
||||
imgFileNamePrefix = Path.Combine(Program.TempImagesDir, string.Format("t{0}-{1}-", StateMachine.Time, RoiCfg.Name));
|
||||
return new RoiDetectionOp(this, NetCamera, imgFileNamePrefix, RoiX, RoiY, RoiWid, RoiHgh);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null; /// When NetCamera == null or ROI is in simulation mode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IOperation GrabImageOp(string imageFileName, bool blackAndWhite, bool lowResolution, ImageRotation imageRotation)
|
||||
{
|
||||
if (NetCamera != null)
|
||||
{
|
||||
/// TODO: Implement support for sharing one camera by multiple ROI-s
|
||||
return NetCamera.GrabImagesOp(new string[] { imageFileName }, blackAndWhite, lowResolution, imageRotation);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public IOperation GrabImageOp(string imageFileName)
|
||||
{
|
||||
if (NetCamera != null)
|
||||
{
|
||||
/// TODO: Implement support for sharing one camera by multiple ROI-s
|
||||
return NetCamera.GrabImagesOp(new string[] { imageFileName }, false, true, ImageRotation.None);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates wmPulses, caled from 'Start' and 'Run' functions of 'ReadRegisterOp'
|
||||
/// </summary>
|
||||
void UdatePulses()
|
||||
{
|
||||
if (detected && roiHandle != 0)
|
||||
{
|
||||
cameraPulses = NetCamera.GetResult(roiHandle, out cameraTime);
|
||||
}
|
||||
|
||||
wmRefPulses = StateMachine.ControlBoard.RefPulses;
|
||||
}
|
||||
|
||||
///
|
||||
/// Note: Measurement operations of cameras should preceeede ReadRegister operations of ROI-s
|
||||
///
|
||||
public IOperation ReadRegisterOp()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
UdatePulses();
|
||||
Clear();
|
||||
volumeStart = WMVolume;
|
||||
timestampStart = WMTestTime;
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>eventDone</returns>
|
||||
public Event Run()
|
||||
{
|
||||
UdatePulses();
|
||||
volumeEnd = WMVolume;
|
||||
timestampEnd = WMTestTime;
|
||||
return Event.ReadRegisterDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
public class RoiCfg : ComponentCfgBase, IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RoiCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new RoiCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public string PreviousRoi;
|
||||
|
||||
[XmlIgnore]
|
||||
public bool LoadImages;
|
||||
|
||||
[XmlIgnore]
|
||||
public bool SaveImages;
|
||||
|
||||
/// <summary> Procedure parameters </summary>
|
||||
[XmlIgnore]
|
||||
public ProcedureParams ProcParams;
|
||||
public override IParamsProvider GetRuntimeProcParamsProvider() { return ProcParams; }
|
||||
public override IParamsProvider CreateProcParamsProvider() { return new ProcedureParams(true); }
|
||||
|
||||
public int DetectionImagesCount { get { return ProcParams.DetectionImagesCount; } }
|
||||
public int DetectionPeriod1 { get { return ProcParams.DetectionPeriod1; } }
|
||||
public int DetectionPeriod2 { get { return ProcParams.DetectionPeriod2; } }
|
||||
public string RoiParams { get { return ProcParams.RoiParams; } }
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
RoiCfg()
|
||||
{
|
||||
ProcParams = new ProcedureParams(true);
|
||||
}
|
||||
|
||||
public RoiCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = "Camera";
|
||||
DebugLevel = DebugMode.Inherit;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("{0} ({1}) PreviousRoi={2} {3}", Name, ParentName,
|
||||
string.IsNullOrEmpty(PreviousRoi) ? "---" : PreviousRoi,
|
||||
(LoadImages ? " load images" : (SaveImages ? " save images" : "")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
public partial class RoiCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
RoiCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as RoiCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public RoiCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PumpCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
previousRoiComboBox.Items.Add("---");
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
foreach (var cmpnt in parent.CmpntEntities)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is TBF.Rig.Network.Camera.CLP1611.Factory)
|
||||
{
|
||||
parentNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is TBF.Rig.Network.Camera.Roi.Factory)
|
||||
{
|
||||
previousRoiComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
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;
|
||||
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
|
||||
previousRoiComboBox.Text = string.IsNullOrEmpty(config.PreviousRoi) ? "---" : config.PreviousRoi;
|
||||
loadImagesCheckBox.Checked = config.LoadImages;
|
||||
saveImagesCheckBox.Checked = config.SaveImages;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
previousRoiComboBox.Enabled = true;
|
||||
loadImagesCheckBox.Enabled = true;
|
||||
saveImagesCheckBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Parent Name'";
|
||||
}
|
||||
|
||||
if (!previousRoiComboBox.Items.Contains(previousRoiComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Previous RoI'";
|
||||
}
|
||||
|
||||
if (loadImagesCheckBox.Checked && saveImagesCheckBox.Checked)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Images cannot be Loaded and Saved at the same time";
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
string newParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
|
||||
string newPreviousRoi = previousRoiComboBox.Text.Equals("---") ? string.Empty : previousRoiComboBox.Text;
|
||||
|
||||
if (config.Name != nameTextBox.Text ||
|
||||
config.ParentName != newParentName ||
|
||||
config.PreviousRoi != newPreviousRoi)
|
||||
{
|
||||
config.Name = nameTextBox.Text;
|
||||
config.ParentName = newParentName;
|
||||
config.PreviousRoi = newPreviousRoi;
|
||||
|
||||
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
if (config.LoadImages != loadImagesCheckBox.Checked ||
|
||||
config.SaveImages != saveImagesCheckBox.Checked)
|
||||
{
|
||||
config.LoadImages = loadImagesCheckBox.Checked;
|
||||
config.SaveImages = saveImagesCheckBox.Checked;
|
||||
|
||||
flags |= (CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.VolatileChange);
|
||||
}
|
||||
|
||||
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
||||
{
|
||||
Roi.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
partial class RoiCfgCtrl
|
||||
{
|
||||
/// <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.parentNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.previousRoiComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.previousRoiLabel = new System.Windows.Forms.Label();
|
||||
this.helpLabel1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.loadImagesCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.saveImagesCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(13, 60);
|
||||
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(99, 34);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(174, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(13, 37);
|
||||
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(96, 11);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(114, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComponentClassName";
|
||||
//
|
||||
// parentNameComboBox
|
||||
//
|
||||
this.parentNameComboBox.Enabled = false;
|
||||
this.parentNameComboBox.FormattingEnabled = true;
|
||||
this.parentNameComboBox.Location = new System.Drawing.Point(99, 57);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(174, 21);
|
||||
this.parentNameComboBox.TabIndex = 4;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(-211, -147);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(57, 13);
|
||||
this.label1.TabIndex = 5;
|
||||
this.label1.Text = "Arguments";
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Enabled = false;
|
||||
this.textBox1.Location = new System.Drawing.Point(-125, -150);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(372, 20);
|
||||
this.textBox1.TabIndex = 6;
|
||||
//
|
||||
// previousRoiComboBox
|
||||
//
|
||||
this.previousRoiComboBox.Enabled = false;
|
||||
this.previousRoiComboBox.FormattingEnabled = true;
|
||||
this.previousRoiComboBox.Location = new System.Drawing.Point(99, 81);
|
||||
this.previousRoiComboBox.Name = "previousRoiComboBox";
|
||||
this.previousRoiComboBox.Size = new System.Drawing.Size(174, 21);
|
||||
this.previousRoiComboBox.TabIndex = 6;
|
||||
//
|
||||
// previousRoiLabel
|
||||
//
|
||||
this.previousRoiLabel.AutoSize = true;
|
||||
this.previousRoiLabel.Location = new System.Drawing.Point(13, 84);
|
||||
this.previousRoiLabel.Name = "previousRoiLabel";
|
||||
this.previousRoiLabel.Size = new System.Drawing.Size(68, 13);
|
||||
this.previousRoiLabel.TabIndex = 5;
|
||||
this.previousRoiLabel.Text = "Previous RoI";
|
||||
//
|
||||
// helpLabel1
|
||||
//
|
||||
this.helpLabel1.AutoSize = true;
|
||||
this.helpLabel1.Location = new System.Drawing.Point(38, 186);
|
||||
this.helpLabel1.Name = "helpLabel1";
|
||||
this.helpLabel1.Size = new System.Drawing.Size(379, 13);
|
||||
this.helpLabel1.TabIndex = 2;
|
||||
this.helpLabel1.Text = "roiWid roiHgh cx cy innerR outerR R3 ang1 ang2 fullAngle teethCount ..." +
|
||||
"";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(68, 204);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(350, 13);
|
||||
this.label2.TabIndex = 3;
|
||||
this.label2.Text = "... angSpeed( - ccw +cw) initSpeed minMvmt maxFwdMvmt bkgndCorr";
|
||||
//
|
||||
// loadImagesCheckBox
|
||||
//
|
||||
this.loadImagesCheckBox.AutoSize = true;
|
||||
this.loadImagesCheckBox.Enabled = false;
|
||||
this.loadImagesCheckBox.Location = new System.Drawing.Point(99, 117);
|
||||
this.loadImagesCheckBox.Name = "loadImagesCheckBox";
|
||||
this.loadImagesCheckBox.Size = new System.Drawing.Size(112, 17);
|
||||
this.loadImagesCheckBox.TabIndex = 6;
|
||||
this.loadImagesCheckBox.Text = "Load images (test)";
|
||||
this.loadImagesCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// saveImagesCheckBox
|
||||
//
|
||||
this.saveImagesCheckBox.AutoSize = true;
|
||||
this.saveImagesCheckBox.Enabled = false;
|
||||
this.saveImagesCheckBox.Location = new System.Drawing.Point(99, 140);
|
||||
this.saveImagesCheckBox.Name = "saveImagesCheckBox";
|
||||
this.saveImagesCheckBox.Size = new System.Drawing.Size(132, 17);
|
||||
this.saveImagesCheckBox.TabIndex = 7;
|
||||
this.saveImagesCheckBox.Text = "Save images (analyze)";
|
||||
this.saveImagesCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RoiCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.helpLabel1);
|
||||
this.Controls.Add(this.saveImagesCheckBox);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.previousRoiComboBox);
|
||||
this.Controls.Add(this.previousRoiLabel);
|
||||
this.Controls.Add(this.loadImagesCheckBox);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "RoiCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(500, 300);
|
||||
this.Load += new System.EventHandler(this.PumpCfgCtrl_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 classNameLabel;
|
||||
private System.Windows.Forms.ComboBox parentNameComboBox;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.ComboBox previousRoiComboBox;
|
||||
private System.Windows.Forms.Label previousRoiLabel;
|
||||
private System.Windows.Forms.Label helpLabel1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.CheckBox loadImagesCheckBox;
|
||||
private System.Windows.Forms.CheckBox saveImagesCheckBox;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,209 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Rig.Network.Telnet;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.Roi
|
||||
{
|
||||
public class RoiDetectionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RoiDetectionOp));
|
||||
public override string ToString() { return string.Format("RoiDetectionOp()"); }
|
||||
|
||||
|
||||
readonly Roi roi;
|
||||
readonly RoiCfg roiCfg;
|
||||
readonly CLP1611.Camera camera;
|
||||
readonly Telnet.TelnetClient telnet;
|
||||
readonly string imgFileNamePrefix;
|
||||
|
||||
string command;
|
||||
bool roiDetectionCommandSent;
|
||||
bool transferringDetectedImage;
|
||||
|
||||
string response;
|
||||
bool passed;
|
||||
bool failed;
|
||||
bool previousFailed;
|
||||
|
||||
Boxes.IntBox roiX;
|
||||
Boxes.IntBox roiY;
|
||||
Boxes.IntBox roiWid;
|
||||
Boxes.IntBox roiHgh; /// Wid and Hgh are usefull when masking
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Events: Event.None or Event.Error
|
||||
/// </summary>
|
||||
/// <param name="camera">CLP1611.Camera reference</param>
|
||||
public RoiDetectionOp(Roi roi, CLP1611.Camera camera, string imgFileNamePrefix,
|
||||
Boxes.IntBox roiX, Boxes.IntBox roiY,
|
||||
Boxes.IntBox roiWid, Boxes.IntBox roiHgh)
|
||||
{
|
||||
this.roi = roi;
|
||||
this.roiCfg = roi.RoiCfg;
|
||||
this.camera = camera;
|
||||
this.telnet = camera.Telnet;
|
||||
this.imgFileNamePrefix = imgFileNamePrefix;
|
||||
this.roiX = roiX;
|
||||
this.roiY = roiY;
|
||||
this.roiWid = roiWid;
|
||||
this.roiHgh = roiHgh;
|
||||
|
||||
roiDetectionCommandSent = false;
|
||||
transferringDetectedImage = false;
|
||||
|
||||
telnet.promptReceivedHandler += delegate(object sndr, PromptReceivedEventArgs a)
|
||||
{
|
||||
OnPromptReceived(sndr, a);
|
||||
};
|
||||
}
|
||||
|
||||
void OnPromptReceived(object sndr, PromptReceivedEventArgs a)
|
||||
{
|
||||
response = a.Response;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
roiDetectionCommandSent = false;
|
||||
transferringDetectedImage = false;
|
||||
}
|
||||
|
||||
public Event Run()
|
||||
{
|
||||
if (!roiDetectionCommandSent)
|
||||
{
|
||||
if (telnet.State == TelnetClient.TelnetState.Inactive)
|
||||
{
|
||||
//
|
||||
// State variables
|
||||
//
|
||||
response = null;
|
||||
passed = false;
|
||||
failed = false;
|
||||
previousFailed = false;
|
||||
|
||||
//
|
||||
// Prepare command
|
||||
//
|
||||
string masks = string.Empty;
|
||||
Roi previous = roi.PreviousRoi;
|
||||
int maskLevel = 0;
|
||||
while (previous != null && maskLevel++ < 3)
|
||||
{
|
||||
if (!previous.Detected)
|
||||
{
|
||||
previousFailed = true;
|
||||
return Event.RoiDetectionPreviousFailed;
|
||||
}
|
||||
|
||||
masks += string.Format(" -m {0} {1} {2} {3}", previous.RoiX.Val, previous.RoiY.Val,
|
||||
previous.RoiWid.Val, previous.RoiHgh.Val);
|
||||
previous = previous.PreviousRoi;
|
||||
}
|
||||
command = string.Format("clp/RoiDetection{0}{1}{2}{3}{4} {5}",
|
||||
masks,
|
||||
string.Format(roiCfg.LoadImages ? " -l {0}" : " -n {0}", roiCfg.DetectionImagesCount),
|
||||
roiCfg.SaveImages ? " -s -jpg" : "",
|
||||
string.Format(" -p1 {0}", roiCfg.DetectionPeriod1),
|
||||
string.Format(" -p2 {0}", roiCfg.DetectionPeriod2),
|
||||
roiCfg.RoiParams);
|
||||
|
||||
//
|
||||
// Send (or enqueue) command
|
||||
//
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.CLEAR_RESPONSE));
|
||||
telnet.Enqueue(new Telnet.Command(Telnet.CmdAction.SEND_COMMAND, command));
|
||||
roiDetectionCommandSent = true;
|
||||
log.WarnFormat("{0}/{1} command={2}", roiCfg.Name, camera.Name, command);
|
||||
}
|
||||
return Event.CameraBusy;
|
||||
}
|
||||
else if (passed)
|
||||
{
|
||||
if (transferringDetectedImage)
|
||||
{
|
||||
/// ROI detection passed and image transfer is in progress
|
||||
return Event.RoiDetectionPassed;
|
||||
}
|
||||
else if (0 == camera.DownloadFile("detected.jpg", imgFileNamePrefix + "detected.jpg"))
|
||||
{
|
||||
/// File transfer successfully started
|
||||
transferringDetectedImage = true;
|
||||
return Event.RoiDetectionPassed;
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Wait until the previous image transfer completes
|
||||
return Event.CameraBusy;
|
||||
}
|
||||
}
|
||||
else if (failed)
|
||||
{
|
||||
/// ROI detection failed, there in no image to transfer
|
||||
return Event.RoiDetectionFailed;
|
||||
}
|
||||
else if (previousFailed)
|
||||
{
|
||||
return Event.RoiDetectionPreviousFailed;
|
||||
}
|
||||
else if (response != null)
|
||||
{
|
||||
int from = response.IndexOf('[');
|
||||
int to = response.IndexOf(']');
|
||||
if (!response.Contains("RESULT=0\r\n") || from < 0 || to < 0 || to < from)
|
||||
{
|
||||
roi.ClearRoi();
|
||||
failed = true;
|
||||
log.WarnFormat("{0}/{1} Detection failed: {2}", roiCfg.Name, camera.Name, response);
|
||||
return Event.RoiDetectionFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
string oroiStr = response.Substring(from + 1, to - from - 1);
|
||||
string[] terms = oroiStr.Split(new char[] { ',' });
|
||||
int x, y, w, h;
|
||||
if (terms.Length != 5 || !int.TryParse(terms[0], out x) || !int.TryParse(terms[1], out y)
|
||||
|| !int.TryParse(terms[2], out w) || !int.TryParse(terms[3], out h))
|
||||
{
|
||||
roi.ClearRoi();
|
||||
failed = true;
|
||||
log.WarnFormat("{0}/{1} Cannot parse response: {2}", roiCfg.Name, camera.Name, response);
|
||||
return Event.RoiDetectionFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
roi.SetRoi(x, y, w, h);
|
||||
log.WarnFormat("{0}/{1} Detection PASSED: x={2} y={3} w={4} h={5}", roiCfg.Name, camera.Name, x, y, w, h);
|
||||
passed = true;
|
||||
|
||||
///
|
||||
/// Start the file transfer
|
||||
///
|
||||
if (0 == camera.DownloadFile("detected.jpg", imgFileNamePrefix + "detected.jpg"))
|
||||
{
|
||||
/// File transfer successfully started
|
||||
transferringDetectedImage = true;
|
||||
return Event.RoiDetectionPassed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.CameraBusy; /// File transfer not started yet
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.CameraBusy;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.RoiForFixedStart
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Roi.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Roi(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Roi(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new RoiCfg(this.GetType().Namespace.Substring(8), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(RoiCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.RoiForFixedStart
|
||||
{
|
||||
public class ProcedureParams : ProcedureParamsBase, IParamsProvider, IProcedureParams
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ProcedureParams) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public double PulsesPerLtr; /// [l^-1]
|
||||
|
||||
public override void InitializeAll()
|
||||
{
|
||||
PulsesPerLtr = 1.0;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
Strings.PulsesPerLtr,
|
||||
};
|
||||
public override string ParamName(int i) { return paramNames[i]; }
|
||||
public override int ParamsCount() { return paramNames.Length; }
|
||||
|
||||
public override string ToString(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: return PulsesPerLtr.ToString();
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves parameters from UI controls
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: PulsesPerLtr = Utils.ParseUDouble(strValue); return CfgUpdateFlags.None;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies whether strings in UI controls represent valid parameters
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
|
||||
double dummy;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (Utils.TryParseUDouble(strValue, out dummy)) return true;
|
||||
break;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(ProcedureParams prms)
|
||||
{
|
||||
prms.PulsesPerLtr = this.PulsesPerLtr;
|
||||
}
|
||||
|
||||
public IParamsProvider Clone()
|
||||
{
|
||||
ProcedureParams pars = new ProcedureParams();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public override void UpdateFromDbEntity(ComponentProcedure dbEntity)
|
||||
{
|
||||
if (dbEntity == null) return;
|
||||
try
|
||||
{
|
||||
ProcedureParams tmp = Serializer.Deserialize(new StringReader(dbEntity.Parameters)) as ProcedureParams;
|
||||
|
||||
procedureParamsEntity = dbEntity;
|
||||
componentName = dbEntity.CmpntName;
|
||||
procedure = dbEntity.Procedure;
|
||||
|
||||
if (tmp != null) tmp.CopyContentTo(this);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public ProcedureParams() { }
|
||||
|
||||
public ProcedureParams(bool initialize)
|
||||
{
|
||||
if (initialize) InitializeAll();
|
||||
}
|
||||
|
||||
public ProcedureParams(ComponentProcedure procedureParamsEntity, string componentName, Procedure procedure)
|
||||
{
|
||||
this.procedureParamsEntity = procedureParamsEntity;
|
||||
this.componentName = componentName;
|
||||
this.procedure = procedure;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.RoiForFixedStart
|
||||
{
|
||||
public class Roi : ComponentBase, GenericDevices.IRegReaderStillCamera, IOperation
|
||||
{
|
||||
/// TODO: Implement support for sharing one camera by multiple ROI-s
|
||||
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Roi));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}({1})", this.GetType().Namespace.Substring(8), Cfg.ToString(1));
|
||||
}
|
||||
|
||||
///
|
||||
/// Cfg
|
||||
///
|
||||
readonly RoiCfg roiCfg;
|
||||
|
||||
///
|
||||
/// Camera and ICamera
|
||||
///
|
||||
public readonly CLP1611.Camera NetCamera;
|
||||
public GenericDevices.ICamera Camera { get { return NetCamera as GenericDevices.ICamera; } }
|
||||
|
||||
public int Position
|
||||
{
|
||||
get
|
||||
{
|
||||
int firstDigitPos = Name.IndexOfAny(new char[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' });
|
||||
int position;
|
||||
return (firstDigitPos < 0) ? 0 : (int.TryParse(Name.Substring(firstDigitPos), out position) ? position : 0);
|
||||
}
|
||||
}
|
||||
public Config.Entities.RegisterReaderType RegisterReaderType { get { return Config.Entities.RegisterReaderType.Manual; } }
|
||||
public double PulsesPerLtr { get { return roiCfg.ProcParams.PulsesPerLtr; } }
|
||||
public double LtrsPerPulse { get { return (PulsesPerLtr <= float.Epsilon) ? 1.0 : (1 / PulsesPerLtr); } }
|
||||
|
||||
|
||||
double beginWMState;
|
||||
public double BeginWMState
|
||||
{
|
||||
get { return beginWMState; }
|
||||
set { beginWMState = value; }
|
||||
}
|
||||
|
||||
double endWMState;
|
||||
public double EndWMState
|
||||
{
|
||||
get { return endWMState; }
|
||||
set { endWMState = value; }
|
||||
}
|
||||
|
||||
public double WMVolume { get { return endWMState - beginWMState; } }
|
||||
|
||||
public int WMPulses { get { return (int)(WMVolume / LtrsPerPulse); } }
|
||||
|
||||
int wmRefPulses;
|
||||
public int WMRefPulses { get { return wmRefPulses; } }
|
||||
|
||||
|
||||
public Roi()
|
||||
{
|
||||
}
|
||||
|
||||
public Roi(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
roiCfg = cfg as RoiCfg;
|
||||
NetCamera = TbfComponents.FindComponent(cfg.ParentName, components) as CLP1611.Camera;
|
||||
|
||||
Clear();
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
#region Configuration Change Handling
|
||||
|
||||
public static void OnCfgChange(object sender, CfgChangeArgs args)
|
||||
{
|
||||
if (CfgChangeHandler == null) return;
|
||||
try { CfgChangeHandler(sender, args); }
|
||||
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
|
||||
}
|
||||
|
||||
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
|
||||
|
||||
public override void StartChangeHandler()
|
||||
{
|
||||
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
|
||||
{
|
||||
RoiCfg tmpcfg = args.Cfg as RoiCfg;
|
||||
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
|
||||
{
|
||||
if (args.Command == CfgChangeCmd.CfgChange)
|
||||
{
|
||||
roiCfg.BlackAndWhite = tmpcfg.BlackAndWhite;
|
||||
roiCfg.LowResolution = tmpcfg.LowResolution;
|
||||
roiCfg.ImageRotation = tmpcfg.ImageRotation;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Configuration Change Handling
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
log.DebugFormat("{0}:Clear()", Name);
|
||||
beginWMState = 0;
|
||||
endWMState = 0;
|
||||
wmRefPulses = 0;
|
||||
}
|
||||
|
||||
private void ReadPulses()
|
||||
{
|
||||
wmRefPulses = StateMachine.ControlBoard.RefPulses;
|
||||
}
|
||||
|
||||
|
||||
public IOperation GrabImageOp(string imageFileName)
|
||||
{
|
||||
return GrabImageOp(imageFileName, roiCfg.BlackAndWhite, roiCfg.LowResolution, roiCfg.ImageRotation);
|
||||
}
|
||||
|
||||
public IOperation GrabImageOp(string imageFileName,
|
||||
bool blackAndWhite, bool lowResolution, Config.Entities.ImageRotation imageRotation)
|
||||
{
|
||||
if (NetCamera != null)
|
||||
{
|
||||
/// TODO: Implement support for sharing one camera by multiple ROI-s
|
||||
return NetCamera.GrabImagesOp(new string[] { imageFileName }, blackAndWhite, lowResolution, imageRotation);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Events: Event.ReadRegisterDone
|
||||
/// </summary>
|
||||
/// <returns>ReadWaterMeter instance reference casted to IOperaton</returns>
|
||||
public IOperation ReadRegisterOp()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
ReadPulses();
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>eventDone</returns>
|
||||
public Event Run()
|
||||
{
|
||||
ReadPulses();
|
||||
return Event.ReadRegisterDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.RoiForFixedStart
|
||||
{
|
||||
public class RoiCfg : ComponentCfgBase, IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RoiCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new RoiCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public bool BlackAndWhite;
|
||||
public bool LowResolution;
|
||||
public ImageRotation ImageRotation;
|
||||
|
||||
/// <summary> Procedure parameters </summary>
|
||||
[XmlIgnore]
|
||||
public ProcedureParams ProcParams;
|
||||
public override IParamsProvider GetRuntimeProcParamsProvider() { return ProcParams; }
|
||||
public override IParamsProvider CreateProcParamsProvider() { return new ProcedureParams(true); }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
RoiCfg()
|
||||
{
|
||||
ProcParams = new ProcedureParams(true);
|
||||
}
|
||||
|
||||
public RoiCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = "Camera";
|
||||
BlackAndWhite = false;
|
||||
LowResolution = true;
|
||||
ImageRotation = ImageRotation.None;
|
||||
DebugLevel = DebugMode.Inherit;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("{0} Camera={1} B&W={2}, LowRes={3}, Rotation={4}",
|
||||
Name, ParentName, BlackAndWhite, LowResolution, ImageRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.Network.Camera.RoiForFixedStart
|
||||
{
|
||||
public partial class RoiCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
static readonly ILog log = LogManager.GetLogger(typeof(RoiCfgCtrl));
|
||||
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
RoiCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as RoiCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public RoiCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PumpCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
foreach (var cmpnt in parent.CmpntEntities)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is TBF.Rig.Network.Camera.CLP1611.Factory)
|
||||
{
|
||||
parentNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ImageRotation ir = 0; ir < ImageRotation.Count; ir++)
|
||||
{
|
||||
imageRotationComboBox.Items.Add(ir.ToDescription());
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
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;
|
||||
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
|
||||
blackAndWhiteCheckBox.Checked = config.BlackAndWhite;
|
||||
loResolutionCheckBox.Checked = config.LowResolution;
|
||||
imageRotationComboBox.Text = config.ImageRotation.ToDescription();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
blackAndWhiteCheckBox.Enabled = true;
|
||||
loResolutionCheckBox.Enabled = true;
|
||||
imageRotationComboBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, parentNameLabel.Text);
|
||||
}
|
||||
|
||||
if (!imageRotationComboBox.Items.Contains(imageRotationComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, imageRotationLabel.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.Name = nameTextBox.Text;
|
||||
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
string newParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
|
||||
if (config.ParentName != newParentName)
|
||||
{
|
||||
config.ParentName = newParentName;
|
||||
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
if (config.BlackAndWhite != blackAndWhiteCheckBox.Checked)
|
||||
{
|
||||
config.BlackAndWhite = blackAndWhiteCheckBox.Checked;
|
||||
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.InvokeCfgChange);
|
||||
}
|
||||
|
||||
if (config.LowResolution != loResolutionCheckBox.Checked)
|
||||
{
|
||||
config.LowResolution = loResolutionCheckBox.Checked;
|
||||
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.InvokeCfgChange);
|
||||
}
|
||||
|
||||
for (ImageRotation ir = 0; ir < ImageRotation.Count; ir++)
|
||||
{
|
||||
if (imageRotationComboBox.Text == ir.ToDescription())
|
||||
{
|
||||
if (config.ImageRotation != ir)
|
||||
{
|
||||
config.ImageRotation = ir;
|
||||
flags |= (CfgUpdateFlags.AnyChange | CfgUpdateFlags.InvokeCfgChange);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
||||
{
|
||||
Roi.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
#region Configuration Change Handling
|
||||
|
||||
public static void OnCmdResponse(object sender, CmdResponseArgs args)
|
||||
{
|
||||
if (CmdResponseHandler == null) return;
|
||||
try { CmdResponseHandler(sender, args); }
|
||||
catch (Exception e) { log.Error("CmdResponseHandler(...) failed", e); }
|
||||
}
|
||||
|
||||
public static event EventHandler<CmdResponseArgs> CmdResponseHandler;
|
||||
|
||||
public void StartResponseHandler() { }
|
||||
public void StopResponseHandler() { }
|
||||
|
||||
#endregion Configuration Change Handling
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Camera.RoiForFixedStart
|
||||
{
|
||||
partial class RoiCfgCtrl
|
||||
{
|
||||
/// <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.parentNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.imageRotationComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.imageRotationLabel = new System.Windows.Forms.Label();
|
||||
this.blackAndWhiteCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.loResolutionCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(20, 77);
|
||||
this.parentNameLabel.Name = "parentNameLabel";
|
||||
this.parentNameLabel.Size = new System.Drawing.Size(43, 13);
|
||||
this.parentNameLabel.TabIndex = 3;
|
||||
this.parentNameLabel.Text = "Camera";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(139, 49);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(174, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(20, 52);
|
||||
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(136, 26);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(114, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComponentClassName";
|
||||
//
|
||||
// parentNameComboBox
|
||||
//
|
||||
this.parentNameComboBox.Enabled = false;
|
||||
this.parentNameComboBox.FormattingEnabled = true;
|
||||
this.parentNameComboBox.Location = new System.Drawing.Point(139, 74);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(174, 21);
|
||||
this.parentNameComboBox.TabIndex = 4;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(-211, -147);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(57, 13);
|
||||
this.label1.TabIndex = 5;
|
||||
this.label1.Text = "Arguments";
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Enabled = false;
|
||||
this.textBox1.Location = new System.Drawing.Point(-125, -150);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(372, 20);
|
||||
this.textBox1.TabIndex = 6;
|
||||
//
|
||||
// imageRotationComboBox
|
||||
//
|
||||
this.imageRotationComboBox.Enabled = false;
|
||||
this.imageRotationComboBox.FormattingEnabled = true;
|
||||
this.imageRotationComboBox.Location = new System.Drawing.Point(139, 154);
|
||||
this.imageRotationComboBox.Name = "imageRotationComboBox";
|
||||
this.imageRotationComboBox.Size = new System.Drawing.Size(93, 21);
|
||||
this.imageRotationComboBox.TabIndex = 8;
|
||||
//
|
||||
// imageRotationLabel
|
||||
//
|
||||
this.imageRotationLabel.AutoSize = true;
|
||||
this.imageRotationLabel.Location = new System.Drawing.Point(20, 157);
|
||||
this.imageRotationLabel.Name = "imageRotationLabel";
|
||||
this.imageRotationLabel.Size = new System.Drawing.Size(103, 13);
|
||||
this.imageRotationLabel.TabIndex = 7;
|
||||
this.imageRotationLabel.Text = "Image rotation (ccw)";
|
||||
//
|
||||
// blackAndWhiteCheckBox
|
||||
//
|
||||
this.blackAndWhiteCheckBox.AutoSize = true;
|
||||
this.blackAndWhiteCheckBox.Enabled = false;
|
||||
this.blackAndWhiteCheckBox.Location = new System.Drawing.Point(139, 108);
|
||||
this.blackAndWhiteCheckBox.Name = "blackAndWhiteCheckBox";
|
||||
this.blackAndWhiteCheckBox.Size = new System.Drawing.Size(93, 17);
|
||||
this.blackAndWhiteCheckBox.TabIndex = 5;
|
||||
this.blackAndWhiteCheckBox.Text = "Black && White";
|
||||
this.blackAndWhiteCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// loResolutionCheckBox
|
||||
//
|
||||
this.loResolutionCheckBox.AutoSize = true;
|
||||
this.loResolutionCheckBox.Enabled = false;
|
||||
this.loResolutionCheckBox.Location = new System.Drawing.Point(139, 131);
|
||||
this.loResolutionCheckBox.Name = "loResolutionCheckBox";
|
||||
this.loResolutionCheckBox.Size = new System.Drawing.Size(94, 17);
|
||||
this.loResolutionCheckBox.TabIndex = 6;
|
||||
this.loResolutionCheckBox.Text = "Low resolution";
|
||||
this.loResolutionCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RoiCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.imageRotationComboBox);
|
||||
this.Controls.Add(this.imageRotationLabel);
|
||||
this.Controls.Add(this.blackAndWhiteCheckBox);
|
||||
this.Controls.Add(this.loResolutionCheckBox);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "RoiCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(500, 300);
|
||||
this.Load += new System.EventHandler(this.PumpCfgCtrl_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 classNameLabel;
|
||||
private System.Windows.Forms.ComboBox parentNameComboBox;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.ComboBox imageRotationComboBox;
|
||||
private System.Windows.Forms.Label imageRotationLabel;
|
||||
private System.Windows.Forms.CheckBox blackAndWhiteCheckBox;
|
||||
private System.Windows.Forms.CheckBox loResolutionCheckBox;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TBF.Rig.Network.Telnet
|
||||
{
|
||||
/// <summary>
|
||||
/// One part of the telnet client command, which consists of a pair CmdAction action and string str.
|
||||
/// </summary>
|
||||
public enum CmdAction
|
||||
{
|
||||
VOID = 0, /// Blank (uninitialized) action. 'str' is not used.
|
||||
CONNECT, /// Connect (=open a TCP socket and log in). 'str'=hostname. Notify by 'Connected' event.
|
||||
SET_PROMPT, /// Set a prompt string used in comparisons when executing ..._WAIT4PROMPT. 'str'=prompt.
|
||||
CLEAR_RESPONSE, /// Clear received response buffer. 'str' is not used. Note: Response buffer is cleared also after a detected prompt.
|
||||
SEND_STRING, /// Send a string and do nothing else. 'str'=string to be sent.
|
||||
SEND_MSRMNT_CMD, /// Send a string and extract measurements from received data (filter received data)
|
||||
SEND_COMMAND, /// Send a string and WAIT for a PROMPT. 'str'=string to be sent. Notify by 'PromptReceived' event.
|
||||
REBOOT_RECONNECT, /// Send 'reboot' command (if connected), wait a while and reconect. 'str' is not used. Notify by 'Connected' event.
|
||||
EXIT_RECONNECT, /// Send 'exit' (terminate telnet session) and reconect. 'str' is not used. Notify using 'Connected' event.
|
||||
DISCONNECT, /// Send 'exit' to disconnect, do not reconnect. 'str' is not used.
|
||||
TERMINATE, /// Terminate worker thread (should be done once before TelnetClient destruction. 'str' is not used.
|
||||
LABEL, /// Label marking the start of item commands, 'str' identifies the item.
|
||||
NOTIFICATION, /// Notify by 'Notification' event when this command is processed. 'str'=notification ID-string
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Telnet client command. Consists of a pair 'action', 'str'
|
||||
/// CmdAction 'action' specifies the action to be taken.
|
||||
/// string 'str' is (in most cases) the string to be sent, however it might be a hostname or a prompt.
|
||||
/// </summary>
|
||||
public struct Command
|
||||
{
|
||||
/// Private fields
|
||||
CmdAction action; /// Telnet client action to be taken, e.g. 'send a command'
|
||||
string str; /// String argument, e.g. a Linux command to be sent.
|
||||
int duration; /// Expected duration of the command in [s], 0 = immediate, -1 = unknown
|
||||
int timeout; /// Timeout period for the command in [s], 0 = no timeout
|
||||
Regex fatalRegex; /// A compiled regular expression for a fatal error, or null (null=no fatal error detection)
|
||||
Regex errorRegex; /// A compiled regular expression for an error, or null (null=no error detection)
|
||||
Regex warningRegex; /// A compiled regular expression for a warning, or null (null=no warning detection)
|
||||
Regex successRegex; /// A compiled regular expression for a success, or null (null=no success detection)
|
||||
|
||||
/// Public read only properties
|
||||
public CmdAction Action { get { return action; } }
|
||||
public string Str { get { return str; } }
|
||||
public int Duration { get { return duration; } }
|
||||
public int Timeout { get { return timeout; } }
|
||||
public Regex FatalRegex { get { return fatalRegex; } }
|
||||
public Regex ErrorRegex { get { return errorRegex; } }
|
||||
public Regex WarningRegex { get { return warningRegex; } }
|
||||
public Regex SuccessRegex { get { return successRegex; } }
|
||||
|
||||
///
|
||||
/// Various constructors:
|
||||
/// - duration and timeout are in seconds
|
||||
/// - if timeout and duration is not supplied, timeout=0, duration=0 (timeout switched off)
|
||||
/// - if string is not supplied, null is used
|
||||
///
|
||||
public Command(CmdAction action, string str, int duration, int timeout,
|
||||
Regex fatalRegex, Regex errorRegex, Regex warningRegex, Regex successRegex)
|
||||
{
|
||||
this.action = action;
|
||||
this.str = str;
|
||||
this.duration = duration;
|
||||
this.timeout = timeout;
|
||||
this.fatalRegex = fatalRegex;
|
||||
this.errorRegex = errorRegex;
|
||||
this.warningRegex = warningRegex;
|
||||
this.successRegex = successRegex;
|
||||
}
|
||||
|
||||
public Command(CmdAction action, string str, int duration, int timeout)
|
||||
: this(action, str, duration, timeout, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public Command(CmdAction action, string str)
|
||||
: this(action, str, 0, 0, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public Command(CmdAction action, int duration, int timeout)
|
||||
: this(action, null, duration, timeout, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public Command(CmdAction action)
|
||||
: this(action, null, 0, 0, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For debugging purposes.
|
||||
/// </summary>
|
||||
/// <returns>A name of Command.action</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
string result = action.ToString();
|
||||
|
||||
if (str != null)
|
||||
{
|
||||
result += ", \"" + str + "\"";
|
||||
}
|
||||
|
||||
if (action == CmdAction.CONNECT ||
|
||||
action == CmdAction.REBOOT_RECONNECT ||
|
||||
action == CmdAction.EXIT_RECONNECT ||
|
||||
action == CmdAction.SEND_COMMAND)
|
||||
{
|
||||
result += ", timeout=" + timeout.ToString() + "s";
|
||||
}
|
||||
|
||||
if (action == CmdAction.SEND_COMMAND)
|
||||
{
|
||||
if (fatalRegex != null) { result += ", fatal=" + fatalRegex.ToString(); }
|
||||
if (errorRegex != null) { result += ", error=" + errorRegex.ToString(); }
|
||||
if (warningRegex != null) { result += ", warning=" + warningRegex.ToString(); }
|
||||
if (successRegex != null) { result += ", success=" + successRegex.ToString(); }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Telnet
|
||||
{
|
||||
public class DummyVT : IVirtualTerminal
|
||||
{
|
||||
public DummyVT() { }
|
||||
|
||||
public void ClearScreen() { }
|
||||
public void WriteVt(char c) { }
|
||||
public void WriteVt(string txt) { }
|
||||
public string Text { get { return string.Empty; } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TBF.Rig.Network.Telnet
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of argument of MeasuredDataEventHandler
|
||||
/// </summary>
|
||||
public class MeasuredDataEventArgs : EventArgs
|
||||
{
|
||||
public string MeasuredData; /// Fatal error description messages.
|
||||
|
||||
public MeasuredDataEventArgs(string measuredData)
|
||||
{
|
||||
MeasuredData = measuredData;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Type of argument of FatalEventHandler
|
||||
/// </summary>
|
||||
public class FatalEventArgs : EventArgs
|
||||
{
|
||||
public string FatalErrorText; /// Fatal error description messages.
|
||||
|
||||
public FatalEventArgs(string text)
|
||||
{
|
||||
FatalErrorText = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Type of argument of NotificationEventHandler
|
||||
/// </summary>
|
||||
public class NotificationEventArgs : EventArgs
|
||||
{
|
||||
public string NotificationText; /// String identifying this notification more closely.
|
||||
|
||||
public NotificationEventArgs(string text)
|
||||
{
|
||||
NotificationText = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Type of argument of PromptReceviedEventHandler
|
||||
/// </summary>
|
||||
public class PromptReceivedEventArgs : EventArgs
|
||||
{
|
||||
public string Response; /// Response to a command from the telnet server ...
|
||||
/// ... without the terminal prompt string.
|
||||
|
||||
public PromptReceivedEventArgs(string text)
|
||||
{
|
||||
Response = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Type of argument of VtTextChangedEventHandler
|
||||
/// </summary>
|
||||
public class VtTextChangedEventArgs : EventArgs
|
||||
{
|
||||
public string VtText; // Virtual terminal text.
|
||||
|
||||
public VtTextChangedEventArgs(string text)
|
||||
{
|
||||
VtText = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used as a part of AuxBrdUpgItemMessage
|
||||
/// </summary>
|
||||
public enum Category
|
||||
{
|
||||
Error,
|
||||
Warning,
|
||||
Success,
|
||||
}
|
||||
/// <summary>
|
||||
/// A pair containing Aux Board Upgrade item identification and a message
|
||||
/// (fatal error, error, warning or success message).
|
||||
/// </summary>
|
||||
public class AuxBrdUpgItemMessage
|
||||
{
|
||||
public Category Category; /// Error, Warning or Success
|
||||
public string Label; /// Identifies the aux.board upgrade item
|
||||
public string Message; /// The message
|
||||
|
||||
public AuxBrdUpgItemMessage(Category category, string label, string message)
|
||||
{
|
||||
Category = category;
|
||||
Label = label;
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Type of argument of SummaryEventArgs
|
||||
/// </summary>
|
||||
public class SummaryEventArgs : EventArgs
|
||||
{
|
||||
public IList<AuxBrdUpgItemMessage> SummaryMessages; /// Event description messages.
|
||||
|
||||
public SummaryEventArgs(IList<AuxBrdUpgItemMessage> summaryMessages)
|
||||
{
|
||||
this.SummaryMessages = summaryMessages;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Network.Telnet
|
||||
{
|
||||
public interface IVirtualTerminal
|
||||
{
|
||||
void ClearScreen();
|
||||
void WriteVt(char c);
|
||||
void WriteVt(string txt);
|
||||
string Text { get; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,233 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TBF.Rig.Network.Telnet
|
||||
{
|
||||
/// <summary>
|
||||
/// Virtual terminal (an array of characters).
|
||||
/// This class is thread safe under these circumstances:
|
||||
/// - ClearScreen() and WriteVt() methods called from one thread only
|
||||
/// - properties Text, etc. can be safely read from an arbitrary thread
|
||||
/// </summary>
|
||||
public class VirtualTerminal : IVirtualTerminal
|
||||
{
|
||||
const uint DefaultVtRowsCount = 80; /// Default VT height (number of rows)
|
||||
const uint DefaultVtColumnsCount = 132; /// Default VT width (number of columns)
|
||||
|
||||
/// <summary>
|
||||
/// Virtual terminal special characters.
|
||||
/// <seealso cref = http://support.microsoft.com/kb/231866 />
|
||||
/// </summary>
|
||||
enum SpecialChar
|
||||
{
|
||||
BS = 8, /// 8 = Backspace (move one position to the left)
|
||||
HT, /// 9 = Horizontal tab
|
||||
LF, /// 10 = Line feed
|
||||
VT, /// 11 = Vertical tab
|
||||
FF, /// 12 = Form feed (on visual displays most commonly clears the screen)
|
||||
CR /// 13 = Carriage return
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Public properties
|
||||
///
|
||||
public uint Rows { get { return vtRows; } }
|
||||
public uint Columns { get { return vtColumns; } }
|
||||
public uint CurRow { get { return curRow; } }
|
||||
public uint CurColumn { get { return curColumn; } }
|
||||
|
||||
/// <summary>
|
||||
/// Virtual terminal text buffer as a single string. To be printed out using monospaced font.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
string result = "";
|
||||
char[] oneRow = new char[vtColumns];
|
||||
|
||||
for (int row = 0; row < vtRows; row++)
|
||||
{
|
||||
for (int column = 0; column < vtColumns; column++)
|
||||
{
|
||||
oneRow[column] = vt[row, column];
|
||||
}
|
||||
result += new String(oneRow);
|
||||
|
||||
/// New line at the end of each line except of the last one
|
||||
if (row < vtRows - 1) result += System.Environment.NewLine;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Private fields
|
||||
///
|
||||
char[,] vt; /// Virtual terminal text buffer
|
||||
uint vtRows = 0; /// VT height (number of rows)
|
||||
uint vtColumns = 0; /// VT width (number of columns)
|
||||
uint curRow = 0; /// Current row (cursor position)
|
||||
uint curColumn = 0; /// Current column (cursor position)
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public VirtualTerminal()
|
||||
{
|
||||
vt = new char[DefaultVtRowsCount, DefaultVtColumnsCount];
|
||||
if (vt != null)
|
||||
{
|
||||
vtRows = DefaultVtRowsCount;
|
||||
vtColumns = DefaultVtColumnsCount;
|
||||
ClearScreen();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arbitrary VT size constructor.
|
||||
/// </summary>
|
||||
public VirtualTerminal(uint nrRows, uint nrColumns)
|
||||
{
|
||||
vt = new char[nrRows, nrColumns];
|
||||
if (vt != null)
|
||||
{
|
||||
vtRows = nrRows;
|
||||
vtColumns = nrColumns;
|
||||
ClearScreen();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear VT.
|
||||
/// </summary>
|
||||
public void ClearScreen()
|
||||
{
|
||||
for (uint row = 0; row < vtRows; row++)
|
||||
{
|
||||
for (uint column = 0; column < vtColumns; column++)
|
||||
{
|
||||
vt[row, column] = ' ';
|
||||
}
|
||||
}
|
||||
curRow = 0;
|
||||
curColumn = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scroll VT one line up and clear the bottom line.
|
||||
/// </summary>
|
||||
void ScrollUp()
|
||||
{
|
||||
for (uint row = 0; row < vtRows - 1; row++)
|
||||
{
|
||||
for (uint column = 0; column < vtColumns; column++)
|
||||
{
|
||||
vt[row, column] = vt[row + 1, column];
|
||||
}
|
||||
}
|
||||
for (uint column = 0; column < vtColumns; column++)
|
||||
{
|
||||
vt[vtRows - 1, column] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write one regular printable character to VC.
|
||||
/// </summary>
|
||||
void WritePrintableChar(char c)
|
||||
{
|
||||
vt[curRow, curColumn] = c;
|
||||
if (curColumn < vtColumns - 1)
|
||||
{
|
||||
curColumn++;
|
||||
}
|
||||
else if (curRow < vtRows - 1)
|
||||
{
|
||||
curRow++;
|
||||
curColumn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScrollUp();
|
||||
curRow = vtRows - 1;
|
||||
curColumn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write one character to VT (regular or special).
|
||||
/// </summary>
|
||||
public void WriteVt(char c)
|
||||
{
|
||||
if (c >= 32 && c <= 127)
|
||||
{
|
||||
WritePrintableChar(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((SpecialChar)c)
|
||||
{
|
||||
/// Carriage return
|
||||
case SpecialChar.CR:
|
||||
curColumn = 0;
|
||||
break;
|
||||
|
||||
/// Line feed
|
||||
case SpecialChar.LF:
|
||||
if (curRow < vtRows - 1)
|
||||
{
|
||||
curRow++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScrollUp();
|
||||
curRow = vtRows - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/// Form feed (= clear screen)
|
||||
case SpecialChar.FF:
|
||||
ClearScreen();
|
||||
break;
|
||||
|
||||
/// Backspace
|
||||
case SpecialChar.BS:
|
||||
if (curColumn > 0)
|
||||
{
|
||||
vt[curRow, --curColumn] = ' ';
|
||||
}
|
||||
else if (curRow > 0)
|
||||
{
|
||||
curColumn = vtColumns - 1;
|
||||
vt[--curRow, curColumn] = ' ';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a string to VT.
|
||||
/// </summary>
|
||||
public void WriteVt(string txt)
|
||||
{
|
||||
if (txt != null)
|
||||
{
|
||||
for (int i = 0; i < txt.Length; i++)
|
||||
{
|
||||
WriteVt(txt[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user