Refactorization : BenchControl -> Rig

This commit is contained in:
Milan Hanajik
2021-03-05 16:12:24 +01:00
parent 84c8ec26b6
commit 6cf3bd6160
1461 changed files with 6330 additions and 6330 deletions
+27
View File
@@ -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);
}
}
}
+48
View File
@@ -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());
}
}
}
+39
View File
@@ -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
View File
@@ -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>
+217
View File
@@ -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;
}
}
}
+839
View File
@@ -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;
}
}
}
+194
View File
@@ -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>
+27
View File
@@ -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);
}
}
}
+62
View File
@@ -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>
+153
View File
@@ -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;
}
}
}
+109
View File
@@ -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
View File
@@ -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
+27
View File
@@ -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);
}
}
}
+27
View File
@@ -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;
}
}
}
+266
View File
@@ -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()
{
}
}
}
+63
View File
@@ -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" : "")));
}
}
}
+145
View File
@@ -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
View File
@@ -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;
}
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -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>
+262
View File
@@ -0,0 +1,262 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using log4net;
using Common;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Boxes;
namespace TBF.Rig.Network.Comet.Ambient
{
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
/// Connection settings: 9600 Bd 8-bits No-parity 2-stop-bits Flow control: none.
/// </summary>
public class Ambient : ComponentBase, IDevice, IOperation, GenericDevices.IAmbient
{
private static readonly ILog log = LogManager.GetLogger(typeof(Ambient));
public override string ToString() { return string.Format("Ambient({0})", Cfg.ToString(1)); }
readonly AmbientCfg myCfg;
readonly IPAddress ipAddress;
readonly int tcpPort;
TcpClient tcpClient;
NetworkStream networkStream;
enum State
{
Idle,
WaitingForTemperature,
WaitingForHumidity,
WaitingForPressure,
};
State state;
/// <summary>The state of the measurement</summary>
MsrmntState msrmntState;
///
/// Measured values when MsrmntState == MsrmntState.Valid
///
double temperature; /// [°C]
double pressure; /// [bar]
double humidity; /// [R%]
/// <summary>Measurement time stamp when MsrmntState == MsrmntState.Valid</summary>
int msrmntTimeStamp;
public Ambient()
{
}
/// <summary>
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
/// </summary>
public Ambient(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
myCfg = cfg as AmbientCfg;
if (myCfg == null) throw new ArgumentNullException("No configuration");
ipAddress = IPAddress.Parse(myCfg.IPAddress);
tcpPort = myCfg.TcpPort;
log.Warn(this.ToString());
}
public void Initialize()
{
if (myCfg.DebugLevel == DebugMode.Simulate)
{
temperature = 20.0;
humidity = 40.0;
pressure = 1.0;
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.FatalFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure);
return;
}
tcpClient = new TcpClient();
tcpClient.Connect(ipAddress, tcpPort);
networkStream = tcpClient.GetStream();
state = State.Idle;
msrmntState = MsrmntState.Busy;
log.FatalFormat("Initialization successful: {0}", this.ToString());
}
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
if (myCfg.DebugLevel == DebugMode.Simulate || myCfg.DebugLevel == DebugMode.FailureDuringOperation)
{
msrmntTimeStamp = StateMachine.Time;
return;
}
try
{
int available = tcpClient.Available;
if (available >= 11)
{
byte[] bytes = new byte[available];
networkStream.Read(bytes, 0, available);
log.Debug(Telegram.LogTelegram("Received ", bytes));
int value;
if (available == 11 && bytes[0] == 0 && bytes[2] == 0 && bytes[3] == 0 && bytes[4] == 0
&& bytes[5] == 5 && bytes[6] == 1 && bytes[7] == 3 && bytes[8] == 2)
{
switch (state)
{
case State.WaitingForTemperature:
value = (int)bytes[9] * 256 + (int)bytes[10];
temperature = value / 10.0; /// Conversion to °C
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.InfoFormat("Ambient temperature = {0:F1} C", temperature);
state = State.Idle;
break;
case State.WaitingForHumidity:
value = (int)bytes[9] * 256 + (int)bytes[10];
humidity = value / 10.0; /// Conversion to R%
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.InfoFormat("Ambient humidity = {0:F1} %", humidity);
state = State.Idle;
break;
case State.WaitingForPressure:
value = (int)bytes[9] * 256 + (int)bytes[10];
pressure = value / 10000.0; /// Conversion to bar
msrmntTimeStamp = StateMachine.Time;
msrmntState = MsrmntState.Valid;
log.InfoFormat("Ambient pressure = {0:F0} mbar", 1000 * pressure);
state = State.Idle;
break;
}
}
else
{
state = State.Idle;
}
}
}
catch (Exception e)
{
DebugLevel = DebugMode.FailureDuringOperation;
log.FatalFormat("Ambient: Serail port read failure : {0}", e.Message);
if (e.InnerException != null)
{
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
}
}
}
/// <summary>Run this device</summary>
public void RunDeviceAfter()
{
if (myCfg.DebugLevel == DebugMode.Simulate || myCfg.DebugLevel == DebugMode.FailureDuringOperation)
{
return;
}
try
{
/// 20 seconds cycle
byte[] message = null;
switch (StateMachine.Time % 20)
{
case 0:
state = State.WaitingForTemperature;
message = new byte[12] { 0, 0, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x30, 0, 0x01 };
break;
case 6:
state = State.WaitingForHumidity;
message = new byte[12] { 0, 0x02, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x31, 0, 0x01 };
break;
case 12:
state = State.WaitingForPressure;
message = new byte[12] { 0, 0x03, 0, 0, 0, 0x06, 0x01, 0x03, 0, 0x33, 0, 0x01 };
break;
}
if (message != null)
{
log.Debug(Telegram.LogTelegram("Sending ", message));
networkStream.Write(message, 0, message.Length); /// Read request
}
}
catch (Exception e)
{
DebugLevel = DebugMode.FailureDuringOperation;
log.FatalFormat("TCP/IP write error : {0}", e.Message);
if (e.InnerException != null)
{
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
}
}
}
/// <summary>Stop this device</summary>
public void StopDevice()
{
if (myCfg.DebugLevel != DebugMode.Simulate && myCfg.DebugLevel != DebugMode.FailureDuringOperation)
{
networkStream.Close();
tcpClient.Close();
}
}
public void StopDevice2() { }
///
/// Boxes for the operation result
///
DoubleBox tempBox;
DoubleBox pressureBox;
DoubleBox humiBox;
public IOperation ReadAmbientOp(DoubleBox tempBox, DoubleBox pressureBox, DoubleBox humiBox)
{
this.tempBox = tempBox;
this.pressureBox = pressureBox;
this.humiBox = humiBox;
return this;
}
/// <summary>Start this operation</summary>
public void Start()
{
if (tempBox != null) tempBox.Val = temperature;
if (pressureBox != null) pressureBox.Val = pressure;
if (humiBox != null) humiBox.Val = humidity;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (tempBox != null) tempBox.Val = temperature;
if (pressureBox != null) pressureBox.Val = pressure;
if (humiBox != null) humiBox.Val = humidity;
return Event.AmbientDone;
}
/// <summary>Stop this operation</summary>
public void Stop() { }
}
}
@@ -0,0 +1,45 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Net;
using System.Collections.Generic;
using System.Xml.Serialization;
using Config.Entities;
using TBF.Rig.Generic;
namespace TBF.Rig.Network.Comet.Ambient
{
public class AmbientCfg : ComponentCfgBase, IComponentCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(AmbientCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new AmbientCfgCtrl(); }
///
/// Serialized parameters
///
public string IPAddress;
public int TcpPort;
public string SerialNr;
/// Private parameterless constructor invoked by all other (public) constructors
AmbientCfg() { }
public AmbientCfg(string name, IComponentFactory factory)
: this()
{
this.Name = name;
this.Factory = factory;
IPAddress = "192.168.0.123";
TcpPort = 502;
SerialNr = string.Empty;
}
public string ToString(int i)
{
return string.Format("Name={0}, IP={1}, Port={2}, s/n={3}", Name, IPAddress, TcpPort, SerialNr);
}
}
}
+157
View File
@@ -0,0 +1,157 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
namespace TBF.Rig.Network.Comet.Ambient
{
partial class AmbientCfgCtrl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.serialNrTextBox = new System.Windows.Forms.TextBox();
this.serialNrLabel = new System.Windows.Forms.Label();
this.ipAddressLabel = new System.Windows.Forms.Label();
this.ipAddressTextBox = new System.Windows.Forms.TextBox();
this.tcpPortTextBox = new System.Windows.Forms.TextBox();
this.tcpPortLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(140, 43);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(36, 46);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 1;
this.nameLabel.Text = "Name";
//
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(137, 18);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComonentName";
//
// serialNrTextBox
//
this.serialNrTextBox.Enabled = false;
this.serialNrTextBox.Location = new System.Drawing.Point(140, 121);
this.serialNrTextBox.Name = "serialNrTextBox";
this.serialNrTextBox.Size = new System.Drawing.Size(130, 20);
this.serialNrTextBox.TabIndex = 10;
//
// serialNrLabel
//
this.serialNrLabel.AutoSize = true;
this.serialNrLabel.Location = new System.Drawing.Point(36, 124);
this.serialNrLabel.Name = "serialNrLabel";
this.serialNrLabel.Size = new System.Drawing.Size(71, 13);
this.serialNrLabel.TabIndex = 9;
this.serialNrLabel.Text = "Serial number";
//
// ipAddressLabel
//
this.ipAddressLabel.AutoSize = true;
this.ipAddressLabel.Location = new System.Drawing.Point(36, 72);
this.ipAddressLabel.Name = "ipAddressLabel";
this.ipAddressLabel.Size = new System.Drawing.Size(58, 13);
this.ipAddressLabel.TabIndex = 5;
this.ipAddressLabel.Text = "IP Address";
//
// ipAddressTextBox
//
this.ipAddressTextBox.Enabled = false;
this.ipAddressTextBox.Location = new System.Drawing.Point(140, 69);
this.ipAddressTextBox.Name = "ipAddressTextBox";
this.ipAddressTextBox.Size = new System.Drawing.Size(130, 20);
this.ipAddressTextBox.TabIndex = 6;
//
// tcpPortTextBox
//
this.tcpPortTextBox.Enabled = false;
this.tcpPortTextBox.Location = new System.Drawing.Point(140, 95);
this.tcpPortTextBox.Name = "tcpPortTextBox";
this.tcpPortTextBox.Size = new System.Drawing.Size(130, 20);
this.tcpPortTextBox.TabIndex = 8;
//
// tcpPortLabel
//
this.tcpPortLabel.AutoSize = true;
this.tcpPortLabel.Location = new System.Drawing.Point(36, 98);
this.tcpPortLabel.Name = "tcpPortLabel";
this.tcpPortLabel.Size = new System.Drawing.Size(65, 13);
this.tcpPortLabel.TabIndex = 7;
this.tcpPortLabel.Text = "TCP/IP Port";
//
// AmbientCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.Controls.Add(this.tcpPortTextBox);
this.Controls.Add(this.tcpPortLabel);
this.Controls.Add(this.ipAddressTextBox);
this.Controls.Add(this.ipAddressLabel);
this.Controls.Add(this.serialNrTextBox);
this.Controls.Add(this.serialNrLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Name = "AmbientCfgCtrl";
this.Size = new System.Drawing.Size(400, 254);
this.Load += new System.EventHandler(this.AbbientCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.TextBox serialNrTextBox;
private System.Windows.Forms.Label serialNrLabel;
private System.Windows.Forms.Label ipAddressLabel;
private System.Windows.Forms.TextBox ipAddressTextBox;
private System.Windows.Forms.TextBox tcpPortTextBox;
private System.Windows.Forms.Label tcpPortLabel;
}
}
@@ -0,0 +1,111 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Net;
using System.Windows.Forms;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Resources;
namespace TBF.Rig.Network.Comet.Ambient
{
public partial class AmbientCfgCtrl : UserControl, IComponentCfgCtrl
{
public bool ShowMore { get { return false; } }
AmbientCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as AmbientCfg;
Redraw();
}
}
public AmbientCfgCtrl()
{
InitializeComponent();
}
private void AbbientCfgCtrl_Load(object sender, EventArgs e)
{
Localize();
Redraw();
}
void Localize()
{
nameLabel.Text = Strings.Name;
serialNrLabel.Text = Strings.Serial_Number;
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
classNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
ipAddressTextBox.Text = config.IPAddress != null ? config.IPAddress.ToString() : "192.168.0.123";
tcpPortTextBox.Text = config.TcpPort.ToString();
serialNrTextBox.Text = config.SerialNr.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
ipAddressTextBox.Enabled = true;
tcpPortTextBox.Enabled = true;
serialNrTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
IPAddress ip;
if (!IPAddress.TryParse(ipAddressTextBox.Text, out ip))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + string.Format(Strings.Invalid_0, ipAddressLabel.Text);
}
int port;
if (!int.TryParse(tcpPortTextBox.Text, out port) || port < 0 || port > 65535)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + string.Format(Strings.Invalid_0, tcpPortLabel.Text);
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
if (config.Name != nameTextBox.Text ||
config.IPAddress != ipAddressTextBox.Text ||
config.TcpPort.ToString() != tcpPortTextBox.Text ||
config.SerialNr != serialNrTextBox.Text)
{
config.Name = nameTextBox.Text;
config.IPAddress = ipAddressTextBox.Text;
config.TcpPort = int.Parse(tcpPortTextBox.Text);
config.SerialNr = serialNrTextBox.Text;
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
}
return flags;
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+27
View File
@@ -0,0 +1,27 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.Network.Comet.Ambient
{
public class Factory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public void ResetStaticProperties() { Ambient.ResetStaticProperties(); }
public IComponent DummyComponent() { return new Ambient(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Ambient(cfg, components); }
public IComponentCfg DefaultConfig() { return new AmbientCfg(this.GetType().Namespace.Substring(8), this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(AmbientCfg.Serializer, component, this);
}
}
}
+125
View File
@@ -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;
}
}
}
+15
View File
@@ -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; } }
}
}
+120
View File
@@ -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
+233
View File
@@ -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]);
}
}
}
}
}