Refactorization : BenchControl -> Rig
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using log4net;
|
||||
using Common;
|
||||
using Config;
|
||||
using Config.Entities;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Ambient.Comet
|
||||
{
|
||||
/// <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, IDrawingItCmpntWithMeasuredVal
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Ambient));
|
||||
public override string ToString() { return string.Format("Ambient({0})", Cfg.ToString(1)); }
|
||||
|
||||
///
|
||||
/// Configuration and wrappers
|
||||
///
|
||||
private readonly AmbientCfg ambientCfg;
|
||||
///
|
||||
Unit TempUnit { get { return ambientCfg.TempUnit; } }
|
||||
double TempLimLo { get { return Units.ConvertFrom(TempUnit, ambientCfg.TempLimLo); } }
|
||||
double TempLimHi { get { return Units.ConvertFrom(TempUnit, ambientCfg.TempLimHi); } }
|
||||
double DefaultTemperature { get { return Units.ConvertFrom(TempUnit, ambientCfg.DefaultTemp); } }
|
||||
///
|
||||
Unit PressureUnit { get { return ambientCfg.PressureUnit; } }
|
||||
double PressureLimLo { get { return Units.ConvertFrom(PressureUnit, ambientCfg.PressureLimLo); } }
|
||||
double PressureLimHi { get { return Units.ConvertFrom(PressureUnit, ambientCfg.PressureLimHi); } }
|
||||
double DefaultPressure { get { return Units.ConvertFrom(PressureUnit, ambientCfg.DefaultPressure); } }
|
||||
///
|
||||
Unit HumiUnit { get { return ambientCfg.HumiUnit; } }
|
||||
double HumiLimLo { get { return Units.ConvertFrom(HumiUnit, ambientCfg.HumiLimLo); } }
|
||||
double HumiLimHi { get { return Units.ConvertFrom(HumiUnit, ambientCfg.HumiLimHi); } }
|
||||
double DefaultHumidity { get { return Units.ConvertFrom(HumiUnit, ambientCfg.DefaultHumi); } }
|
||||
|
||||
///
|
||||
/// IDrawingItCmpntWithMeasuredVal interface
|
||||
///
|
||||
public IDrawingItem DrawingItem { get { return ambientCfg as IDrawingItem; } }
|
||||
public bool MsrmntAvailable { get { return true; } }
|
||||
public double MeasuredVal { get { return temperature; } }
|
||||
public string AltString
|
||||
{
|
||||
get {
|
||||
return string.Format(ambientCfg.Format, Units.ConvertTo(TempUnit, temperature),
|
||||
Units.ConvertTo(PressureUnit, pressure),
|
||||
Units.ConvertTo(HumiUnit, humidity));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Private fields
|
||||
SerialPort serialPort;
|
||||
|
||||
/// <summary>The state of the measurement</summary>
|
||||
MsrmntState msrmntState;
|
||||
int msrmntTimeStamp;
|
||||
|
||||
/// Measured values when MsrmntState == MsrmntState.Valid
|
||||
double temperature; /// [°C]
|
||||
double pressure; /// [bar]
|
||||
double humidity; /// [R%]
|
||||
|
||||
|
||||
public Ambient()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
|
||||
/// </summary>
|
||||
public Ambient(AmbientCfg cfg, IList<Generic.IComponent> components)
|
||||
: this(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
public Ambient(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
ambientCfg = cfg as AmbientCfg;
|
||||
|
||||
temperature = DefaultTemperature;
|
||||
pressure = DefaultPressure;
|
||||
humidity = DefaultHumidity;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (ambientCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
msrmntTimeStamp = StateMachine.Time;
|
||||
msrmntState = MsrmntState.Valid;
|
||||
return;
|
||||
}
|
||||
|
||||
string comPortName = "COM" + ambientCfg.ComPortNr.ToString();
|
||||
serialPort = new SerialPort(comPortName, ambientCfg.BaudRate, ambientCfg.Parity, ambientCfg.DataBits, ambientCfg.StopBits);
|
||||
serialPort.Handshake = ambientCfg.Handshake;
|
||||
serialPort.Open();
|
||||
if (ambientCfg.SetDtrToOne)
|
||||
{
|
||||
serialPort.DtrEnable = true;
|
||||
}
|
||||
|
||||
msrmntTimeStamp = 0;
|
||||
msrmntState = MsrmntState.Busy;
|
||||
|
||||
log.FatalFormat("Successfully initialized device {0}", ToString());
|
||||
}
|
||||
|
||||
/// <summary>Run this device</summary>
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if ((ambientCfg.DebugLevel == DebugMode.Normal) && (serialPort != null))
|
||||
{
|
||||
///
|
||||
/// Read response
|
||||
///
|
||||
try
|
||||
{
|
||||
int receivedBytes = serialPort.BytesToRead;
|
||||
|
||||
if (receivedBytes >= 13)
|
||||
{
|
||||
byte[] byteArr = new byte[receivedBytes];
|
||||
for (int i = 0; i < receivedBytes; i++) byteArr[i] = (byte)serialPort.ReadByte();
|
||||
log.Debug(Telegram.LogTelegram("Received ", byteArr));
|
||||
|
||||
if ((receivedBytes == 13) && (byteArr[0] == 1) && (byteArr[1] == 3) && (byteArr[2] == 8) && Telegram.VerifyTelegramCRC(byteArr))
|
||||
{
|
||||
int value = (int)byteArr[3] * 256 + (int)byteArr[4];
|
||||
temperature = value / 10.0;
|
||||
|
||||
value = (int)byteArr[5] * 256 + (int)byteArr[6];
|
||||
humidity = value / 10.0;
|
||||
|
||||
value = (int)byteArr[9] * 256 + (int)byteArr[10];
|
||||
pressure = value / 10000.0;
|
||||
|
||||
msrmntTimeStamp = StateMachine.Time;
|
||||
msrmntState = MsrmntState.Valid;
|
||||
|
||||
UpdateProcessData(temperature, pressure, humidity);
|
||||
|
||||
log.InfoFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugLevel = DebugMode.FailureDuringOperation;
|
||||
//serialPort.Close(); /// ?
|
||||
serialPort = null;
|
||||
|
||||
log.FatalFormat("Ambient: Serial 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 ((ambientCfg.DebugLevel == DebugMode.Normal) && (serialPort != null))
|
||||
{
|
||||
if ((StateMachine.Time % 10) == 0)
|
||||
{
|
||||
///
|
||||
/// Send request once per 10 seconds
|
||||
///
|
||||
try
|
||||
{
|
||||
/// Read four registers: 0x31, 0x32, 0x33, 0x34
|
||||
UInt16 regAddr = 0x0030; /// register addr. = 0x31 (Modbus!)
|
||||
UInt16 count = 4;
|
||||
|
||||
/// Prepare data to be sent
|
||||
byte[] msg = new byte[8];
|
||||
msg[0] = 1; /// (byte)ambientCfg.BusAddress;
|
||||
msg[1] = 3; /// CMD = Read registers
|
||||
msg[2] = (byte)(regAddr >> 8); /// Control Word Hi
|
||||
msg[3] = (byte)(regAddr & 0xFF); /// Control Word Lo
|
||||
msg[4] = (byte)(count >> 8); /// Serial Com Reference Hi
|
||||
msg[5] = (byte)(count & 0xFF); /// Serial Com Reference Lo
|
||||
Telegram.UpdateTelegramCRC(msg);
|
||||
|
||||
log.Debug(Telegram.LogTelegram("Sending ", msg));
|
||||
serialPort.Write(msg, 0, msg.Length);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugLevel = DebugMode.FailureDuringOperation;
|
||||
//serialPort.Close(); /// ?
|
||||
serialPort = null;
|
||||
|
||||
log.FatalFormat("Ambient: Serail port read failure : {0}", e.Message);
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stop this device</summary>
|
||||
public void StopDevice()
|
||||
{
|
||||
if ((ambientCfg.DebugLevel == DebugMode.Normal) && (serialPort != null))
|
||||
{
|
||||
serialPort.Close();
|
||||
serialPort = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void StopDevice2() { }
|
||||
|
||||
void UpdateProcessData(double temperature, double pressure, double humidity)
|
||||
{
|
||||
TBF.Rig.Sequences.ProcessData.AmbTemp.Val = temperature;
|
||||
TBF.Rig.Sequences.ProcessData.AmbPress.Val = pressure;
|
||||
TBF.Rig.Sequences.ProcessData.AmbHumi.Val = humidity;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Boxes for the operation result
|
||||
///
|
||||
DoubleBox tempBox;
|
||||
DoubleBox pressureBox;
|
||||
DoubleBox humiBox;
|
||||
|
||||
public IOperation ReadAmbientOp(DoubleBox temperature, DoubleBox pressure, DoubleBox humidity)
|
||||
{
|
||||
this.tempBox = temperature;
|
||||
this.pressureBox = pressure;
|
||||
this.humiBox = humidity;
|
||||
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,350 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Xml.Serialization;
|
||||
using Config;
|
||||
using Config.Entities;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Ambient.Comet
|
||||
{
|
||||
public class AmbientCfg : ComponentCfgBase, Generic.IComponentCfg, IParamsProvider, IDrawingItemWithMeasuredVal
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(AmbientCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
||||
{
|
||||
return new Configs.ParamsProvider.ComponentCfgCtrl(this, null);
|
||||
}
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int ComPortNr; /// 0
|
||||
public int BaudRate; /// 1
|
||||
public Parity Parity; /// 2
|
||||
public int DataBits; /// 3
|
||||
public StopBits StopBits; /// 4
|
||||
public Handshake Handshake; /// 5
|
||||
public bool SetDtrToOne; /// 6
|
||||
public Unit TempUnit; /// 7
|
||||
public double TempLimLo; /// 8
|
||||
public double TempLimHi; /// 9
|
||||
public double DefaultTemp; /// 10
|
||||
public Unit PressureUnit; /// 11
|
||||
public double PressureLimLo; /// 12
|
||||
public double PressureLimHi; /// 13
|
||||
public double DefaultPressure; /// 14
|
||||
public Unit HumiUnit; /// 15
|
||||
public double HumiLimLo; /// 16
|
||||
public double HumiLimHi; /// 17
|
||||
public double DefaultHumi; /// 18
|
||||
public string Format; /// 19
|
||||
|
||||
/// Schematic drawing info
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
public int MsrdX { get; set; }
|
||||
public int MsrdY { get; set; }
|
||||
public Orient MsrdOrient { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public string MsrdFormat { get { return string.Empty; } }
|
||||
[XmlIgnore]
|
||||
public Config.Unit MsrdUnit { get { return TempUnit; } }
|
||||
[XmlIgnore]
|
||||
public double MsrdValLimLo { get { return TempLimLo; } }
|
||||
[XmlIgnore]
|
||||
public double MsrdValLimHi { get { return TempLimHi; } }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
AmbientCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
Format = string.Empty;
|
||||
}
|
||||
|
||||
public AmbientCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.Ambient;
|
||||
Sz = Sz.M;
|
||||
Factory = factory;
|
||||
Name = name;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
ComPortNr = 6;
|
||||
BaudRate = 9600;
|
||||
Parity = System.IO.Ports.Parity.None;
|
||||
DataBits = 8;
|
||||
StopBits = System.IO.Ports.StopBits.Two;
|
||||
Handshake = System.IO.Ports.Handshake.None;
|
||||
SetDtrToOne = false;
|
||||
TempUnit = Unit.C;
|
||||
TempLimLo = 15;
|
||||
TempLimHi = 30;
|
||||
DefaultTemp = 25;
|
||||
PressureUnit = Unit.hPa;
|
||||
PressureLimLo = 960;
|
||||
PressureLimHi = 1060;
|
||||
DefaultPressure = 1013;
|
||||
HumiUnit = Unit.RPct;
|
||||
HumiLimLo = 20;
|
||||
HumiLimHi = 80;
|
||||
DefaultHumi = 50;
|
||||
Format = "{0:F1} °C\n{1:F0} hPa\n{2:F0} R%";
|
||||
|
||||
MsrdY = 22;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Serial port number", /// 0
|
||||
"Baud rate", /// 1
|
||||
"Parity", /// 2
|
||||
"Data bits", /// 3
|
||||
"Stop bits", /// 4
|
||||
"Handshake", /// 5
|
||||
"Set DTR to one", /// 6
|
||||
"Unit of temperature", /// 7
|
||||
"Temperature limit Lo", /// 8
|
||||
"Temperature limit Hi", /// 9
|
||||
"Default temperature", /// 10
|
||||
"Unit of pressure", /// 11
|
||||
"Pressure limit Lo", /// 12
|
||||
"Pressure limit Hi", /// 13
|
||||
"Default pressure", /// 14
|
||||
"Unit of rel. humidity", /// 15
|
||||
"Rel. humidity limit Lo", /// 16
|
||||
"Rel. humidity limit Hi", /// 17
|
||||
"Default retl. humidity", /// 18
|
||||
"Display format", /// 19
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
|
||||
public ICollection<string> ParamValues(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
return new string[] { "150", "300", "600", "1200", "2400", "4800", "9600",
|
||||
"19200", "38400", "57600", "76800", "115200"};
|
||||
case 2:
|
||||
return new string[] { Parity.None.ToString(), Parity.Odd.ToString(), Parity.Even.ToString() };
|
||||
case 3:
|
||||
return new string[] { "7", "8" };
|
||||
case 4:
|
||||
return new string[] { StopBits.None.ToString(),
|
||||
StopBits.One.ToString(),
|
||||
StopBits.OnePointFive.ToString(),
|
||||
StopBits.Two.ToString() };
|
||||
case 5:
|
||||
return new string[] { Handshake.None.ToString(),
|
||||
Handshake.XOnXOff.ToString(),
|
||||
Handshake.RequestToSend.ToString(),
|
||||
Handshake.RequestToSendXOnXOff.ToString() };
|
||||
case 6:
|
||||
return new string[] { Strings.yes, Strings.no };
|
||||
case 7:
|
||||
return new string[] { "°C", "°F", "K" };
|
||||
case 11:
|
||||
return new string[] { "Pa", "hPa", "mbar", "kPa", "inHg", "psi", "bar", "MPa" };
|
||||
case 15:
|
||||
return new string[] { "R%" };
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: return ComPortNr.ToString();
|
||||
case 1: return BaudRate.ToString();
|
||||
case 2: return Parity.ToString();
|
||||
case 3: return DataBits.ToString();
|
||||
case 4: return StopBits.ToString();
|
||||
case 5: return Handshake.ToString();
|
||||
case 6: return SetDtrToOne ? Strings.yes : Strings.no;
|
||||
case 7: return TempUnit.ToDescription();
|
||||
case 8: return TempLimLo.ToString();
|
||||
case 9: return TempLimHi.ToString();
|
||||
case 10: return DefaultTemp.ToString();
|
||||
case 11: return PressureUnit.ToDescription();
|
||||
case 12: return PressureLimLo.ToString();
|
||||
case 13: return PressureLimHi.ToString();
|
||||
case 14: return DefaultPressure.ToString();
|
||||
case 15: return HumiUnit.ToDescription();
|
||||
case 16: return HumiLimLo.ToString();
|
||||
case 17: return HumiLimHi.ToString();
|
||||
case 18: return DefaultHumi.ToString();
|
||||
case 19: return Format.Replace("\n", "<LF>");
|
||||
default:
|
||||
return string.Format("{0} {1}[{2},{3}] Com{4}, {5}Bd, {6}-bits, parity={7}, stopBits={8}, {9}",
|
||||
Name, Shape, X, Y, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string str)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: ComPortNr = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 1: BaudRate = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 2: Parity = TBF.Utils.GetParity(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 3: DataBits = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 4: StopBits = TBF.Utils.GetStopBits(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 5: Handshake = TBF.Utils.GetHandshake(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 6: SetDtrToOne = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
|
||||
case 7:
|
||||
foreach (var u in new Unit[] { Unit.C, Unit.F, Unit.K })
|
||||
{
|
||||
if (str == u.ToDescription()) { TempUnit = u; return CfgUpdateFlags.RestartRqrd; }
|
||||
}
|
||||
return CfgUpdateFlags.None;
|
||||
case 8: TempLimLo = Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 9: TempLimHi = Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 10: DefaultTemp = Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 11:
|
||||
foreach (var u in new Unit[] { Unit.Pa, Unit.hPa, Unit.mbar, Unit.kPa, Unit.inHg, Unit.psi, Unit.bar, Unit.MPa })
|
||||
{
|
||||
if (str == u.ToDescription()) { PressureUnit = u; return CfgUpdateFlags.RestartRqrd; }
|
||||
}
|
||||
return CfgUpdateFlags.None;
|
||||
case 12: PressureLimLo = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 13: PressureLimHi = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 14: DefaultPressure = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 15:
|
||||
foreach (var u in new Unit[] { Unit.RPct })
|
||||
{
|
||||
if (str == u.ToDescription()) { HumiUnit = u; return CfgUpdateFlags.RestartRqrd; }
|
||||
}
|
||||
return CfgUpdateFlags.None;
|
||||
case 16: HumiLimLo = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 17: HumiLimHi = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 18: DefaultHumi = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 19: Format = str.Replace("<LF>", "\n"); return CfgUpdateFlags.RestartRqrd;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string str, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
int idummy;
|
||||
double dummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (int.TryParse(str, out idummy) && idummy > 0) return true;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 11:
|
||||
case 15:
|
||||
if (ParamValues(i).Contains(str)) return true;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
if (TBF.Utils.TryParseSDouble(str, out dummy)) return true;
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
if (TBF.Utils.TryParseUDouble(str, out dummy)) return true;
|
||||
break;
|
||||
case 19:
|
||||
return true;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(AmbientCfg prms)
|
||||
{
|
||||
prms.ParentName = this.ParentName;
|
||||
|
||||
prms.Shape = this.Shape;
|
||||
prms.Sz = this.Sz;
|
||||
prms.Orient = this.Orient;
|
||||
prms.Flip = this.Flip;
|
||||
prms.LblX = this.LblX;
|
||||
prms.LblY = this.LblY;
|
||||
prms.LblOrient = this.LblOrient;
|
||||
prms.MsrdX = this.MsrdX;
|
||||
prms.MsrdY = this.MsrdY;
|
||||
prms.MsrdOrient = this.MsrdOrient;
|
||||
|
||||
prms.ComPortNr = this.ComPortNr;
|
||||
prms.BaudRate = this.BaudRate;
|
||||
prms.Parity = this.Parity;
|
||||
prms.DataBits = this.DataBits;
|
||||
prms.StopBits = this.StopBits;
|
||||
prms.Handshake = this.Handshake;
|
||||
prms.SetDtrToOne = this.SetDtrToOne;
|
||||
prms.TempUnit = this.TempUnit;
|
||||
prms.TempLimLo = this.TempLimLo;
|
||||
prms.TempLimHi = this.TempLimHi;
|
||||
prms.DefaultTemp = this.DefaultTemp;
|
||||
prms.PressureUnit = this.PressureUnit;
|
||||
prms.PressureLimLo = this.PressureLimLo;
|
||||
prms.PressureLimHi = this.PressureLimHi;
|
||||
prms.DefaultPressure = this.DefaultPressure;
|
||||
prms.HumiUnit = this.HumiUnit;
|
||||
prms.HumiLimLo = this.HumiLimLo;
|
||||
prms.HumiLimHi = this.HumiLimHi;
|
||||
prms.DefaultHumi = this.DefaultHumi;
|
||||
prms.Format = this.Format;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
AmbientCfg pars = new AmbientCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Ambient.Comet
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return 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); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new AmbientCfg("Ambient", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(AmbientCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Config;
|
||||
using Config.Entities;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Ambient.Greco
|
||||
{
|
||||
/// <summary>
|
||||
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
|
||||
/// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware.
|
||||
/// </summary>
|
||||
public class Ambient : ComponentBase, IDevice, IOperation, GenericDevices.IAmbient, IDrawingItCmpntWithMeasuredVal
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Ambient));
|
||||
public override string ToString() { return string.Format("Ambient({0})", Cfg.ToString(1)); }
|
||||
|
||||
private readonly AmbientCfg ambientCfg;
|
||||
///
|
||||
Unit TempUnit { get { return ambientCfg.TempUnit; } }
|
||||
double TempLimLo { get { return Units.ConvertFrom(TempUnit, ambientCfg.TempLimLo); } }
|
||||
double TempLimHi { get { return Units.ConvertFrom(TempUnit, ambientCfg.TempLimHi); } }
|
||||
double DefaultTemperature { get { return Units.ConvertFrom(TempUnit, ambientCfg.DefaultTemp); } }
|
||||
///
|
||||
Unit PressureUnit { get { return ambientCfg.PressureUnit; } }
|
||||
double PressureLimLo { get { return Units.ConvertFrom(PressureUnit, ambientCfg.PressureLimLo); } }
|
||||
double PressureLimHi { get { return Units.ConvertFrom(PressureUnit, ambientCfg.PressureLimHi); } }
|
||||
double DefaultPressure { get { return Units.ConvertFrom(PressureUnit, ambientCfg.DefaultPressure); } }
|
||||
///
|
||||
Unit HumiUnit { get { return ambientCfg.HumiUnit; } }
|
||||
double HumiLimLo { get { return Units.ConvertFrom(HumiUnit, ambientCfg.HumiLimLo); } }
|
||||
double HumiLimHi { get { return Units.ConvertFrom(HumiUnit, ambientCfg.HumiLimHi); } }
|
||||
double DefaultHumidity { get { return Units.ConvertFrom(HumiUnit, ambientCfg.DefaultHumi); } }
|
||||
|
||||
///
|
||||
/// IDrawingItCmpntWithMeasuredVal interface
|
||||
///
|
||||
public IDrawingItem DrawingItem { get { return ambientCfg as IDrawingItem; } }
|
||||
public bool MsrmntAvailable { get { return true; } }
|
||||
public double MeasuredVal { get { return temperature; } }
|
||||
public string AltString
|
||||
{
|
||||
get {
|
||||
return string.Format(ambientCfg.Format, Units.ConvertTo(TempUnit, temperature),
|
||||
Units.ConvertTo(PressureUnit, pressure),
|
||||
Units.ConvertTo(HumiUnit, humidity));
|
||||
}
|
||||
}
|
||||
|
||||
/// Private fields
|
||||
SerialPort serialPort;
|
||||
StringBuilder measurementBuilder;
|
||||
|
||||
/// <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)
|
||||
/// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware.
|
||||
/// </summary>
|
||||
public Ambient(AmbientCfg cfg, IList<Generic.IComponent> components)
|
||||
: this(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
public Ambient(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
ambientCfg = cfg as AmbientCfg;
|
||||
|
||||
temperature = DefaultTemperature;
|
||||
pressure = DefaultPressure;
|
||||
humidity = DefaultHumidity;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (ambientCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
msrmntTimeStamp = StateMachine.Time;
|
||||
msrmntState = MsrmntState.Valid;
|
||||
return;
|
||||
}
|
||||
|
||||
string comPortName = "COM" + ambientCfg.ComPortNr.ToString();
|
||||
serialPort = new SerialPort(comPortName, ambientCfg.BaudRate, ambientCfg.Parity, ambientCfg.DataBits, ambientCfg.StopBits);
|
||||
serialPort.Handshake = ambientCfg.Handshake;
|
||||
serialPort.Open();
|
||||
measurementBuilder = new StringBuilder(40);
|
||||
msrmntState = MsrmntState.Busy;
|
||||
|
||||
log.FatalFormat("Successfully initialized device {0}", ToString());
|
||||
}
|
||||
|
||||
/// <summary>Run this device</summary>
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if (ambientCfg.DebugLevel == DebugMode.Simulate ||
|
||||
ambientCfg.DebugLevel == DebugMode.FailureDuringOperation)
|
||||
{
|
||||
msrmntTimeStamp = StateMachine.Time;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
measurementBuilder.Append(serialPort.ReadExisting());
|
||||
int len = measurementBuilder.Length;
|
||||
|
||||
///
|
||||
/// Device sends each 20 sec one line of ASCII text with data in the following format:
|
||||
/// (temp) 6 characters, two decimal digits, with leading spaces
|
||||
/// TAB 1 character
|
||||
/// (humi) 6 characters, two decimal digits, with leading spaces
|
||||
/// TAB 1 character
|
||||
/// (pressure) 6 characters, one decimal digits, with leading spaces is LT 1000
|
||||
/// CR + LF 2 characters
|
||||
/// Example:
|
||||
/// 23.42 38.08 1061.1
|
||||
/// 23.39 38.04 1060.8
|
||||
/// 23.39 38.08 1061.4
|
||||
///
|
||||
if (len >= 22)
|
||||
{
|
||||
string measurement = measurementBuilder.ToString();
|
||||
measurementBuilder.Clear();
|
||||
|
||||
double t = 0;
|
||||
double h = 0;
|
||||
double p = 0;
|
||||
if (double.TryParse(measurement.Substring(len - 22, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite,
|
||||
CultureInfo.InvariantCulture, out t) &&
|
||||
measurement[len - 16] == '\t' &&
|
||||
double.TryParse(measurement.Substring(len - 15, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite,
|
||||
CultureInfo.InvariantCulture, out h) &&
|
||||
measurement[len - 9] == '\t' &&
|
||||
double.TryParse(measurement.Substring(len - 8, 6), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite,
|
||||
CultureInfo.InvariantCulture, out p) &&
|
||||
measurement[len - 2] == '\r' &&
|
||||
measurement[len - 1] == '\n')
|
||||
{
|
||||
temperature = t;
|
||||
humidity = h;
|
||||
pressure = p / 1000.0;
|
||||
|
||||
UpdateProcessData(temperature, pressure, humidity);
|
||||
msrmntTimeStamp = StateMachine.Time;
|
||||
msrmntState = MsrmntState.Valid;
|
||||
log.InfoFormat("Ambient: temperature = {0:F1} C, humidity = {1:F1} %, pressure = {2:F0} mbar", temperature, humidity, 1000 * pressure);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Warn("Invalid string received: " + measurement);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugLevel = DebugMode.FailureDuringOperation;
|
||||
serialPort = null;
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Stop this device</summary>
|
||||
public void StopDevice()
|
||||
{
|
||||
if (serialPort != null) serialPort.Close();
|
||||
}
|
||||
|
||||
public void StopDevice2() { }
|
||||
|
||||
void UpdateProcessData(double temperature, double pressure, double humidity)
|
||||
{
|
||||
TBF.Rig.Sequences.ProcessData.AmbTemp.Val = temperature;
|
||||
TBF.Rig.Sequences.ProcessData.AmbPress.Val = pressure;
|
||||
TBF.Rig.Sequences.ProcessData.AmbHumi.Val = humidity;
|
||||
}
|
||||
|
||||
///
|
||||
/// Boxes for the operation result
|
||||
///
|
||||
DoubleBox tempBox;
|
||||
DoubleBox pressureBox;
|
||||
DoubleBox humiBox;
|
||||
|
||||
public IOperation ReadAmbientOp(DoubleBox temperature, DoubleBox pressure, DoubleBox humidity)
|
||||
{
|
||||
this.tempBox = temperature;
|
||||
this.pressureBox = pressure;
|
||||
this.humiBox = humidity;
|
||||
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,341 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Xml.Serialization;
|
||||
using Config;
|
||||
using Config.Entities;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Ambient.Greco
|
||||
{
|
||||
public class AmbientCfg : ComponentCfgBase, Generic.IComponentCfg, IParamsProvider, IDrawingItemWithMeasuredVal
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(AmbientCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
|
||||
{
|
||||
return new Configs.ParamsProvider.ComponentCfgCtrl(this, null);
|
||||
}
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int ComPortNr; /// 0
|
||||
public int BaudRate; /// 1
|
||||
public Parity Parity; /// 2
|
||||
public int DataBits; /// 3
|
||||
public StopBits StopBits; /// 4
|
||||
public Handshake Handshake; /// 5
|
||||
public Unit TempUnit; /// 6
|
||||
public double TempLimLo; /// 7
|
||||
public double TempLimHi; /// 8
|
||||
public double DefaultTemp; /// 9
|
||||
public Unit PressureUnit; /// 10
|
||||
public double PressureLimLo; /// 11
|
||||
public double PressureLimHi; /// 12
|
||||
public double DefaultPressure; /// 13
|
||||
public Unit HumiUnit; /// 14
|
||||
public double HumiLimLo; /// 15
|
||||
public double HumiLimHi; /// 16
|
||||
public double DefaultHumi; /// 17
|
||||
public string Format; /// 18
|
||||
|
||||
/// Schematic drawing info
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
public int MsrdX { get; set; }
|
||||
public int MsrdY { get; set; }
|
||||
public Orient MsrdOrient { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public string MsrdFormat { get { return string.Empty; } }
|
||||
[XmlIgnore]
|
||||
public Config.Unit MsrdUnit { get { return TempUnit; } }
|
||||
[XmlIgnore]
|
||||
public double MsrdValLimLo { get { return TempLimLo; } }
|
||||
[XmlIgnore]
|
||||
public double MsrdValLimHi { get { return TempLimHi; } }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
AmbientCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
Format = string.Empty;
|
||||
}
|
||||
|
||||
public AmbientCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.Ambient;
|
||||
Sz = Sz.M;
|
||||
Factory = factory;
|
||||
Name = name;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
ComPortNr = 6;
|
||||
BaudRate = 19200;
|
||||
Parity = System.IO.Ports.Parity.None;
|
||||
DataBits = 8;
|
||||
StopBits = System.IO.Ports.StopBits.One;
|
||||
Handshake = System.IO.Ports.Handshake.None;
|
||||
TempUnit = Unit.C;
|
||||
TempLimLo = 15;
|
||||
TempLimHi = 30;
|
||||
DefaultTemp = 25;
|
||||
PressureUnit = Unit.hPa;
|
||||
PressureLimLo = 960;
|
||||
PressureLimHi = 1060;
|
||||
DefaultPressure = 1013;
|
||||
HumiUnit = Unit.RPct;
|
||||
HumiLimLo = 20;
|
||||
HumiLimHi = 80;
|
||||
DefaultHumi = 50;
|
||||
Format = "{0:F1} °C\n{1:F0} hPa\n{2:F0} R%";
|
||||
|
||||
MsrdY = 22;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Serial port number", /// 0
|
||||
"Baud rate", /// 1
|
||||
"Parity", /// 2
|
||||
"Data bits", /// 3
|
||||
"Stop bits", /// 4
|
||||
"Handshake", /// 5
|
||||
"Unit of temperature", /// 6
|
||||
"Temperature limit Lo", /// 7
|
||||
"Temperature limit Hi", /// 8
|
||||
"Default temperature", /// 9
|
||||
"Unit of pressure", /// 10
|
||||
"Pressure limit Lo", /// 11
|
||||
"Pressure limit Hi", /// 12
|
||||
"Default pressure", /// 13
|
||||
"Unit of rel. humidity", /// 14
|
||||
"Rel. humidity limit Lo", /// 15
|
||||
"Rel. humidity limit Hi", /// 16
|
||||
"Default retl. humidity", /// 17
|
||||
"Display format", /// 18
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
|
||||
public ICollection<string> ParamValues(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
return new string[] { "150", "300", "600", "1200", "2400", "4800", "9600",
|
||||
"19200", "38400", "57600", "76800", "115200"};
|
||||
case 2:
|
||||
return new string[] { Parity.None.ToString(), Parity.Odd.ToString(), Parity.Even.ToString() };
|
||||
case 3:
|
||||
return new string[] { "7", "8" };
|
||||
case 4:
|
||||
return new string[] { StopBits.None.ToString(),
|
||||
StopBits.One.ToString(),
|
||||
StopBits.OnePointFive.ToString(),
|
||||
StopBits.Two.ToString() };
|
||||
case 5:
|
||||
return new string[] { Handshake.None.ToString(),
|
||||
Handshake.XOnXOff.ToString(),
|
||||
Handshake.RequestToSend.ToString(),
|
||||
Handshake.RequestToSendXOnXOff.ToString() };
|
||||
case 6:
|
||||
return new string[] { "°C", "°F", "K" };
|
||||
case 10:
|
||||
return new string[] { "Pa", "hPa", "mbar", "kPa", "inHg", "psi", "bar", "MPa" };
|
||||
case 14:
|
||||
return new string[] { "R%" };
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: return ComPortNr.ToString();
|
||||
case 1: return BaudRate.ToString();
|
||||
case 2: return Parity.ToString();
|
||||
case 3: return DataBits.ToString();
|
||||
case 4: return StopBits.ToString();
|
||||
case 5: return Handshake.ToString();
|
||||
case 6: return TempUnit.ToDescription();
|
||||
case 7: return TempLimLo.ToString();
|
||||
case 8: return TempLimHi.ToString();
|
||||
case 9: return DefaultTemp.ToString();
|
||||
case 10: return PressureUnit.ToDescription();
|
||||
case 11: return PressureLimLo.ToString();
|
||||
case 12: return PressureLimHi.ToString();
|
||||
case 13: return DefaultPressure.ToString();
|
||||
case 14: return HumiUnit.ToDescription();
|
||||
case 15: return HumiLimLo.ToString();
|
||||
case 16: return HumiLimHi.ToString();
|
||||
case 17: return DefaultHumi.ToString();
|
||||
case 18: return Format.Replace("\n", "<LF>");
|
||||
default:
|
||||
return string.Format("{0} {1}[{2},{3}] Com{4}, {5}Bd, {6}-bits, parity={7}, stopBits={8}, {9}",
|
||||
Name, Shape, X, Y, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string str)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: ComPortNr = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 1: BaudRate = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 2: Parity = TBF.Utils.GetParity(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 3: DataBits = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 4: StopBits = TBF.Utils.GetStopBits(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 5: Handshake = TBF.Utils.GetHandshake(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 6:
|
||||
foreach (var u in new Unit[] { Unit.C, Unit.F, Unit.K })
|
||||
{
|
||||
if (str == u.ToDescription()) { TempUnit = u; return CfgUpdateFlags.RestartRqrd; }
|
||||
}
|
||||
return CfgUpdateFlags.None;
|
||||
case 7: TempLimLo = Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 8: TempLimHi = Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 9: DefaultTemp = Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 10:
|
||||
foreach (var u in new Unit[] { Unit.Pa, Unit.hPa, Unit.mbar, Unit.kPa, Unit.inHg, Unit.psi, Unit.bar, Unit.MPa })
|
||||
{
|
||||
if (str == u.ToDescription()) { PressureUnit = u; return CfgUpdateFlags.RestartRqrd; }
|
||||
}
|
||||
return CfgUpdateFlags.None;
|
||||
case 11: PressureLimLo = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 12: PressureLimHi = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 13: DefaultPressure = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 14:
|
||||
foreach (var u in new Unit[] { Unit.RPct })
|
||||
{
|
||||
if (str == u.ToDescription()) { HumiUnit = u; return CfgUpdateFlags.RestartRqrd; }
|
||||
}
|
||||
return CfgUpdateFlags.None;
|
||||
case 15: HumiLimLo = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 16: HumiLimHi = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 17: DefaultHumi = Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
|
||||
case 18: Format = str.Replace("<LF>", "\n"); return CfgUpdateFlags.RestartRqrd;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string str, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
int idummy;
|
||||
double dummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (int.TryParse(str, out idummy) && idummy > 0) return true;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 10:
|
||||
case 14:
|
||||
if (ParamValues(i).Contains(str)) return true;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
if (TBF.Utils.TryParseSDouble(str, out dummy)) return true;
|
||||
break;
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
if (TBF.Utils.TryParseUDouble(str, out dummy)) return true;
|
||||
break;
|
||||
case 18:
|
||||
return true;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(AmbientCfg prms)
|
||||
{
|
||||
prms.ParentName = this.ParentName;
|
||||
|
||||
prms.Shape = this.Shape;
|
||||
prms.Sz = this.Sz;
|
||||
prms.Orient = this.Orient;
|
||||
prms.Flip = this.Flip;
|
||||
prms.LblX = this.LblX;
|
||||
prms.LblY = this.LblY;
|
||||
prms.LblOrient = this.LblOrient;
|
||||
prms.MsrdX = this.MsrdX;
|
||||
prms.MsrdY = this.MsrdY;
|
||||
prms.MsrdOrient = this.MsrdOrient;
|
||||
|
||||
prms.ComPortNr = this.ComPortNr;
|
||||
prms.BaudRate = this.BaudRate;
|
||||
prms.Parity = this.Parity;
|
||||
prms.DataBits = this.DataBits;
|
||||
prms.StopBits = this.StopBits;
|
||||
prms.Handshake = this.Handshake;
|
||||
prms.TempUnit = this.TempUnit;
|
||||
prms.TempLimLo = this.TempLimLo;
|
||||
prms.TempLimHi = this.TempLimHi;
|
||||
prms.DefaultTemp = this.DefaultTemp;
|
||||
prms.PressureUnit = this.PressureUnit;
|
||||
prms.PressureLimLo = this.PressureLimLo;
|
||||
prms.PressureLimHi = this.PressureLimHi;
|
||||
prms.DefaultPressure = this.DefaultPressure;
|
||||
prms.HumiUnit = this.HumiUnit;
|
||||
prms.HumiLimLo = this.HumiLimLo;
|
||||
prms.HumiLimHi = this.HumiLimHi;
|
||||
prms.DefaultHumi = this.DefaultHumi;
|
||||
prms.Format = this.Format;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
AmbientCfg pars = new AmbientCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Ambient.Greco
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return 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); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new AmbientCfg("Ambient", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(AmbientCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig
|
||||
{
|
||||
public class BenchPath
|
||||
{
|
||||
public int ItemNr;
|
||||
public string Name;
|
||||
public float Qfrom;
|
||||
public float Qto;
|
||||
public ITempMeter TempMtrUp;
|
||||
public ITempMeter TempMtrDown;
|
||||
public IPressureMeter PressMtrUp;
|
||||
public IPressureMeter PressMtrDown;
|
||||
public IPressureMeter PressMtrDelta;
|
||||
public IValve StopBFValve;
|
||||
public IList<IValve> ValvesOpen;
|
||||
public IList<IValve> ValvesClose;
|
||||
|
||||
/// Constructor from name, the rest is empty
|
||||
public BenchPath(string name, int itemNr)
|
||||
{
|
||||
ItemNr = itemNr;
|
||||
Name = name;
|
||||
ValvesOpen = new List<IValve>();
|
||||
ValvesClose = new List<IValve>();
|
||||
}
|
||||
|
||||
/// Constructor from data entity
|
||||
public BenchPath(Config.Entities.BenchPath entity, IList<Rig.Generic.IComponent> components)
|
||||
: this(entity.Name, entity.ItemNr)
|
||||
{
|
||||
Qfrom = entity.Qfrom;
|
||||
Qto = entity.Qto;
|
||||
TempMtrUp = TbfComponents.FindComponent(entity.TempMtrUp, components) as ITempMeter;
|
||||
TempMtrDown = TbfComponents.FindComponent(entity.TempMtrDown, components) as ITempMeter;
|
||||
PressMtrUp = TbfComponents.FindComponent(entity.PressMtrUp, components) as IPressureMeter;
|
||||
PressMtrDown = TbfComponents.FindComponent(entity.PressMtrDown, components) as IPressureMeter;
|
||||
PressMtrDelta = TbfComponents.FindComponent(entity.PressMtrDelta, components) as IPressureMeter;
|
||||
StopBFValve = TbfComponents.FindComponent(entity.StopBFValve, components) as IValve;
|
||||
|
||||
string[] vOpen = entity.ValvesOpen.Split(new char[] { ';' });
|
||||
ValvesOpen = new List<IValve>();
|
||||
foreach (var vName in vOpen) ValvesOpen.Add((IValve)TbfComponents.FindComponent(vName, components));
|
||||
|
||||
string[] vClose = entity.ValvesClose.Split(new char[] { ';' });
|
||||
ValvesClose = new List<IValve>();
|
||||
foreach (var vName in vClose) ValvesClose.Add((IValve)TbfComponents.FindComponent(vName, components));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} StopBF={1}",
|
||||
Name,
|
||||
(StopBFValve != null) ? StopBFValve.Name : "---");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dirichlet.Numerics;
|
||||
using log4net;
|
||||
using TBF.Rig.ControlBoard;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Pump
|
||||
{
|
||||
public class Pump : ComponentBase, GenericDevices.IPump, GenericDevices.IValve, SchematicDrawing.IDrawingItCmpnt
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Pump));
|
||||
public override string ToString() { return string.Format("Pump({0})", Cfg.ToString(1)); }
|
||||
|
||||
readonly PumpCfg pumpCfg;
|
||||
public SchematicDrawing.IDrawingItem DrawingItem { get { return pumpCfg as SchematicDrawing.IDrawingItem; } }
|
||||
|
||||
public int Delay { get { return pumpCfg.Delay; } }
|
||||
|
||||
public ValveCategory Category { get { return ValveCategory.Feeding; } } /// Pump category is Feeding
|
||||
|
||||
public GenericDevices.IValve CoupledTo { get { return null; } }
|
||||
public bool InvertCouple { get { return false; } }
|
||||
public int LagOpening { get { return 0; } }
|
||||
public int LagClosing { get { return 0; } }
|
||||
|
||||
public double Power { get { return State ? 100.0 : 0; } }
|
||||
|
||||
|
||||
readonly IControlBoard controlBoard;
|
||||
readonly int bitPosition; /// 0 .. 127
|
||||
|
||||
public readonly UInt128 Mask; /// derived from bitPosition in the constructor
|
||||
|
||||
|
||||
public Pump()
|
||||
{
|
||||
}
|
||||
|
||||
public Pump(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
pumpCfg = cfg as PumpCfg;
|
||||
|
||||
controlBoard = TbfComponents.FindComponent(cfg.ParentName, components) as IControlBoard;
|
||||
if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent");
|
||||
|
||||
bitPosition = pumpCfg.BitNr;
|
||||
Mask = (((UInt128)1) << pumpCfg.BitNr);
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public bool State
|
||||
{
|
||||
get { return (controlBoard.Route & Mask) != 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Pump
|
||||
{
|
||||
public class PumpCfg : ComponentCfgBase, IChildComponentCfg, IRouteBasedDrawingItem
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(PumpCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new PumpCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int BitNr { get; set; }
|
||||
public bool Inverted { get; set; } /// When true the pump function is inverted: 0 = on, 1 = off
|
||||
public int Delay;
|
||||
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
[XmlIgnore]
|
||||
public IList<GEdge> EdgesToSet { get; set; }
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
PumpCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
EdgesToSet = new List<GEdge>();
|
||||
}
|
||||
|
||||
public PumpCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.Pump;
|
||||
Sz = Sz.M;
|
||||
|
||||
Factory = factory;
|
||||
Name = "P";
|
||||
ParentName = "CB";
|
||||
BitNr = 0;
|
||||
Delay = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, Parent={1}, Bit={2}, Delay={3}",
|
||||
Name,
|
||||
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
|
||||
BitNr,
|
||||
Delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.BuiltIn.Pump
|
||||
{
|
||||
partial class PumpCfgCtrl
|
||||
{
|
||||
/// <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.bitPositionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.bitPositionLabel = 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.delayTextBox = new System.Windows.Forms.TextBox();
|
||||
this.delayLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// bitPositionTextBox
|
||||
//
|
||||
this.bitPositionTextBox.Enabled = false;
|
||||
this.bitPositionTextBox.Location = new System.Drawing.Point(122, 99);
|
||||
this.bitPositionTextBox.Name = "bitPositionTextBox";
|
||||
this.bitPositionTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.bitPositionTextBox.TabIndex = 6;
|
||||
//
|
||||
// bitPositionLabel
|
||||
//
|
||||
this.bitPositionLabel.AutoSize = true;
|
||||
this.bitPositionLabel.Location = new System.Drawing.Point(36, 102);
|
||||
this.bitPositionLabel.Name = "bitPositionLabel";
|
||||
this.bitPositionLabel.Size = new System.Drawing.Size(59, 13);
|
||||
this.bitPositionLabel.TabIndex = 5;
|
||||
this.bitPositionLabel.Text = "Bit Position";
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(36, 76);
|
||||
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(122, 47);
|
||||
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, 50);
|
||||
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(119, 21);
|
||||
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(122, 73);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.parentNameComboBox.TabIndex = 4;
|
||||
//
|
||||
// delayTextBox
|
||||
//
|
||||
this.delayTextBox.Enabled = false;
|
||||
this.delayTextBox.Location = new System.Drawing.Point(122, 124);
|
||||
this.delayTextBox.Name = "delayTextBox";
|
||||
this.delayTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.delayTextBox.TabIndex = 8;
|
||||
//
|
||||
// delayLabel
|
||||
//
|
||||
this.delayLabel.AutoSize = true;
|
||||
this.delayLabel.Location = new System.Drawing.Point(36, 127);
|
||||
this.delayLabel.Name = "delayLabel";
|
||||
this.delayLabel.Size = new System.Drawing.Size(48, 13);
|
||||
this.delayLabel.TabIndex = 7;
|
||||
this.delayLabel.Text = "Delay [s]";
|
||||
//
|
||||
// PumpCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.delayTextBox);
|
||||
this.Controls.Add(this.delayLabel);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.bitPositionTextBox);
|
||||
this.Controls.Add(this.bitPositionLabel);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "PumpCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 200);
|
||||
this.Load += new System.EventHandler(this.PumpCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox bitPositionTextBox;
|
||||
private System.Windows.Forms.Label bitPositionLabel;
|
||||
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.TextBox delayTextBox;
|
||||
private System.Windows.Forms.Label delayLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Pump
|
||||
{
|
||||
public partial class PumpCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
PumpCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as PumpCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public PumpCfgCtrl()
|
||||
{
|
||||
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 (cmpnt.ClassName.Contains("ControlBoard"))
|
||||
{
|
||||
parentNameComboBox.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;
|
||||
bitPositionTextBox.Text = config.BitNr.ToString();
|
||||
delayTextBox.Text = config.Delay.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
bitPositionTextBox.Enabled = true;
|
||||
delayTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
config.Name = nameTextBox.Text;
|
||||
config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
|
||||
config.BitNr = int.Parse(bitPositionTextBox.Text);
|
||||
config.Delay = int.Parse(delayTextBox.Text);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Parent Name'";
|
||||
}
|
||||
if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 128)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Bit Position' should be between 0 and 127";
|
||||
}
|
||||
if (!int.TryParse(delayTextBox.Text, out dummy) || dummy < 0 || dummy >= 300 || (dummy % StateMachine.Period) != 0)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Delay' should be between 0 and 300s (5min)";
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Pump
|
||||
{
|
||||
public class PumpFactory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "Pump"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Pump.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Pump(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Pump(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new PumpCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(PumpCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dirichlet.Numerics;
|
||||
using log4net;
|
||||
using TBF.Rig.ControlBoard.Legacy;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
{
|
||||
public class Pump : ComponentBase, GenericDevices.IPumpFM, GenericDevices.IValve, IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Pump));
|
||||
public override string ToString() { return string.Format("PumpTandem({0})", Cfg.ToString(1)); }
|
||||
|
||||
readonly PumpCfg pumpCfg;
|
||||
|
||||
readonly GenericDevices.IPump pump1;
|
||||
readonly GenericDevices.IPump pump2;
|
||||
|
||||
readonly GenericDevices.IPumpFM pumpFm1;
|
||||
readonly GenericDevices.IPumpFM pumpFm2;
|
||||
|
||||
public bool State { get { return pump1.State || pump2.State; } }
|
||||
public int Delay { get { return Math.Max(pump1.Delay, pump2.Delay); } }
|
||||
public ValveCategory Category { get { return ValveCategory.Feeding; } } /// Pump category is Feeding
|
||||
public GenericDevices.IValve CoupledTo { get { return null; } }
|
||||
public bool InvertCouple { get { return false; } }
|
||||
public int LagOpening { get { return 0; } }
|
||||
public int LagClosing { get { return 0; } }
|
||||
|
||||
/// <summary>
|
||||
/// Pump power in [%] in range 0 .. 100.0
|
||||
/// </summary>
|
||||
public double Power
|
||||
{
|
||||
get { return (pump1.Power + pump2.Power) / 2; }
|
||||
}
|
||||
|
||||
|
||||
readonly UInt128 mask1;
|
||||
readonly UInt128 mask2;
|
||||
public UInt128 Mask { get { return mask1 | mask2; } } /// derived from masks of two pumps
|
||||
|
||||
|
||||
public Pump()
|
||||
{
|
||||
}
|
||||
|
||||
public Pump(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
pumpCfg = cfg as PumpCfg;
|
||||
|
||||
pump1 = (GenericDevices.IPump)TbfComponents.FindComponent(pumpCfg.Pump1, components);
|
||||
if (pump1 == null) throw new Exception("Cannot find component Pump 1");
|
||||
|
||||
pump2 = (GenericDevices.IPump)TbfComponents.FindComponent(pumpCfg.Pump2, components);
|
||||
if (pump2 == null) throw new Exception("Cannot find component Pump 2");
|
||||
|
||||
pumpFm1 = pump1 as GenericDevices.IPumpFM;
|
||||
pumpFm2 = pump2 as GenericDevices.IPumpFM;
|
||||
|
||||
if (pump1 is BuiltIn.Pump.Pump) { mask1 = (pump1 as BuiltIn.Pump.Pump).Mask; }
|
||||
else if (pump1 is Elde.PumpWithFM.Pump) { mask1 = (pump1 as Elde.PumpWithFM.Pump).Mask; }
|
||||
else if (pump1 is Danfoss.VLT2800.Pump) { mask1 = (pump1 as Danfoss.VLT2800.Pump).Mask; }
|
||||
else { mask1 = 0; }
|
||||
|
||||
if (pump2 is BuiltIn.Pump.Pump) { mask2 = (pump2 as BuiltIn.Pump.Pump).Mask; }
|
||||
else if (pump2 is Elde.PumpWithFM.Pump) { mask2 = (pump2 as Elde.PumpWithFM.Pump).Mask; }
|
||||
else if (pump2 is Danfoss.VLT2800.Pump) { mask2 = (pump2 as Danfoss.VLT2800.Pump).Mask; }
|
||||
else { mask2 = 0; }
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
public void TurnOn(double powerArg)
|
||||
{
|
||||
if ((pumpFm1 != null) && (pumpFm2 != null))
|
||||
{
|
||||
pumpFm1.TurnOn(powerArg);
|
||||
pumpFm2.TurnOn(powerArg);
|
||||
}
|
||||
else if ((pumpFm1 != null) && (pumpFm2 == null))
|
||||
{
|
||||
// TODO
|
||||
if (powerArg >= 50)
|
||||
{
|
||||
pumpFm1.TurnOn(2 * (powerArg - 50.0));
|
||||
//pump2.
|
||||
}
|
||||
else
|
||||
{
|
||||
pumpFm1.TurnOn(2 * powerArg);
|
||||
//pump2.
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
public void TurnOff()
|
||||
{
|
||||
if ((pumpFm1 != null) && (pumpFm2 != null))
|
||||
{
|
||||
pumpFm1.TurnOff();
|
||||
pumpFm2.TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The currently running operation.
|
||||
/// </summary>
|
||||
public enum CurrentOp
|
||||
{
|
||||
None,
|
||||
TurnOn,
|
||||
TurnOff,
|
||||
}
|
||||
///
|
||||
CurrentOp currentOp;
|
||||
|
||||
double powerForOp;
|
||||
|
||||
/// <summary>
|
||||
/// Turn the pump frequency inverter on.
|
||||
/// </summary>
|
||||
public IOperation TurnOnOp(double powerArg)
|
||||
{
|
||||
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
|
||||
currentOp = CurrentOp.TurnOn;
|
||||
powerForOp = powerArg;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn the pump frequency inverter on.
|
||||
/// </summary>
|
||||
public IOperation TurnOffOp()
|
||||
{
|
||||
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
|
||||
currentOp = CurrentOp.TurnOff;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Start the operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
switch (currentOp)
|
||||
{
|
||||
case CurrentOp.TurnOn:
|
||||
TurnOn(powerForOp);
|
||||
return;
|
||||
case CurrentOp.TurnOff:
|
||||
default:
|
||||
TurnOff();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run the operation</summary>
|
||||
public Event Run()
|
||||
{
|
||||
return Event.TurnPumpOnOffDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop the operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
currentOp = CurrentOp.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
{
|
||||
public class PumpCfg : ComponentCfgBase, IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(PumpCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new PumpCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public string Pump1; /// Name of the pump 1 component
|
||||
public string Pump2; /// Name of the pump 2 component
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
PumpCfg()
|
||||
{
|
||||
Name = "PumpTandem";
|
||||
ParentName = string.Empty;
|
||||
Pump1 = string.Empty;
|
||||
Pump2 = string.Empty;
|
||||
}
|
||||
|
||||
public PumpCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
this.Factory = factory;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, Pump1={1}, Pump2={2}",
|
||||
Name,
|
||||
string.IsNullOrEmpty(Pump1) ? "-" : Pump1,
|
||||
string.IsNullOrEmpty(Pump2) ? "-" : Pump2);
|
||||
}
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
{
|
||||
partial class PumpCfgCtrl
|
||||
{
|
||||
/// <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.pump2ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.pump2Label = new System.Windows.Forms.Label();
|
||||
this.pump1ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.pump1Label = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(140, 47);
|
||||
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(30, 50);
|
||||
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(119, 21);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// pump2ComboBox
|
||||
//
|
||||
this.pump2ComboBox.Enabled = false;
|
||||
this.pump2ComboBox.FormattingEnabled = true;
|
||||
this.pump2ComboBox.Location = new System.Drawing.Point(140, 96);
|
||||
this.pump2ComboBox.Name = "pump2ComboBox";
|
||||
this.pump2ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.pump2ComboBox.TabIndex = 12;
|
||||
//
|
||||
// pump2Label
|
||||
//
|
||||
this.pump2Label.AutoSize = true;
|
||||
this.pump2Label.Location = new System.Drawing.Point(30, 99);
|
||||
this.pump2Label.Name = "pump2Label";
|
||||
this.pump2Label.Size = new System.Drawing.Size(43, 13);
|
||||
this.pump2Label.TabIndex = 11;
|
||||
this.pump2Label.Text = "Pump 2";
|
||||
//
|
||||
// pump1ComboBox
|
||||
//
|
||||
this.pump1ComboBox.Enabled = false;
|
||||
this.pump1ComboBox.FormattingEnabled = true;
|
||||
this.pump1ComboBox.Location = new System.Drawing.Point(140, 71);
|
||||
this.pump1ComboBox.Name = "pump1ComboBox";
|
||||
this.pump1ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.pump1ComboBox.TabIndex = 10;
|
||||
//
|
||||
// pump1Label
|
||||
//
|
||||
this.pump1Label.AutoSize = true;
|
||||
this.pump1Label.Location = new System.Drawing.Point(30, 74);
|
||||
this.pump1Label.Name = "pump1Label";
|
||||
this.pump1Label.Size = new System.Drawing.Size(43, 13);
|
||||
this.pump1Label.TabIndex = 9;
|
||||
this.pump1Label.Text = "Pump 1";
|
||||
//
|
||||
// PumpCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.pump2ComboBox);
|
||||
this.Controls.Add(this.pump2Label);
|
||||
this.Controls.Add(this.pump1ComboBox);
|
||||
this.Controls.Add(this.pump1Label);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "PumpCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 200);
|
||||
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.ComboBox pump2ComboBox;
|
||||
private System.Windows.Forms.Label pump2Label;
|
||||
private System.Windows.Forms.ComboBox pump1ComboBox;
|
||||
private System.Windows.Forms.Label pump1Label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
{
|
||||
public partial class PumpCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parentDlg;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
PumpCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as PumpCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public PumpCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PumpCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parentDlg = ParentForm as ComponentParametersDlg;
|
||||
if (parentDlg == null) return;
|
||||
|
||||
if (parentDlg.CmpntEntities != null)
|
||||
{
|
||||
foreach (var cmpnt in parentDlg.CmpntEntities)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is BuiltIn.Pump.PumpFactory ||
|
||||
TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.PumpWithFM.PumpFactory ||
|
||||
TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Danfoss.VLT2800.PumpFactory ||
|
||||
TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is BuiltIn.PumpTandem.PumpFactory)
|
||||
{
|
||||
pump1ComboBox.Items.Add(cmpnt.Name);
|
||||
pump2ComboBox.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;
|
||||
pump1ComboBox.Text = string.IsNullOrEmpty(config.Pump1) ? "---" : config.Pump1;
|
||||
pump2ComboBox.Text = string.IsNullOrEmpty(config.Pump2) ? "---" : config.Pump2;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
pump1ComboBox.Enabled = true;
|
||||
pump2ComboBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (!pump1ComboBox.Items.Contains(pump1ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Pump 1'";
|
||||
}
|
||||
if (!pump2ComboBox.Items.Contains(pump2ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Pump 2'";
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
config.Name = nameTextBox.Text;
|
||||
config.Pump1 = pump1ComboBox.Text.Equals("---") ? string.Empty : pump1ComboBox.Text;
|
||||
config.Pump2 = pump2ComboBox.Text.Equals("---") ? string.Empty : pump2ComboBox.Text;
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
{
|
||||
public class PumpFactory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "PumpTandem"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Pump.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Pump(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Pump(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new PumpCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(PumpCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using Dirichlet.Numerics;
|
||||
using TBF.Rig.ControlBoard;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.BuiltIn
|
||||
{
|
||||
public class SetValvesOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetValvesOp));
|
||||
|
||||
/// Set by the constructor
|
||||
IControlBoard controlBoard;
|
||||
|
||||
class SwitchPoint
|
||||
{
|
||||
public int TimeSec; /// Relative time in [s] from the start of the operation
|
||||
public IList<IValve> VOpen; /// List of valves to open in this point of time
|
||||
public IList<IValve> VClose; /// List of valves to close in this point of time
|
||||
public UInt128 MasksOpen; /// OR-ed bitmasks of valves to open in this point of time
|
||||
public UInt128 MasksClose; /// OR-ed bitmasks of valves to close in this point of time
|
||||
|
||||
public SwitchPoint(int time, IList<IValve> vOpen, IList<IValve> vClose)
|
||||
{
|
||||
this.TimeSec = time;
|
||||
this.VOpen = (vOpen == null) ? new List<IValve>() : vOpen;
|
||||
this.VClose = (vClose == null) ? new List<IValve>() : vClose;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Max. delay of all valves that were opened or closed
|
||||
/// </summary>
|
||||
/// <param name="changed">'ulong' with bits of valves that were actually changed set ot '1'</param>
|
||||
/// <returns>Delay in [s]</returns>
|
||||
public int MaxDelay(UInt128 changed)
|
||||
{
|
||||
int max = 0;
|
||||
foreach (var vlv in VOpen)
|
||||
{
|
||||
/// Skip the delay evaluation and update in case the valve/pump have not changed
|
||||
if (vlv is Valve.Valve && ((vlv as Valve.Valve).Mask & changed) == 0) continue;
|
||||
if (vlv is Pump.Pump && ((vlv as Pump.Pump).Mask & changed) == 0) continue;
|
||||
if (vlv is Elde.PumpWithFM.Pump && ((vlv as Elde.PumpWithFM.Pump).Mask & changed) == 0) continue;
|
||||
if (vlv is Danfoss.VLT2800.Pump && ((vlv as Danfoss.VLT2800.Pump).Mask & changed) == 0) continue;
|
||||
if (vlv is Modbus.PumpFM.DanfossVLT.Pump && ((vlv as Modbus.PumpFM.DanfossVLT.Pump).Mask & changed) == 0) continue;
|
||||
|
||||
if ((vlv != null) && (vlv.Delay > max)) max = vlv.Delay;
|
||||
}
|
||||
foreach (var vlv in VClose)
|
||||
{
|
||||
/// Skip the delay evaluation and update in case the valve/pump have not changed
|
||||
if (vlv is Valve.Valve && ((vlv as Valve.Valve).Mask & changed) == 0) continue;
|
||||
if (vlv is Pump.Pump && ((vlv as Pump.Pump).Mask & changed) == 0) continue;
|
||||
if (vlv is Elde.PumpWithFM.Pump && ((vlv as Elde.PumpWithFM.Pump).Mask & changed) == 0) continue;
|
||||
if (vlv is Danfoss.VLT2800.Pump && ((vlv as Danfoss.VLT2800.Pump).Mask & changed) == 0) continue;
|
||||
if (vlv is Modbus.PumpFM.DanfossVLT.Pump && ((vlv as Modbus.PumpFM.DanfossVLT.Pump).Mask & changed) == 0) continue;
|
||||
|
||||
if ((vlv != null) && (vlv.Delay > max)) max = vlv.Delay;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
IList<SwitchPoint> switchPointsRaw;
|
||||
IList<SwitchPoint> switchPoints;
|
||||
int nextIx;
|
||||
int swStartTime;
|
||||
int maxDelayTime; /// Max. delay from all valve/pump switches.
|
||||
/// Relative time in [s] from the start of the operation
|
||||
|
||||
/// <summary>
|
||||
/// Processes coupled valves and creates switch points.
|
||||
/// </summary>
|
||||
/// <param name="valvesOpen">A list of opening master valves</param>
|
||||
/// <param name="valvesClose">A list of closing master valves</param>
|
||||
/// <returns></returns>
|
||||
IList<SwitchPoint> AddSwitchPoints(IList<SwitchPoint> swPoints, IList<IValve> valvesOpen, IList<IValve> valvesClose, int time)
|
||||
{
|
||||
int ix0 = swPoints.Count;
|
||||
swPoints.Add(new SwitchPoint(time, valvesOpen, valvesClose));
|
||||
|
||||
foreach (var valve in StateMachine.CoupledValves)
|
||||
{
|
||||
if ((!valve.InvertCouple && valvesOpen.Contains(valve.CoupledTo)) ||
|
||||
(valve.InvertCouple && valvesClose.Contains(valve.CoupledTo)))
|
||||
{
|
||||
/// The coupled valve 'valve' is opening
|
||||
int lag = time + valve.LagOpening;
|
||||
if (lag == time)
|
||||
{
|
||||
swPoints[ix0].VOpen.Add(valve);
|
||||
}
|
||||
else
|
||||
{
|
||||
swPoints.Add(new SwitchPoint(lag, ValveBase.MakeList(valve), null));
|
||||
}
|
||||
}
|
||||
else if ((!valve.InvertCouple && valvesClose.Contains(valve.CoupledTo)) ||
|
||||
(valve.InvertCouple && valvesOpen.Contains(valve.CoupledTo)))
|
||||
{
|
||||
/// The coupled valve 'valve' is closing
|
||||
int lag = time + valve.LagClosing;
|
||||
if (lag == time)
|
||||
{
|
||||
swPoints[ix0].VClose.Add(valve);
|
||||
}
|
||||
else
|
||||
{
|
||||
swPoints.Add(new SwitchPoint(lag, null, ValveBase.MakeList(valve)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return swPoints;
|
||||
}
|
||||
|
||||
|
||||
IList<SwitchPoint> SortAndMergeSwitchPoints(IList<SwitchPoint> unsorted)
|
||||
{
|
||||
IList<SwitchPoint> result = new List<SwitchPoint>();
|
||||
|
||||
SwitchPoint lastAdded = null;
|
||||
while (unsorted.Count > 0)
|
||||
{
|
||||
SwitchPoint first = null;
|
||||
foreach (var point in unsorted)
|
||||
{
|
||||
if (first == null || first.TimeSec > point.TimeSec) first = point;
|
||||
}
|
||||
if (lastAdded == null || lastAdded.TimeSec != first.TimeSec)
|
||||
{
|
||||
result.Add(first);
|
||||
lastAdded = first;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastAdded.VOpen = ValveBase.Merge(lastAdded.VOpen, first.VOpen);
|
||||
lastAdded.VClose = ValveBase.Merge(lastAdded.VClose, first.VClose);
|
||||
}
|
||||
unsorted.Remove(first);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void MakeMasks(IList<SwitchPoint> switchPoints, int timeShift)
|
||||
{
|
||||
foreach (var point in switchPoints)
|
||||
{
|
||||
/// Only Elde.Valve valves are used, other valves are ignored
|
||||
point.MasksOpen = 0;
|
||||
foreach (var valve in point.VOpen)
|
||||
{
|
||||
if (valve is Valve.Valve) point.MasksOpen |= (valve as Valve.Valve).Mask;
|
||||
if (valve is Pump.Pump) point.MasksOpen |= (valve as Pump.Pump).Mask;
|
||||
if (valve is Elde.PumpWithFM.Pump) point.MasksOpen |= (valve as Elde.PumpWithFM.Pump).Mask;
|
||||
if (valve is Danfoss.VLT2800.Pump) point.MasksOpen |= (valve as Danfoss.VLT2800.Pump).Mask;
|
||||
if (valve is Modbus.PumpFM.DanfossVLT.Pump) point.MasksOpen |= (valve as Modbus.PumpFM.DanfossVLT.Pump).Mask;
|
||||
if (valve is PumpTandem.Pump) point.MasksOpen |= (valve as PumpTandem.Pump).Mask;
|
||||
}
|
||||
point.MasksClose = 0;
|
||||
foreach (var valve in point.VClose)
|
||||
{
|
||||
if (valve is Valve.Valve) point.MasksClose |= (valve as Valve.Valve).Mask;
|
||||
if (valve is Pump.Pump) point.MasksClose |= (valve as Pump.Pump).Mask;
|
||||
if (valve is Elde.PumpWithFM.Pump) point.MasksClose |= (valve as Elde.PumpWithFM.Pump).Mask;
|
||||
if (valve is Danfoss.VLT2800.Pump) point.MasksClose |= (valve as Danfoss.VLT2800.Pump).Mask;
|
||||
if (valve is Modbus.PumpFM.DanfossVLT.Pump) point.MasksClose |= (valve as Modbus.PumpFM.DanfossVLT.Pump).Mask;
|
||||
if (valve is PumpTandem.Pump) point.MasksClose |= (valve as PumpTandem.Pump).Mask;
|
||||
}
|
||||
point.TimeSec += timeShift;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Open and/or close multiple valves.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="cb">Control board device</param>
|
||||
/// <param name="valvesOpen">A list of opening master valves</param>
|
||||
/// <param name="valvesClose">A list of closing master valves</param>
|
||||
/// <remarks>Only Elde.Valve valves are used, other valves on the lists are ignored</remarks>
|
||||
public SetValvesOp(IControlBoard cb, IList<IValve> valvesOpen, IList<IValve> valvesClose)
|
||||
{
|
||||
controlBoard = cb;
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
|
||||
if (valvesOpen == null) valvesOpen = new List<IValve>();
|
||||
if (valvesClose == null) valvesClose = new List<IValve>();
|
||||
|
||||
switchPointsRaw = new List<SwitchPoint>();
|
||||
AddSwitchPoints(switchPointsRaw, valvesOpen, valvesClose, 0);
|
||||
switchPoints = SortAndMergeSwitchPoints(switchPointsRaw);
|
||||
int timeShift = -switchPoints[0].TimeSec;
|
||||
MakeMasks(switchPoints, timeShift);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open one valve and/or close one valve.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="cb">Control board device</param>
|
||||
/// <param name="valveOpen">Valve to be opened</param>
|
||||
/// <param name="valveClose">Valve to be closed</param>
|
||||
/// <remarks>Only Elde.Valve valves are used, other valves on the lists are ignored</remarks>
|
||||
public SetValvesOp(IControlBoard cb, IValve valveOpen, IValve valveClose)
|
||||
: this(cb, ValveBase.MakeList(valveOpen), ValveBase.MakeList(valveClose))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OPEN or CLOSE start/stop valve and associated valves and/or pumps.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="controlBoard">Control board device</param>
|
||||
/// <param name="open">true: open start valve, false: close start valve</param>
|
||||
/// <param name="outPath">OutputPath specifying the start valve and associated valves/pumps</param>
|
||||
/// <remarks>Only Elde.Valve valves are used, other valves on the lists are ignored</remarks>
|
||||
public SetValvesOp(IControlBoard cb, bool open, OutputPath outPath)
|
||||
{
|
||||
controlBoard = cb;
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
|
||||
IList<IValve> none = new List<IValve>(); /// An empty list of valves
|
||||
switchPointsRaw = new List<SwitchPoint>();
|
||||
|
||||
if (open)
|
||||
{
|
||||
if (outPath.InvertSV1)
|
||||
AddSwitchPoints(switchPointsRaw, none, ValveBase.MakeList(outPath.StartValve1), 0); /// close SV1
|
||||
else
|
||||
AddSwitchPoints(switchPointsRaw, ValveBase.MakeList(outPath.StartValve1), none, 0); /// open SV1
|
||||
|
||||
if (outPath.StartValve2 != null)
|
||||
{
|
||||
if (outPath.InvertSV2)
|
||||
AddSwitchPoints(switchPointsRaw, none, ValveBase.MakeList(outPath.StartValve2), -outPath.LagSV2); /// close SV2 after lag
|
||||
else
|
||||
AddSwitchPoints(switchPointsRaw, ValveBase.MakeList(outPath.StartValve2), none, -outPath.LagSV2); /// open SV2 after lag
|
||||
}
|
||||
|
||||
if (outPath.StartValve3 != null)
|
||||
{
|
||||
if (outPath.InvertSV3)
|
||||
AddSwitchPoints(switchPointsRaw, none, ValveBase.MakeList(outPath.StartValve3), -outPath.LagSV3); /// close SV3 after lag
|
||||
else
|
||||
AddSwitchPoints(switchPointsRaw, ValveBase.MakeList(outPath.StartValve3), none, -outPath.LagSV3); /// open SV3 after lag
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outPath.InvertSV1)
|
||||
AddSwitchPoints(switchPointsRaw, ValveBase.MakeList(outPath.StartValve1), none, 0); /// open SV1
|
||||
else
|
||||
AddSwitchPoints(switchPointsRaw, none, ValveBase.MakeList(outPath.StartValve1), 0); /// close SV1
|
||||
|
||||
if (outPath.StartValve2 != null)
|
||||
{
|
||||
if (outPath.InvertSV2)
|
||||
AddSwitchPoints(switchPointsRaw, ValveBase.MakeList(outPath.StartValve2), none, outPath.LagSV2); /// open SV2 after lag
|
||||
else
|
||||
AddSwitchPoints(switchPointsRaw, none, ValveBase.MakeList(outPath.StartValve2), outPath.LagSV2); /// close SV2 after lag
|
||||
}
|
||||
|
||||
if (outPath.StartValve3 != null)
|
||||
{
|
||||
if (outPath.InvertSV3)
|
||||
AddSwitchPoints(switchPointsRaw, ValveBase.MakeList(outPath.StartValve3), none, outPath.LagSV3); /// open SV3 after lag
|
||||
else
|
||||
AddSwitchPoints(switchPointsRaw, none, ValveBase.MakeList(outPath.StartValve3), outPath.LagSV3); /// close SV3 after lag
|
||||
}
|
||||
}
|
||||
|
||||
switchPoints = SortAndMergeSwitchPoints(switchPointsRaw);
|
||||
int timeShift = -switchPoints[0].TimeSec;
|
||||
MakeMasks(switchPoints, timeShift);
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
UInt128 changed = controlBoard.SetValves(switchPoints[0].MasksOpen, switchPoints[0].MasksClose, StateMachine.ExtendedValves);
|
||||
swStartTime = StateMachine.Time;
|
||||
maxDelayTime = switchPoints[0].MaxDelay(changed);
|
||||
nextIx = 1;
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.SetValvesDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (nextIx >= switchPoints.Count)
|
||||
{
|
||||
return (StateMachine.Time >= swStartTime + maxDelayTime) ? Event.ValvesSet : Event.ValvesBusy;
|
||||
}
|
||||
|
||||
if (StateMachine.Time >= swStartTime + switchPoints[nextIx].TimeSec)
|
||||
{
|
||||
UInt128 changed = controlBoard.SetValves(switchPoints[nextIx].MasksOpen, switchPoints[nextIx].MasksClose, StateMachine.ExtendedValves);
|
||||
|
||||
int nextDelay = switchPoints[nextIx].MaxDelay(changed);
|
||||
if (switchPoints[nextIx].TimeSec + nextDelay > maxDelayTime)
|
||||
{
|
||||
maxDelayTime = switchPoints[nextIx].TimeSec + nextDelay;
|
||||
}
|
||||
|
||||
nextIx++;
|
||||
}
|
||||
|
||||
return Event.ValvesBusy;
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dirichlet.Numerics;
|
||||
using log4net;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Valve
|
||||
{
|
||||
/// <summary>
|
||||
/// Plain valve, open/close state is controlled by 1 bit from the route
|
||||
/// </summary>
|
||||
public class Valve : ValveBase, IValve, SchematicDrawing.IDrawingItCmpnt
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Valve));
|
||||
public override string ToString() { return string.Format("Valve({0})", Cfg.ToString(1)); }
|
||||
|
||||
readonly ValveCfg valveCfg;
|
||||
public SchematicDrawing.IDrawingItem DrawingItem { get { return valveCfg as SchematicDrawing.IDrawingItem; } }
|
||||
|
||||
readonly TBF.Rig.ControlBoard.IControlBoard controlBoard;
|
||||
|
||||
public ValveCategory Category { get { return valveCfg.Category; } }
|
||||
public int Delay { get { return valveCfg.OpenCloseTime; } }
|
||||
public bool Inverted { get { return valveCfg.Inverted; } }
|
||||
|
||||
public IValve CoupledTo { get { return coupledTo; } }
|
||||
readonly IValve coupledTo;
|
||||
|
||||
public bool InvertCouple { get { return valveCfg.InvertCouple; } }
|
||||
public int LagOpening { get { return valveCfg.LagOpening; } }
|
||||
public int LagClosing { get { return valveCfg.LagClosing; } }
|
||||
|
||||
public readonly UInt128 Mask; /// derived from bitPosition in the constructor
|
||||
|
||||
public int BitPosition { get { return valveCfg.BitNr; } }
|
||||
|
||||
|
||||
public Valve()
|
||||
{
|
||||
}
|
||||
|
||||
public Valve(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
valveCfg = cfg as ValveCfg;
|
||||
|
||||
controlBoard = TbfComponents.FindComponent(cfg.ParentName, components) as TBF.Rig.ControlBoard.IControlBoard;
|
||||
if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent");
|
||||
|
||||
if (valveCfg.BitNr < 0 || valveCfg.BitNr >= 128)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("position");
|
||||
}
|
||||
this.Mask = (((UInt128)1) << valveCfg.BitNr);
|
||||
|
||||
if (valveCfg.CoupledToName != null)
|
||||
{
|
||||
coupledTo = (IValve)TbfComponents.FindComponent(valveCfg.CoupledToName, components);
|
||||
}
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public bool State
|
||||
{
|
||||
get { return (controlBoard.Route & Mask) != 0; }
|
||||
}
|
||||
|
||||
|
||||
#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)
|
||||
{
|
||||
ValveCfg tmpcfg = args.Cfg as ValveCfg;
|
||||
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
|
||||
{
|
||||
if (args.Command == CfgChangeCmd.CfgChange)
|
||||
{
|
||||
valveCfg.OpenCloseTime = tmpcfg.OpenCloseTime;
|
||||
valveCfg.LagOpening = tmpcfg.LagOpening;
|
||||
valveCfg.LagClosing = tmpcfg.LagClosing;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion Configuration Change Handling
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Valve
|
||||
{
|
||||
public class ValveCfg : ComponentCfgBase, IChildComponentCfg, IRouteBasedDrawingItem
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ValveCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new ValveCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int BitNr { get; set; } /// Bit-position
|
||||
public bool Inverted { get; set; } /// When true the valve function is inverted: 0 = open, 1 = closed
|
||||
public ValveCategory Category; /// None, Feeding, Bench or Output
|
||||
public int OpenCloseTime; /// Delay for SetValvesOp operations
|
||||
///
|
||||
public string CoupledToName; /// Name of the coupled valve or null
|
||||
public bool InvertCouple; /// The coupled valve has inverted position
|
||||
public int LagOpening; /// Delay (referred to the master valve) when opening this valve in [s]
|
||||
public int LagClosing; /// Delay (referred to the master valve) when closing this valve in [s]
|
||||
/// Negative values of delays mean an earlier function of the coupled valve.
|
||||
|
||||
/// Schematic drawing info
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
[XmlIgnore]
|
||||
public IList<GEdge> EdgesToSet { get; set; }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ValveCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
EdgesToSet = new List<GEdge>();
|
||||
}
|
||||
|
||||
public ValveCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.Valve;
|
||||
Sz = Sz.M;
|
||||
|
||||
Factory = factory;
|
||||
Name = "V";
|
||||
ParentName = "UniCB";
|
||||
BitNr = 0;
|
||||
Category = ValveCategory.None;
|
||||
OpenCloseTime = 1;
|
||||
Inverted = false;
|
||||
CoupledToName = string.Empty;
|
||||
InvertCouple = false;
|
||||
LagOpening = 0;
|
||||
LagClosing = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("{0}({1}) {2}[{3},{4}] bit={5} inv={6} delay={7}s cat={8} coupled to={9} inv.couple={10} lagO={11}s lagC={12}s",
|
||||
Name,
|
||||
string.IsNullOrEmpty(ParentName) ? "-" : ParentName,
|
||||
Shape,
|
||||
X,
|
||||
Y,
|
||||
BitNr,
|
||||
Inverted ? "yes" : "no",
|
||||
OpenCloseTime,
|
||||
Category,
|
||||
string.IsNullOrEmpty(CoupledToName) ? "-" : CoupledToName,
|
||||
InvertCouple ? "yes" : "no",
|
||||
LagOpening,
|
||||
LagClosing);
|
||||
}
|
||||
}
|
||||
}
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.BuiltIn.Valve
|
||||
{
|
||||
partial class ValveCfgCtrl
|
||||
{
|
||||
/// <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.bitPositionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.bitPositionLabel = 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.coupledToLabel = new System.Windows.Forms.Label();
|
||||
this.invertCoupleCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.lagOpeningLabel = new System.Windows.Forms.Label();
|
||||
this.lagClosingLabel = new System.Windows.Forms.Label();
|
||||
this.lagOpeningTextBox = new System.Windows.Forms.TextBox();
|
||||
this.lagClosingTextBox = new System.Windows.Forms.TextBox();
|
||||
this.coupledToComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.categoryLabel = new System.Windows.Forms.Label();
|
||||
this.categoryComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.openCloseTimeTextBox = new System.Windows.Forms.TextBox();
|
||||
this.openCloseTimeLabel = new System.Windows.Forms.Label();
|
||||
this.invertedCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// bitPositionTextBox
|
||||
//
|
||||
this.bitPositionTextBox.Enabled = false;
|
||||
this.bitPositionTextBox.Location = new System.Drawing.Point(158, 99);
|
||||
this.bitPositionTextBox.Name = "bitPositionTextBox";
|
||||
this.bitPositionTextBox.Size = new System.Drawing.Size(81, 20);
|
||||
this.bitPositionTextBox.TabIndex = 8;
|
||||
//
|
||||
// bitPositionLabel
|
||||
//
|
||||
this.bitPositionLabel.AutoSize = true;
|
||||
this.bitPositionLabel.Location = new System.Drawing.Point(42, 102);
|
||||
this.bitPositionLabel.Name = "bitPositionLabel";
|
||||
this.bitPositionLabel.Size = new System.Drawing.Size(58, 13);
|
||||
this.bitPositionLabel.TabIndex = 7;
|
||||
this.bitPositionLabel.Text = "Bit position";
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(42, 54);
|
||||
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(158, 28);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(132, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(42, 31);
|
||||
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(156, 8);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// coupledToLabel
|
||||
//
|
||||
this.coupledToLabel.AutoSize = true;
|
||||
this.coupledToLabel.Location = new System.Drawing.Point(42, 125);
|
||||
this.coupledToLabel.Name = "coupledToLabel";
|
||||
this.coupledToLabel.Size = new System.Drawing.Size(52, 13);
|
||||
this.coupledToLabel.TabIndex = 10;
|
||||
this.coupledToLabel.Text = "Copled to";
|
||||
//
|
||||
// invertCoupleCheckBox
|
||||
//
|
||||
this.invertCoupleCheckBox.AutoSize = true;
|
||||
this.invertCoupleCheckBox.Enabled = false;
|
||||
this.invertCoupleCheckBox.Location = new System.Drawing.Point(248, 124);
|
||||
this.invertCoupleCheckBox.Name = "invertCoupleCheckBox";
|
||||
this.invertCoupleCheckBox.Size = new System.Drawing.Size(53, 17);
|
||||
this.invertCoupleCheckBox.TabIndex = 12;
|
||||
this.invertCoupleCheckBox.Text = "Invert";
|
||||
this.invertCoupleCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// parentNameComboBox
|
||||
//
|
||||
this.parentNameComboBox.Enabled = false;
|
||||
this.parentNameComboBox.FormattingEnabled = true;
|
||||
this.parentNameComboBox.Location = new System.Drawing.Point(158, 51);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(132, 21);
|
||||
this.parentNameComboBox.TabIndex = 4;
|
||||
//
|
||||
// lagOpeningLabel
|
||||
//
|
||||
this.lagOpeningLabel.AutoSize = true;
|
||||
this.lagOpeningLabel.Location = new System.Drawing.Point(16, 47);
|
||||
this.lagOpeningLabel.Name = "lagOpeningLabel";
|
||||
this.lagOpeningLabel.Size = new System.Drawing.Size(162, 13);
|
||||
this.lagOpeningLabel.TabIndex = 15;
|
||||
this.lagOpeningLabel.Text = "Lag when opening coupled v. [s]";
|
||||
//
|
||||
// lagClosingLabel
|
||||
//
|
||||
this.lagClosingLabel.AutoSize = true;
|
||||
this.lagClosingLabel.Location = new System.Drawing.Point(16, 70);
|
||||
this.lagClosingLabel.Name = "lagClosingLabel";
|
||||
this.lagClosingLabel.Size = new System.Drawing.Size(157, 13);
|
||||
this.lagClosingLabel.TabIndex = 17;
|
||||
this.lagClosingLabel.Text = "Lag when closing coupled v. [s]";
|
||||
//
|
||||
// lagOpeningTextBox
|
||||
//
|
||||
this.lagOpeningTextBox.Enabled = false;
|
||||
this.lagOpeningTextBox.Location = new System.Drawing.Point(184, 44);
|
||||
this.lagOpeningTextBox.Name = "lagOpeningTextBox";
|
||||
this.lagOpeningTextBox.Size = new System.Drawing.Size(81, 20);
|
||||
this.lagOpeningTextBox.TabIndex = 16;
|
||||
//
|
||||
// lagClosingTextBox
|
||||
//
|
||||
this.lagClosingTextBox.Enabled = false;
|
||||
this.lagClosingTextBox.Location = new System.Drawing.Point(184, 67);
|
||||
this.lagClosingTextBox.Name = "lagClosingTextBox";
|
||||
this.lagClosingTextBox.Size = new System.Drawing.Size(81, 20);
|
||||
this.lagClosingTextBox.TabIndex = 18;
|
||||
//
|
||||
// coupledToComboBox
|
||||
//
|
||||
this.coupledToComboBox.Enabled = false;
|
||||
this.coupledToComboBox.FormattingEnabled = true;
|
||||
this.coupledToComboBox.Location = new System.Drawing.Point(158, 122);
|
||||
this.coupledToComboBox.Name = "coupledToComboBox";
|
||||
this.coupledToComboBox.Size = new System.Drawing.Size(81, 21);
|
||||
this.coupledToComboBox.TabIndex = 11;
|
||||
//
|
||||
// categoryLabel
|
||||
//
|
||||
this.categoryLabel.AutoSize = true;
|
||||
this.categoryLabel.Location = new System.Drawing.Point(42, 78);
|
||||
this.categoryLabel.Name = "categoryLabel";
|
||||
this.categoryLabel.Size = new System.Drawing.Size(49, 13);
|
||||
this.categoryLabel.TabIndex = 5;
|
||||
this.categoryLabel.Text = "Category";
|
||||
//
|
||||
// categoryComboBox
|
||||
//
|
||||
this.categoryComboBox.Enabled = false;
|
||||
this.categoryComboBox.FormattingEnabled = true;
|
||||
this.categoryComboBox.Location = new System.Drawing.Point(158, 75);
|
||||
this.categoryComboBox.Name = "categoryComboBox";
|
||||
this.categoryComboBox.Size = new System.Drawing.Size(132, 21);
|
||||
this.categoryComboBox.TabIndex = 6;
|
||||
//
|
||||
// openCloseTimeTextBox
|
||||
//
|
||||
this.openCloseTimeTextBox.Enabled = false;
|
||||
this.openCloseTimeTextBox.Location = new System.Drawing.Point(184, 21);
|
||||
this.openCloseTimeTextBox.Name = "openCloseTimeTextBox";
|
||||
this.openCloseTimeTextBox.Size = new System.Drawing.Size(81, 20);
|
||||
this.openCloseTimeTextBox.TabIndex = 14;
|
||||
//
|
||||
// openCloseTimeLabel
|
||||
//
|
||||
this.openCloseTimeLabel.AutoSize = true;
|
||||
this.openCloseTimeLabel.Location = new System.Drawing.Point(16, 24);
|
||||
this.openCloseTimeLabel.Name = "openCloseTimeLabel";
|
||||
this.openCloseTimeLabel.Size = new System.Drawing.Size(99, 13);
|
||||
this.openCloseTimeLabel.TabIndex = 13;
|
||||
this.openCloseTimeLabel.Text = "Open/close time [s]";
|
||||
//
|
||||
// invertedCheckBox
|
||||
//
|
||||
this.invertedCheckBox.AutoSize = true;
|
||||
this.invertedCheckBox.Enabled = false;
|
||||
this.invertedCheckBox.Location = new System.Drawing.Point(248, 101);
|
||||
this.invertedCheckBox.Name = "invertedCheckBox";
|
||||
this.invertedCheckBox.Size = new System.Drawing.Size(65, 17);
|
||||
this.invertedCheckBox.TabIndex = 9;
|
||||
this.invertedCheckBox.Text = "Inverted";
|
||||
this.invertedCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.openCloseTimeLabel);
|
||||
this.groupBox1.Controls.Add(this.lagOpeningLabel);
|
||||
this.groupBox1.Controls.Add(this.openCloseTimeTextBox);
|
||||
this.groupBox1.Controls.Add(this.lagClosingLabel);
|
||||
this.groupBox1.Controls.Add(this.lagOpeningTextBox);
|
||||
this.groupBox1.Controls.Add(this.lagClosingTextBox);
|
||||
this.groupBox1.Location = new System.Drawing.Point(25, 161);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(301, 97);
|
||||
this.groupBox1.TabIndex = 19;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Parameters applied immediately (no restart required)";
|
||||
//
|
||||
// ValveCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.invertedCheckBox);
|
||||
this.Controls.Add(this.categoryComboBox);
|
||||
this.Controls.Add(this.categoryLabel);
|
||||
this.Controls.Add(this.coupledToComboBox);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.invertCoupleCheckBox);
|
||||
this.Controls.Add(this.coupledToLabel);
|
||||
this.Controls.Add(this.bitPositionTextBox);
|
||||
this.Controls.Add(this.bitPositionLabel);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "ValveCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(388, 291);
|
||||
this.Load += new System.EventHandler(this.ValveCfgCtrl_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox bitPositionTextBox;
|
||||
private System.Windows.Forms.Label bitPositionLabel;
|
||||
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.Label coupledToLabel;
|
||||
private System.Windows.Forms.CheckBox invertCoupleCheckBox;
|
||||
private System.Windows.Forms.ComboBox parentNameComboBox;
|
||||
private System.Windows.Forms.Label lagOpeningLabel;
|
||||
private System.Windows.Forms.Label lagClosingLabel;
|
||||
private System.Windows.Forms.TextBox lagOpeningTextBox;
|
||||
private System.Windows.Forms.TextBox lagClosingTextBox;
|
||||
private System.Windows.Forms.ComboBox coupledToComboBox;
|
||||
private System.Windows.Forms.Label categoryLabel;
|
||||
private System.Windows.Forms.ComboBox categoryComboBox;
|
||||
private System.Windows.Forms.TextBox openCloseTimeTextBox;
|
||||
private System.Windows.Forms.Label openCloseTimeLabel;
|
||||
private System.Windows.Forms.CheckBox invertedCheckBox;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Valve
|
||||
{
|
||||
public partial class ValveCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
ValveCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as ValveCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public ValveCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ValveCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
categoryComboBox.Items.Add(ValveCategory.Feeding.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.Bench.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.Output.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.None.ToString());
|
||||
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
parentNameComboBox.Items.Add("---");
|
||||
coupledToComboBox.Items.Add("---");
|
||||
foreach (var cmpnt in parent.CmpntEntities)
|
||||
{
|
||||
if (cmpnt.ClassName.Contains("ControlBoard"))
|
||||
{
|
||||
parentNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is BuiltIn.Valve.ValveFactory)
|
||||
{
|
||||
coupledToComboBox.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;
|
||||
bitPositionTextBox.Text = config.BitNr.ToString();
|
||||
invertedCheckBox.Checked = config.Inverted;
|
||||
openCloseTimeTextBox.Text = config.OpenCloseTime.ToString();
|
||||
categoryComboBox.Text = config.Category.ToString();
|
||||
coupledToComboBox.Text = string.IsNullOrEmpty(config.CoupledToName) ? "---" : config.CoupledToName;
|
||||
invertCoupleCheckBox.Checked = config.InvertCouple;
|
||||
lagOpeningTextBox.Text = config.LagOpening.ToString();
|
||||
lagClosingTextBox.Text = config.LagClosing.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
bitPositionTextBox.Enabled = true;
|
||||
invertedCheckBox.Enabled = true;
|
||||
openCloseTimeTextBox.Enabled = true;
|
||||
categoryComboBox.Enabled = true;
|
||||
coupledToComboBox.Enabled = true;
|
||||
invertCoupleCheckBox.Enabled = true;
|
||||
lagOpeningTextBox.Enabled = true;
|
||||
lagClosingTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
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 newBitPosition = int.Parse(bitPositionTextBox.Text);
|
||||
string newCoupledToName = coupledToComboBox.Text.Equals("---") ? string.Empty : coupledToComboBox.Text;
|
||||
|
||||
int newLagOpening = int.Parse(lagOpeningTextBox.Text);
|
||||
int newLagClosing = int.Parse(lagClosingTextBox.Text);
|
||||
int newOpenCloseTime = int.Parse(openCloseTimeTextBox.Text);
|
||||
|
||||
ValveCategory newCategory;
|
||||
if (categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString())) newCategory = ValveCategory.Feeding;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Bench.ToString())) newCategory = ValveCategory.Bench;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Output.ToString())) newCategory = ValveCategory.Output;
|
||||
else newCategory = ValveCategory.None;
|
||||
|
||||
if (config.Name != nameTextBox.Text ||
|
||||
config.ParentName != newParentName ||
|
||||
config.BitNr != newBitPosition ||
|
||||
config.Category != newCategory ||
|
||||
config.Inverted != invertedCheckBox.Checked ||
|
||||
config.CoupledToName != newCoupledToName ||
|
||||
config.InvertCouple != invertCoupleCheckBox.Checked)
|
||||
{
|
||||
config.Name = nameTextBox.Text;
|
||||
config.ParentName = newParentName;
|
||||
config.BitNr = newBitPosition;
|
||||
config.Category = newCategory;
|
||||
config.Inverted = invertedCheckBox.Checked;
|
||||
config.CoupledToName = newCoupledToName;
|
||||
config.InvertCouple = invertCoupleCheckBox.Checked;
|
||||
|
||||
flags |= (CfgUpdateFlags.RestartRqrd | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
if (config.OpenCloseTime != newOpenCloseTime ||
|
||||
config.LagOpening != newLagOpening ||
|
||||
config.LagClosing != newLagClosing)
|
||||
{
|
||||
config.OpenCloseTime = newOpenCloseTime;
|
||||
config.LagOpening = newLagOpening;
|
||||
config.LagClosing = newLagClosing;
|
||||
|
||||
flags |= (CfgUpdateFlags.InvokeCfgChange | CfgUpdateFlags.AnyChange);
|
||||
}
|
||||
|
||||
if ((flags & CfgUpdateFlags.InvokeCfgChange) != 0)
|
||||
{
|
||||
Valve.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Parent Name'";
|
||||
}
|
||||
if (!categoryComboBox.Items.Contains(categoryComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Category'";
|
||||
}
|
||||
if (!coupledToComboBox.Items.Contains(coupledToComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Coupled To'";
|
||||
}
|
||||
if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 128)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Bit Position' should be between 0 and 127";
|
||||
}
|
||||
if (!int.TryParse(openCloseTimeTextBox.Text, out dummy) || dummy < 0 || dummy > 300 || (dummy % StateMachine.Period) != 0)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Open/close time' should be between 0 and 300 s";
|
||||
if (dummy % StateMachine.Period != 0)
|
||||
message += Environment.NewLine + string.Format("and a multiple of {0}", StateMachine.Period);
|
||||
}
|
||||
if (!int.TryParse(lagOpeningTextBox.Text, out dummy) || (dummy % StateMachine.Period) != 0)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format("'Delay when opening' error should be a multiple of {0}", StateMachine.Period);
|
||||
}
|
||||
if (!int.TryParse(lagClosingTextBox.Text, out dummy) || (dummy % StateMachine.Period) != 0)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format("'Delay when closing' error should be a multiple of {0}", StateMachine.Period);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.Valve
|
||||
{
|
||||
public class ValveFactory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "Valve"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Valve.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Valve(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Valve(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ValveCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ValveCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.BuiltIn
|
||||
{
|
||||
public class ValveBase : ComponentBase
|
||||
{
|
||||
public ValveBase()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes ComponentBase constructor
|
||||
/// </summary>
|
||||
public ValveBase(Generic.IComponentCfg cfg) : base(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the list of components and return all valves (masters and coupled)
|
||||
/// </summary>
|
||||
public static IList<IValve> AllValves(IList<Generic.IComponent> cmpnts)
|
||||
{
|
||||
IList<IValve> result = new List<IValve>();
|
||||
foreach (var cmpnt in cmpnts) if (cmpnt is IValve) result.Add(cmpnt as IValve);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the list of components and return masters valves
|
||||
/// </summary>
|
||||
public static IList<IValve> GetMasterValves(IList<Generic.IComponent> cmpnts)
|
||||
{
|
||||
IList<IValve> result = new List<IValve>();
|
||||
foreach (var cmpnt in cmpnts)
|
||||
{
|
||||
IValve valve = cmpnt as IValve;
|
||||
if (valve != null && valve.CoupledTo == null) result.Add(valve);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the list of components and return coupled valves
|
||||
/// </summary>
|
||||
public static IList<IValve> CoupledValves(IList<Generic.IComponent> cmpnts)
|
||||
{
|
||||
IList<IValve> result = new List<IValve>();
|
||||
foreach (var cmpnt in cmpnts)
|
||||
{
|
||||
IValve valve = cmpnt as IValve;
|
||||
if (valve != null && valve.CoupledTo != null) result.Add(valve);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the list of components and return extended valves
|
||||
/// </summary>
|
||||
public static IList<BuiltIn.ValveEx.Valve> ExtendedValves(IList<Generic.IComponent> cmpnts)
|
||||
{
|
||||
IList<BuiltIn.ValveEx.Valve> result = new List<BuiltIn.ValveEx.Valve>();
|
||||
foreach (var cmpnt in cmpnts)
|
||||
{
|
||||
if (cmpnt is BuiltIn.ValveEx.Valve) result.Add(cmpnt as BuiltIn.ValveEx.Valve);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a list with one valved passed as an argument to this function
|
||||
/// </summary>
|
||||
/// <param name="valve">Valve</param>
|
||||
/// <returns>List with one valve</returns>
|
||||
public static IList<IValve> MakeList(IValve valve)
|
||||
{
|
||||
IList<IValve> result = new List<IValve>();
|
||||
if (valve != null) result.Add(valve);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IList<IValve> Merge(IList<IValve> valves1, IList<IValve> valves2)
|
||||
{
|
||||
IList<IValve> result = new List<IValve>();
|
||||
if (valves1 != null) foreach (var valve in valves1) result.Add(valve);
|
||||
if (valves2 != null) foreach (var valve in valves2) result.Add(valve);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IList<IValve> Merge(IList<IValve> valves1, IList<IValve> valves2, IList<IValve> valves3)
|
||||
{
|
||||
IList<IValve> result = new List<IValve>();
|
||||
if (valves1 != null) foreach (var valve in valves1) result.Add(valve);
|
||||
if (valves2 != null) foreach (var valve in valves2) result.Add(valve);
|
||||
if (valves3 != null) foreach (var valve in valves3) result.Add(valve);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
///
|
||||
/// Copyright (c) 2015-2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using Dirichlet.Numerics;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.ValveEx
|
||||
{
|
||||
public class Valve : ComponentBase, Generic.IComponent
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Valve));
|
||||
public override string ToString() { return string.Format("ValveEx({0})", Cfg.ToString(1)); }
|
||||
|
||||
readonly ValveCfg valveCfg;
|
||||
|
||||
public readonly UInt128 Mask; /// derived from bitPosition in the constructor
|
||||
///
|
||||
public readonly IValve[] InputValves;
|
||||
|
||||
public Valve()
|
||||
{
|
||||
}
|
||||
|
||||
public Valve(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
valveCfg = cfg as ValveCfg;
|
||||
|
||||
//controlBoard = (ControlBoardDev)TbfComponents.FindComponent(cfg.ParentName, components);
|
||||
//if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent");
|
||||
|
||||
if (valveCfg.BitPosition < 0 || valveCfg.BitPosition >= 128)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("position");
|
||||
}
|
||||
this.Mask = (((UInt128)1) << valveCfg.BitPosition);
|
||||
|
||||
InputValves = new IValve[valveCfg.InputValvesCount];
|
||||
InputValves[0] = TbfComponents.FindComponent(valveCfg.Input1, components) as IValve;
|
||||
InputValves[1] = TbfComponents.FindComponent(valveCfg.Input2, components) as IValve;
|
||||
if (InputValves.Length > 2)
|
||||
{
|
||||
InputValves[2] = TbfComponents.FindComponent(valveCfg.Input3, components) as IValve;
|
||||
}
|
||||
if (InputValves.Length > 3)
|
||||
{
|
||||
InputValves[3] = TbfComponents.FindComponent(valveCfg.Input4, components) as IValve;
|
||||
}
|
||||
if (InputValves.Length > 4)
|
||||
{
|
||||
InputValves[4] = TbfComponents.FindComponent(valveCfg.Input5, components) as IValve;
|
||||
}
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public void UpdateRoute(ref UInt128 route)
|
||||
{
|
||||
bool output;
|
||||
|
||||
if (valveCfg.LogicalOp == ValveExOperation.And)
|
||||
{
|
||||
output = true;
|
||||
foreach (var valve in InputValves)
|
||||
{
|
||||
if (valve != null) output = output && valve.State;
|
||||
}
|
||||
}
|
||||
else if (valveCfg.LogicalOp == ValveExOperation.Or)
|
||||
{
|
||||
output = false;
|
||||
foreach (var valve in InputValves)
|
||||
{
|
||||
if (valve != null) output = output || valve.State;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
if (output != valveCfg.InvertOutput)
|
||||
{
|
||||
route = route | Mask; /// Set the output bit to true
|
||||
}
|
||||
else
|
||||
{
|
||||
route = route & (~Mask); /// Reset the output bit to false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
///
|
||||
/// Copyright (c) 2015-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.ValveEx
|
||||
{
|
||||
public class ValveCfg : ComponentCfgBase, IComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ValveCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new ValveCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int BitPosition; /// Bit-position
|
||||
///
|
||||
public ValveExOperation LogicalOp; /// Logical operation between input valves
|
||||
public bool InvertOutput; /// Invert the output of logical operation
|
||||
public int InputValvesCount;
|
||||
public string Input1; /// Input valve 1
|
||||
public string Input2; /// Input valve 2
|
||||
public string Input3; /// Input valve 3
|
||||
public string Input4; /// Input valve 4
|
||||
public string Input5; /// Input valve 5
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ValveCfg()
|
||||
{
|
||||
Name = "VEx";
|
||||
ParentName = string.Empty;
|
||||
BitPosition = 0;
|
||||
LogicalOp = ValveExOperation.And;
|
||||
InvertOutput = false;
|
||||
InputValvesCount = 2;
|
||||
Input1 = string.Empty;
|
||||
Input2 = string.Empty;
|
||||
Input3 = string.Empty;
|
||||
Input4 = string.Empty;
|
||||
Input5 = string.Empty;
|
||||
}
|
||||
|
||||
public ValveCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
this.Factory = factory;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, Bit={1}, LogOp.={2}, Inv.Output={3}, #inputs={4}, I1={5}, I2={6}, I3={7}, I4={8}s, I5={9}",
|
||||
Name,
|
||||
BitPosition,
|
||||
(LogicalOp == ValveExOperation.And) ? "AND" : "OR",
|
||||
InvertOutput ? "yes" : "no",
|
||||
InputValvesCount,
|
||||
Input1,
|
||||
Input2,
|
||||
Input3,
|
||||
Input4,
|
||||
Input5);
|
||||
}
|
||||
}
|
||||
}
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
///
|
||||
/// Copyright (c) 2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.BuiltIn.ValveEx
|
||||
{
|
||||
partial class ValveCfgCtrl
|
||||
{
|
||||
/// <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.bitPositionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.bitPositionLabel = 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.inputsCountLabel = new System.Windows.Forms.Label();
|
||||
this.inputsCountTextBox = new System.Windows.Forms.TextBox();
|
||||
this.logicalOpLabel = new System.Windows.Forms.Label();
|
||||
this.logicalOpComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.invertedOutpCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.input1ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.input1Label = new System.Windows.Forms.Label();
|
||||
this.input2ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.input2Label = new System.Windows.Forms.Label();
|
||||
this.input3ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.input3Label = new System.Windows.Forms.Label();
|
||||
this.input4ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.input4Label = new System.Windows.Forms.Label();
|
||||
this.input5ComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.input5Label = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// bitPositionTextBox
|
||||
//
|
||||
this.bitPositionTextBox.Enabled = false;
|
||||
this.bitPositionTextBox.Location = new System.Drawing.Point(117, 58);
|
||||
this.bitPositionTextBox.Name = "bitPositionTextBox";
|
||||
this.bitPositionTextBox.Size = new System.Drawing.Size(66, 20);
|
||||
this.bitPositionTextBox.TabIndex = 4;
|
||||
//
|
||||
// bitPositionLabel
|
||||
//
|
||||
this.bitPositionLabel.AutoSize = true;
|
||||
this.bitPositionLabel.Location = new System.Drawing.Point(17, 61);
|
||||
this.bitPositionLabel.Name = "bitPositionLabel";
|
||||
this.bitPositionLabel.Size = new System.Drawing.Size(58, 13);
|
||||
this.bitPositionLabel.TabIndex = 3;
|
||||
this.bitPositionLabel.Text = "Bit position";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(117, 35);
|
||||
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(17, 38);
|
||||
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(115, 15);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// inputsCountLabel
|
||||
//
|
||||
this.inputsCountLabel.AutoSize = true;
|
||||
this.inputsCountLabel.Location = new System.Drawing.Point(17, 108);
|
||||
this.inputsCountLabel.Name = "inputsCountLabel";
|
||||
this.inputsCountLabel.Size = new System.Drawing.Size(66, 13);
|
||||
this.inputsCountLabel.TabIndex = 8;
|
||||
this.inputsCountLabel.Text = "Inputs count";
|
||||
//
|
||||
// inputsCountTextBox
|
||||
//
|
||||
this.inputsCountTextBox.Enabled = false;
|
||||
this.inputsCountTextBox.Location = new System.Drawing.Point(117, 105);
|
||||
this.inputsCountTextBox.Name = "inputsCountTextBox";
|
||||
this.inputsCountTextBox.Size = new System.Drawing.Size(66, 20);
|
||||
this.inputsCountTextBox.TabIndex = 9;
|
||||
this.inputsCountTextBox.TextChanged += new System.EventHandler(this.inputsCountTextBox_TextChanged);
|
||||
//
|
||||
// logicalOpLabel
|
||||
//
|
||||
this.logicalOpLabel.AutoSize = true;
|
||||
this.logicalOpLabel.Location = new System.Drawing.Point(17, 84);
|
||||
this.logicalOpLabel.Name = "logicalOpLabel";
|
||||
this.logicalOpLabel.Size = new System.Drawing.Size(88, 13);
|
||||
this.logicalOpLabel.TabIndex = 6;
|
||||
this.logicalOpLabel.Text = "Logical operation";
|
||||
//
|
||||
// logicalOpComboBox
|
||||
//
|
||||
this.logicalOpComboBox.Enabled = false;
|
||||
this.logicalOpComboBox.FormattingEnabled = true;
|
||||
this.logicalOpComboBox.Location = new System.Drawing.Point(117, 81);
|
||||
this.logicalOpComboBox.Name = "logicalOpComboBox";
|
||||
this.logicalOpComboBox.Size = new System.Drawing.Size(66, 21);
|
||||
this.logicalOpComboBox.TabIndex = 7;
|
||||
//
|
||||
// invertedOutpCheckBox
|
||||
//
|
||||
this.invertedOutpCheckBox.AutoSize = true;
|
||||
this.invertedOutpCheckBox.Enabled = false;
|
||||
this.invertedOutpCheckBox.Location = new System.Drawing.Point(196, 61);
|
||||
this.invertedOutpCheckBox.Name = "invertedOutpCheckBox";
|
||||
this.invertedOutpCheckBox.Size = new System.Drawing.Size(98, 17);
|
||||
this.invertedOutpCheckBox.TabIndex = 5;
|
||||
this.invertedOutpCheckBox.Text = "Inverted output";
|
||||
this.invertedOutpCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// input1ComboBox
|
||||
//
|
||||
this.input1ComboBox.Enabled = false;
|
||||
this.input1ComboBox.FormattingEnabled = true;
|
||||
this.input1ComboBox.Location = new System.Drawing.Point(117, 127);
|
||||
this.input1ComboBox.Name = "input1ComboBox";
|
||||
this.input1ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.input1ComboBox.TabIndex = 11;
|
||||
//
|
||||
// input1Label
|
||||
//
|
||||
this.input1Label.AutoSize = true;
|
||||
this.input1Label.Location = new System.Drawing.Point(18, 130);
|
||||
this.input1Label.Name = "input1Label";
|
||||
this.input1Label.Size = new System.Drawing.Size(40, 13);
|
||||
this.input1Label.TabIndex = 10;
|
||||
this.input1Label.Text = "Input 1";
|
||||
//
|
||||
// input2ComboBox
|
||||
//
|
||||
this.input2ComboBox.Enabled = false;
|
||||
this.input2ComboBox.FormattingEnabled = true;
|
||||
this.input2ComboBox.Location = new System.Drawing.Point(117, 150);
|
||||
this.input2ComboBox.Name = "input2ComboBox";
|
||||
this.input2ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.input2ComboBox.TabIndex = 13;
|
||||
//
|
||||
// input2Label
|
||||
//
|
||||
this.input2Label.AutoSize = true;
|
||||
this.input2Label.Location = new System.Drawing.Point(17, 153);
|
||||
this.input2Label.Name = "input2Label";
|
||||
this.input2Label.Size = new System.Drawing.Size(40, 13);
|
||||
this.input2Label.TabIndex = 12;
|
||||
this.input2Label.Text = "Input 2";
|
||||
//
|
||||
// input3ComboBox
|
||||
//
|
||||
this.input3ComboBox.Enabled = false;
|
||||
this.input3ComboBox.FormattingEnabled = true;
|
||||
this.input3ComboBox.Location = new System.Drawing.Point(117, 173);
|
||||
this.input3ComboBox.Name = "input3ComboBox";
|
||||
this.input3ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.input3ComboBox.TabIndex = 15;
|
||||
//
|
||||
// input3Label
|
||||
//
|
||||
this.input3Label.AutoSize = true;
|
||||
this.input3Label.Location = new System.Drawing.Point(18, 176);
|
||||
this.input3Label.Name = "input3Label";
|
||||
this.input3Label.Size = new System.Drawing.Size(40, 13);
|
||||
this.input3Label.TabIndex = 14;
|
||||
this.input3Label.Text = "Input 3";
|
||||
//
|
||||
// input4ComboBox
|
||||
//
|
||||
this.input4ComboBox.Enabled = false;
|
||||
this.input4ComboBox.FormattingEnabled = true;
|
||||
this.input4ComboBox.Location = new System.Drawing.Point(117, 196);
|
||||
this.input4ComboBox.Name = "input4ComboBox";
|
||||
this.input4ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.input4ComboBox.TabIndex = 17;
|
||||
//
|
||||
// input4Label
|
||||
//
|
||||
this.input4Label.AutoSize = true;
|
||||
this.input4Label.Location = new System.Drawing.Point(18, 199);
|
||||
this.input4Label.Name = "input4Label";
|
||||
this.input4Label.Size = new System.Drawing.Size(40, 13);
|
||||
this.input4Label.TabIndex = 16;
|
||||
this.input4Label.Text = "Input 4";
|
||||
//
|
||||
// input5ComboBox
|
||||
//
|
||||
this.input5ComboBox.Enabled = false;
|
||||
this.input5ComboBox.FormattingEnabled = true;
|
||||
this.input5ComboBox.Location = new System.Drawing.Point(117, 219);
|
||||
this.input5ComboBox.Name = "input5ComboBox";
|
||||
this.input5ComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.input5ComboBox.TabIndex = 19;
|
||||
//
|
||||
// input5Label
|
||||
//
|
||||
this.input5Label.AutoSize = true;
|
||||
this.input5Label.Location = new System.Drawing.Point(18, 222);
|
||||
this.input5Label.Name = "input5Label";
|
||||
this.input5Label.Size = new System.Drawing.Size(40, 13);
|
||||
this.input5Label.TabIndex = 18;
|
||||
this.input5Label.Text = "Input 5";
|
||||
//
|
||||
// ValveCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.input5ComboBox);
|
||||
this.Controls.Add(this.input5Label);
|
||||
this.Controls.Add(this.input4ComboBox);
|
||||
this.Controls.Add(this.input4Label);
|
||||
this.Controls.Add(this.input3ComboBox);
|
||||
this.Controls.Add(this.input3Label);
|
||||
this.Controls.Add(this.input2ComboBox);
|
||||
this.Controls.Add(this.input2Label);
|
||||
this.Controls.Add(this.input1ComboBox);
|
||||
this.Controls.Add(this.input1Label);
|
||||
this.Controls.Add(this.invertedOutpCheckBox);
|
||||
this.Controls.Add(this.logicalOpComboBox);
|
||||
this.Controls.Add(this.logicalOpLabel);
|
||||
this.Controls.Add(this.inputsCountTextBox);
|
||||
this.Controls.Add(this.inputsCountLabel);
|
||||
this.Controls.Add(this.bitPositionTextBox);
|
||||
this.Controls.Add(this.bitPositionLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "ValveCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 250);
|
||||
this.Load += new System.EventHandler(this.ValveCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox bitPositionTextBox;
|
||||
private System.Windows.Forms.Label bitPositionLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.Label inputsCountLabel;
|
||||
private System.Windows.Forms.TextBox inputsCountTextBox;
|
||||
private System.Windows.Forms.Label logicalOpLabel;
|
||||
private System.Windows.Forms.ComboBox logicalOpComboBox;
|
||||
private System.Windows.Forms.CheckBox invertedOutpCheckBox;
|
||||
private System.Windows.Forms.ComboBox input1ComboBox;
|
||||
private System.Windows.Forms.Label input1Label;
|
||||
private System.Windows.Forms.ComboBox input2ComboBox;
|
||||
private System.Windows.Forms.Label input2Label;
|
||||
private System.Windows.Forms.ComboBox input3ComboBox;
|
||||
private System.Windows.Forms.Label input3Label;
|
||||
private System.Windows.Forms.ComboBox input4ComboBox;
|
||||
private System.Windows.Forms.Label input4Label;
|
||||
private System.Windows.Forms.ComboBox input5ComboBox;
|
||||
private System.Windows.Forms.Label input5Label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
///
|
||||
/// Copyright (c) 2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.ValveEx
|
||||
{
|
||||
public partial class ValveCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
ValveCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as ValveCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public ValveCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ValveCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
logicalOpComboBox.Items.Add("AND");
|
||||
logicalOpComboBox.Items.Add("OR");
|
||||
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
AddValvePumpItemsToCombo(input1ComboBox, parent.CmpntEntities);
|
||||
AddValvePumpItemsToCombo(input2ComboBox, parent.CmpntEntities);
|
||||
AddValvePumpItemsToCombo(input3ComboBox, parent.CmpntEntities);
|
||||
AddValvePumpItemsToCombo(input4ComboBox, parent.CmpntEntities);
|
||||
AddValvePumpItemsToCombo(input5ComboBox, parent.CmpntEntities);
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void AddValvePumpItemsToCombo(ComboBox combo, IList<Config.Entities.Component> components)
|
||||
{
|
||||
foreach (var cmpntEntity in components)
|
||||
{
|
||||
IComponent comp = TbfComponents.CmpntFactoryFromClassName(cmpntEntity.ClassName).DummyComponent();
|
||||
if (comp is GenericDevices.IValve )
|
||||
{
|
||||
combo.Items.Add(cmpntEntity.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
bitPositionTextBox.Text = config.BitPosition.ToString();
|
||||
invertedOutpCheckBox.Checked = config.InvertOutput;
|
||||
logicalOpComboBox.Text = (config.LogicalOp == ValveExOperation.And) ? "AND" : ((config.LogicalOp == ValveExOperation.Or) ? "OR" : "---");
|
||||
inputsCountTextBox.Text = config.InputValvesCount.ToString();
|
||||
input1ComboBox.Text = config.Input1;
|
||||
input2ComboBox.Text = config.Input2;
|
||||
input3ComboBox.Text = config.Input3;
|
||||
input4ComboBox.Text = config.Input4;
|
||||
input5ComboBox.Text = config.Input5;
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
bitPositionTextBox.Enabled = true;
|
||||
invertedOutpCheckBox.Enabled = true;
|
||||
logicalOpComboBox.Enabled = true;
|
||||
inputsCountTextBox.Enabled = true;
|
||||
input1ComboBox.Enabled = true;
|
||||
input2ComboBox.Enabled = true;
|
||||
input3ComboBox.Enabled = true;
|
||||
input4ComboBox.Enabled = true;
|
||||
input5ComboBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
config.Name = nameTextBox.Text;
|
||||
config.BitPosition = int.Parse(bitPositionTextBox.Text);
|
||||
config.InvertOutput = invertedOutpCheckBox.Checked;
|
||||
config.LogicalOp = (logicalOpComboBox.Text == "AND") ? ValveExOperation.And : ValveExOperation.Or;
|
||||
config.InputValvesCount = int.Parse(inputsCountTextBox.Text);
|
||||
config.Input1 = input1ComboBox.Text.Equals("---") ? string.Empty : input1ComboBox.Text;
|
||||
config.Input2 = input2ComboBox.Text.Equals("---") ? string.Empty : input2ComboBox.Text;
|
||||
if (config.InputValvesCount >= 3) config.Input3 = input3ComboBox.Text.Equals("---") ? string.Empty : input3ComboBox.Text;
|
||||
if (config.InputValvesCount >= 4) config.Input4 = input4ComboBox.Text.Equals("---") ? string.Empty : input4ComboBox.Text;
|
||||
if (config.InputValvesCount >= 5) config.Input5 = input5ComboBox.Text.Equals("---") ? string.Empty : input5ComboBox.Text;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 128)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Bit Position' should be between 0 and 127";
|
||||
}
|
||||
if (!logicalOpComboBox.Items.Contains(logicalOpComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Category'";
|
||||
}
|
||||
int nrInputs;
|
||||
if (!int.TryParse(inputsCountTextBox.Text, out nrInputs) || nrInputs < 2 || nrInputs > 5)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Inputs count' out of range (2..5)";
|
||||
}
|
||||
if (!input1ComboBox.Items.Contains(input1ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Input 1'";
|
||||
}
|
||||
if (!input2ComboBox.Items.Contains(input2ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Input 2'";
|
||||
}
|
||||
if (nrInputs >= 3 && !input3ComboBox.Items.Contains(input3ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Input 3'";
|
||||
}
|
||||
if (nrInputs >= 4 && !input4ComboBox.Items.Contains(input4ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Input 4'";
|
||||
}
|
||||
if (nrInputs >= 5 && !input5ComboBox.Items.Contains(input5ComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Input 5'";
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
private void inputsCountTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
int count;
|
||||
if (int.TryParse(inputsCountTextBox.Text, out count) && count >= 2 || count <= 5)
|
||||
{
|
||||
input3Label.Visible = (count >= 3);
|
||||
input4Label.Visible = (count >= 4);
|
||||
input5Label.Visible = (count >= 5);
|
||||
input3ComboBox.Visible = (count >= 3);
|
||||
input4ComboBox.Visible = (count >= 4);
|
||||
input5ComboBox.Visible = (count >= 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2015-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.BuiltIn.ValveEx
|
||||
{
|
||||
public class ValveFactory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "ValveEx"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Valve.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Valve(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Valve(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ValveCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ValveCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
|
||||
namespace TBF.Rig
|
||||
{
|
||||
public class CfgChangeArgs : EventArgs
|
||||
{
|
||||
public CfgChangeCmd Command;
|
||||
public Generic.IComponentCfg Cfg;
|
||||
|
||||
public CfgChangeArgs(CfgChangeCmd command, Generic.IComponentCfg cfg)
|
||||
{
|
||||
Command = command;
|
||||
Cfg = cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
|
||||
namespace TBF.Rig
|
||||
{
|
||||
public class CmdResponseArgs : EventArgs
|
||||
{
|
||||
public CfgChangeCmd Command;
|
||||
public int Id; /// Either Idx1(RV) or BitPosition (Div) to identify the component
|
||||
public Int16 Response;
|
||||
|
||||
public CmdResponseArgs(CfgChangeCmd command, int id, Int16 response)
|
||||
{
|
||||
Command = command;
|
||||
Id = id;
|
||||
Response = response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig
|
||||
{
|
||||
public class ComponentBase : IComponent
|
||||
{
|
||||
readonly Generic.IComponentCfg cfg;
|
||||
public Generic.IComponentCfg Cfg { get { return cfg; } }
|
||||
|
||||
public string Name { get { return cfg.Name; } }
|
||||
public string ClassName { get { return cfg.Factory.ClassName; } }
|
||||
public string ParentName { get { return cfg.ParentName; } }
|
||||
public Generic.IComponentFactory Factory { get { return cfg.Factory; } }
|
||||
public int ItemNr { get { return cfg.ItemNr; } }
|
||||
public DebugMode DebugLevel { get { return cfg.DebugLevel; } set { cfg.DebugLevel = value; } }
|
||||
public LogLevel LogLevel { get { return cfg.LogLevel; } }
|
||||
|
||||
public IList<MeasurementCorrection> Corrections
|
||||
{
|
||||
get { return cfg.Corrections; }
|
||||
set { cfg.Corrections = value; }
|
||||
}
|
||||
|
||||
public IList<Uncertainty> Uncertainties
|
||||
{
|
||||
get { return cfg.Uncertainties; }
|
||||
set { cfg.Uncertainties = value; }
|
||||
}
|
||||
|
||||
|
||||
/// Constructor, components created in this way is used by
|
||||
/// IComponentFactory.DummyComponent() function. Such dummy component should be used
|
||||
/// only for runtime class type identification (e.g. object is iValve)
|
||||
public ComponentBase()
|
||||
{
|
||||
cfg = null;
|
||||
}
|
||||
|
||||
/// Constructor with configuration as an argument
|
||||
public ComponentBase(IComponentCfg cfg)
|
||||
{
|
||||
if (cfg == null) throw new ArgumentNullException("cfg");
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
/// <summary> Empty implementation, might be overriden in derived classes </summary>
|
||||
public static void ResetStaticProperties() { }
|
||||
|
||||
/// <summary> Empty implementation, might be overriden in derived classes </summary>
|
||||
public virtual void StartChangeHandler() { }
|
||||
|
||||
/// <summary> Empty implementation, might be overriden in derived classes </summary>
|
||||
public virtual void StopChangeHandler() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig
|
||||
{
|
||||
public class ComponentCfgBase
|
||||
{
|
||||
[XmlIgnore]
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set { name = value; }
|
||||
}
|
||||
string name;
|
||||
|
||||
[XmlIgnore]
|
||||
public Generic.IComponentFactory Factory
|
||||
{
|
||||
get { return factory; }
|
||||
set { factory = value; }
|
||||
}
|
||||
Generic.IComponentFactory factory;
|
||||
|
||||
[XmlIgnore]
|
||||
public string ClassName
|
||||
{
|
||||
get { return Factory.ToString(); }
|
||||
}
|
||||
|
||||
[XmlIgnore]
|
||||
public string ParentName
|
||||
{
|
||||
get { return parentName; }
|
||||
set { parentName = value; }
|
||||
}
|
||||
string parentName;
|
||||
|
||||
[XmlIgnore]
|
||||
public int ItemNr
|
||||
{
|
||||
get { return itemNr; }
|
||||
set { itemNr = value; }
|
||||
}
|
||||
int itemNr;
|
||||
|
||||
[XmlIgnore]
|
||||
public DebugMode DebugLevel
|
||||
{
|
||||
get { return debugLevel; }
|
||||
set { debugLevel = value; }
|
||||
}
|
||||
DebugMode debugLevel;
|
||||
|
||||
[XmlIgnore]
|
||||
public LogLevel LogLevel
|
||||
{
|
||||
get { return logLevel; }
|
||||
set { logLevel = value; }
|
||||
}
|
||||
LogLevel logLevel;
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<MeasurementCorrection> Corrections
|
||||
{
|
||||
get { return corrections; }
|
||||
set { corrections = value; }
|
||||
}
|
||||
IList<MeasurementCorrection> corrections;
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<Uncertainty> Uncertainties
|
||||
{
|
||||
get { return uncertainties; }
|
||||
set { uncertainties = value; }
|
||||
}
|
||||
IList<Uncertainty> uncertainties;
|
||||
|
||||
|
||||
protected ComponentCfgBase()
|
||||
{
|
||||
itemNr = 0;
|
||||
debugLevel = DebugMode.Normal;
|
||||
logLevel = LogLevel.Off;
|
||||
}
|
||||
|
||||
protected ComponentCfgBase(Generic.IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
protected ComponentCfgBase(Generic.IComponentFactory factory, string name)
|
||||
: this(factory)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected ComponentCfgBase(Generic.IComponentFactory factory, string name, string parentName)
|
||||
: this(factory, name)
|
||||
{
|
||||
this.parentName = parentName;
|
||||
}
|
||||
|
||||
|
||||
public virtual XmlSerializer GetSerializer() { return new XmlSerializer(GetType()); }
|
||||
|
||||
public Component CreateDbEntity()
|
||||
{
|
||||
using (var writer = new StringWriter())
|
||||
{
|
||||
GetSerializer().Serialize(writer, this);
|
||||
return Component.CreateFromCfg(Name, factory.ClassName, ParentName, ItemNr, DebugLevel, LogLevel, writer.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static IComponentCfg CreateFromDbEntity(XmlSerializer s, Component cmpntEntity, IComponentFactory factory)
|
||||
{
|
||||
using (var reader = new StringReader(cmpntEntity.Parameters))
|
||||
{
|
||||
IComponentCfg config = s.Deserialize(reader) as IComponentCfg;
|
||||
if (config != null)
|
||||
{
|
||||
config.Name = cmpntEntity.Name;
|
||||
config.ParentName = cmpntEntity.Parent;
|
||||
config.ItemNr = cmpntEntity.ItemNr;
|
||||
config.DebugLevel = cmpntEntity.DebugMode;
|
||||
config.LogLevel = cmpntEntity.LogLevel;
|
||||
config.Corrections = cmpntEntity.Corrections;
|
||||
config.Uncertainties = cmpntEntity.Uncertainties;
|
||||
config.Factory = factory;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void LoadTestParamsFromDB(Test test)
|
||||
{
|
||||
ITestParams tstPrms = (GetRuntimeTestParamsProvider() as ITestParams);
|
||||
if (tstPrms != null)
|
||||
{
|
||||
tstPrms.FromDbEntity(Name, test);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void LoadProcedureParamsFromDB(Procedure procedure)
|
||||
{
|
||||
IProcedureParams procPrms = (GetRuntimeProcParamsProvider() as IProcedureParams);
|
||||
if (procPrms != null)
|
||||
{
|
||||
procPrms.FromDbEntity(Name, procedure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If there are any procedure parameters, this function should be overriden
|
||||
/// by one returning a reference to a newly created object
|
||||
/// implementing IParamsProvider and IProcedureParams.
|
||||
///
|
||||
/// This default implementation returns null = no procedure parameters.
|
||||
/// </summary>
|
||||
/// <returns>Procedure parameters provider for this component or null</returns>
|
||||
public virtual IParamsProvider CreateProcParamsProvider()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If there are any procedure parameters, this function should be overriden
|
||||
/// by one returning a reference to an object
|
||||
/// implementing IParamsProvider and IProcedureParams used in runtime.
|
||||
///
|
||||
/// This default implementation returns null = no procedure parameters.
|
||||
/// </summary>
|
||||
/// <returns>Procedure parameters provider for this component or null</returns>
|
||||
public virtual IParamsProvider GetRuntimeProcParamsProvider()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual IParamsProvider GetUIProcParamsProvider(Procedure procedure)
|
||||
{
|
||||
if (GetRuntimeProcParamsProvider() == null)
|
||||
{
|
||||
/// Component has no test parametes
|
||||
return null;
|
||||
}
|
||||
|
||||
ComponentProcedure procParamsEntity = procedure.GetProcedureParamsEntity(Name);
|
||||
|
||||
if (procParamsEntity != null)
|
||||
{
|
||||
if (procParamsEntity.GetParamsProvider() != null)
|
||||
{
|
||||
/// Parameters provider for this entity already fetched - return it
|
||||
return procParamsEntity.GetParamsProvider();
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Parameters provider for this entity will be created and updated from the entity later on
|
||||
IParamsProvider paramsProvider = CreateProcParamsProvider();
|
||||
(paramsProvider as IProcedureParams).UpdateFromDbEntity(procParamsEntity);
|
||||
procParamsEntity.SetParamsProvider(paramsProvider);
|
||||
return paramsProvider;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IParamsProvider paramsProvider = CreateProcParamsProvider();
|
||||
(paramsProvider as IProcedureParams).FromDbEntity(Name, procedure);
|
||||
return paramsProvider;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If there are any procedure parameters, this function should be overriden
|
||||
/// by one returning a reference to a newly created object
|
||||
/// implementing IParamsProvider and ITestParams.
|
||||
///
|
||||
/// This default implementation returns null = no test parameters.
|
||||
/// </summary>
|
||||
/// <returns>Procedure parameters provider for this component or null</returns>
|
||||
public virtual IParamsProvider CreateTestParamsProvider()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If there are any test parameters, this function should be overriden
|
||||
/// by one returning a reference to an object
|
||||
/// implementing IParamsProvider and ITestParams used in runtime.
|
||||
///
|
||||
/// This default implementation returns null = no test parameters.
|
||||
/// </summary>
|
||||
/// <returns>Test parameters provider for this component or null</returns>
|
||||
public virtual IParamsProvider GetRuntimeTestParamsProvider()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual IParamsProvider GetUITestParamsProvider(Test test)
|
||||
{
|
||||
if (GetRuntimeTestParamsProvider() == null)
|
||||
{
|
||||
/// Component has no test parametes
|
||||
return null;
|
||||
}
|
||||
|
||||
ComponentTest testParamsEntity = test.GetTestParamsEntity(Name);
|
||||
|
||||
if (testParamsEntity != null)
|
||||
{
|
||||
if (testParamsEntity.GetParamsProvider() != null)
|
||||
{
|
||||
/// Parameters provider for this entity already fetched - return it
|
||||
return testParamsEntity.GetParamsProvider();
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Parameters provider for this entity will be created and updated from the entity later on
|
||||
IParamsProvider paramsProvider = CreateTestParamsProvider();
|
||||
(paramsProvider as ITestParams).UpdateFromDbEntity(testParamsEntity);
|
||||
testParamsEntity.SetParamsProvider(paramsProvider);
|
||||
return paramsProvider;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IParamsProvider paramsProvider = CreateTestParamsProvider();
|
||||
(paramsProvider as ITestParams).FromDbEntity(Name, test);
|
||||
return paramsProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig;
|
||||
|
||||
namespace TBF.Rig.Configs
|
||||
{
|
||||
public class ConfigCtrlUtils : UserControl
|
||||
{
|
||||
protected PageOrientation GetOrientation(string str)
|
||||
{
|
||||
if (str.Equals(PageOrientation.Landscape.ToString())) return PageOrientation.Landscape;
|
||||
if (str.Equals(PageOrientation.Portrait.ToString())) return PageOrientation.Portrait;
|
||||
return (PageOrientation)(-1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination variable</param>
|
||||
/// <param name="intVal">Source value</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref int cfgVar, int intVal, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
if (cfgVar != intVal) { cfgVar = intVal; return flagsWhenUpdated; } else return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination variable</param>
|
||||
/// <param name="toBeParsedString">Source integer value is obtained by parsing this string</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref int cfgVar, string toBeParsedString, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
int itmp = int.Parse(toBeParsedString);
|
||||
if (cfgVar != itmp) { cfgVar = itmp; return flagsWhenUpdated; } else return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination variable</param>
|
||||
/// <param name="toBeParsedString">Source integer value is obtained by parsing this string</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref float cfgVar, string toBeParsedString, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
float ftmp = Utils.ParseSFloat(toBeParsedString);
|
||||
if (cfgVar != ftmp) { cfgVar = ftmp; return flagsWhenUpdated; } else return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination variable</param>
|
||||
/// <param name="toBeParsedString">Source integer value is obtained by parsing this string</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref double cfgVar, string toBeParsedString, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
double dtmp = Utils.ParseSDouble(toBeParsedString);
|
||||
if (cfgVar != dtmp) { cfgVar = dtmp; return flagsWhenUpdated; } else return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination variable</param>
|
||||
/// <param name="boolVal">Source value</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref bool cfgVar, bool boolVal, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
if (cfgVar != boolVal) { cfgVar = boolVal; return flagsWhenUpdated; } else return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination variable</param>
|
||||
/// <param name="stringVal">Source value</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref string cfgVar, string stringVal, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
if (cfgVar != stringVal) { cfgVar = stringVal; return flagsWhenUpdated; } else return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates destination variable when its value differes from the source value.
|
||||
/// Returns appropriate flags
|
||||
/// </summary>
|
||||
/// <param name="cfgVar">Reference to destination array</param>
|
||||
/// <param name="stringArrVal">Source array of strings</param>
|
||||
/// <param name="flagsWhenUpdated">Flags returned when an update occurs</param>
|
||||
/// <returns>Flags or 0</returns>
|
||||
protected CfgUpdateFlags UpdateDifferent(ref string[] cfgVar, string[] stringArrVal, CfgUpdateFlags flagsWhenUpdated)
|
||||
{
|
||||
if (cfgVar == null && stringArrVal == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (cfgVar == null || stringArrVal == null || !cfgVar.SequenceEqual<string>(stringArrVal))
|
||||
{
|
||||
cfgVar = stringArrVal;
|
||||
return flagsWhenUpdated;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
///
|
||||
/// Copyright (c) 2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Configs.NameOnly
|
||||
{
|
||||
public class TestMethodCfg : ComponentCfgBase, Generic.IComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TestMethodCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new TestMethodCfgCtrl(); }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
TestMethodCfg() { }
|
||||
|
||||
public TestMethodCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}", Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
///
|
||||
/// Copyright (c) 2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Configs.NameOnly
|
||||
{
|
||||
public partial class TestMethodCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
TestMethodCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as TestMethodCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public TestMethodCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void EntryFormCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
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.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
config.Name = nameTextBox.Text;
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
///
|
||||
/// Copyright (c) 2016 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Configs.NameOnly
|
||||
{
|
||||
partial class TestMethodCfgCtrl
|
||||
{
|
||||
/// <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.SuspendLayout();
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(137, 57);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.nameTextBox.TabIndex = 5;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(27, 60);
|
||||
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(134, 33);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 3;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// BasicPrinterCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "BasicPrinterCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 200);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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,192 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.Configs.ParamsProvider
|
||||
{
|
||||
public partial class ComponentCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
static readonly ILog log = LogManager.GetLogger(typeof(ComponentCfgCtrl));
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
|
||||
IParamsProvider paramsProvider;
|
||||
///
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get
|
||||
{
|
||||
return paramsProvider as IComponentCfg;
|
||||
}
|
||||
set
|
||||
{
|
||||
paramsProvider = value as IParamsProvider;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
Control[] editors;
|
||||
CfgUpdateFlags flags;
|
||||
|
||||
public ComponentCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="paramsProvider">Parameters provider implementing IComponentCfg and IParamsProvider</param>
|
||||
/// <param name="parents">A list of parents or null, null hides parentComboBox</param>
|
||||
public ComponentCfgCtrl(IParamsProvider paramsProvider, IEnumerable<Component> parents)
|
||||
: this()
|
||||
{
|
||||
this.paramsProvider = paramsProvider;
|
||||
|
||||
if (parents == null)
|
||||
{
|
||||
parentLabel.Visible = false;
|
||||
parentComboBox.Visible = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var p in parents) parentComboBox.Items.Add(p.Name);
|
||||
}
|
||||
|
||||
editors = new Control[paramsProvider.ParamsCount()];
|
||||
for (int i = 0; i < paramsProvider.ParamsCount(); i++)
|
||||
{
|
||||
ICollection<string> values = paramsProvider.ParamValues(i);
|
||||
if (values == null)
|
||||
{
|
||||
editors[i] = new TextBox();
|
||||
}
|
||||
else
|
||||
{
|
||||
ComboBox cb = new ComboBox();
|
||||
foreach (var v in values) cb.Items.Add(v);
|
||||
editors[i] = cb;
|
||||
}
|
||||
editors[i].Visible = false;
|
||||
this.Controls.Add(editors[i]);
|
||||
}
|
||||
|
||||
flags = CfgUpdateFlags.None;
|
||||
|
||||
paramsListViewEx.SubItemClicked += new Results.Forms.SubItemEventHandler(paramsListViewEx_SubItemClicked);
|
||||
paramsListViewEx.SubItemEndEditing += new Results.Forms.SubItemEndEditingEventHandler(paramsListViewEx_SubItemEndEditing);
|
||||
}
|
||||
|
||||
void Localize()
|
||||
{
|
||||
componentClassLabel.Text = Strings.Component_class;
|
||||
nameLabel.Text = Strings.Name;
|
||||
parentLabel.Text = Strings.Parent_name;
|
||||
}
|
||||
|
||||
private void EntryFormCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
Localize();
|
||||
paramsListViewEx.Columns.Add(Strings.Parameter, 210);
|
||||
paramsListViewEx.Columns.Add(Strings.Value, 210);
|
||||
Redraw();
|
||||
}
|
||||
|
||||
public void Closing()
|
||||
{
|
||||
/// Close CmdResponse handlers here
|
||||
}
|
||||
|
||||
void Redraw()
|
||||
{
|
||||
if (paramsProvider == null) return; /// Control was not loaded, settings were not changed
|
||||
|
||||
componentClassTextBox.Text = Config.Factory.ClassName;
|
||||
nameTextBox.Text = Config.Name;
|
||||
|
||||
if (parentComboBox.Visible) parentComboBox.Text = Config.ParentName;
|
||||
|
||||
paramsListViewEx.Items.Clear();
|
||||
for (int i = 0; i < paramsProvider.ParamsCount(); i++)
|
||||
{
|
||||
ListViewItem lvi = new ListViewItem(paramsProvider.ParamName(i));
|
||||
lvi.SubItems.Add(paramsProvider.ToString(i));
|
||||
lvi.Tag = i;
|
||||
paramsListViewEx.Items.Add(lvi);
|
||||
}
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentComboBox.Enabled = true; /// It still may be invisible
|
||||
paramsListViewEx.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
/// Verify the parent (if parent combo box is visible)
|
||||
if (!parentComboBox.Visible || parentComboBox.Items.Contains(parentComboBox.Text))
|
||||
{
|
||||
return CfgUpdateFlags.None;
|
||||
}
|
||||
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, parentLabel.Text);
|
||||
return CfgUpdateFlags.Error;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
if (paramsProvider == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
CfgUpdateFlags f = this.flags;
|
||||
|
||||
if (Config.Name != nameTextBox.Text)
|
||||
{
|
||||
Config.Name = nameTextBox.Text;
|
||||
f |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
if (parentComboBox.Visible && Config.ParentName != parentComboBox.Text)
|
||||
{
|
||||
Config.ParentName = parentComboBox.Text;
|
||||
f |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private void paramsListViewEx_SubItemClicked(object sender, Results.Forms.SubItemEventArgs e)
|
||||
{
|
||||
if (e.SubItem != 1) return;
|
||||
int itemNr = (int)e.Item.Tag;
|
||||
paramsListViewEx.StartEditing(editors[itemNr], e.Item, e.SubItem);
|
||||
}
|
||||
|
||||
private void paramsListViewEx_SubItemEndEditing(object sender, Results.Forms.SubItemEndEditingEventArgs e)
|
||||
{
|
||||
if (e.SubItem != 1) return;
|
||||
int itemNr = (int)e.Item.Tag;
|
||||
|
||||
string message;
|
||||
if (paramsProvider.ValidateParam(itemNr, e.DisplayText, out message))
|
||||
{
|
||||
flags |= paramsProvider.UpdateParam(itemNr, e.DisplayText);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(message);
|
||||
e.DisplayText = e.Item.SubItems[e.SubItem].Text;
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.Configs.ParamsProvider
|
||||
{
|
||||
partial class ComponentCfgCtrl
|
||||
{
|
||||
/// <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.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.parentComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.parentLabel = new System.Windows.Forms.Label();
|
||||
this.componentClassLabel = new System.Windows.Forms.Label();
|
||||
this.componentClassTextBox = new System.Windows.Forms.TextBox();
|
||||
this.paramsListViewEx = new Results.Forms.ListViewEx();
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||
this.splitContainer1.Panel1.SuspendLayout();
|
||||
this.splitContainer1.Panel2.SuspendLayout();
|
||||
this.splitContainer1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(161, 30);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(262, 20);
|
||||
this.nameTextBox.TabIndex = 5;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(6, 33);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 4;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
|
||||
this.splitContainer1.IsSplitterFixed = true;
|
||||
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
|
||||
this.splitContainer1.Name = "splitContainer1";
|
||||
this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||
//
|
||||
// splitContainer1.Panel1
|
||||
//
|
||||
this.splitContainer1.Panel1.Controls.Add(this.parentComboBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.parentLabel);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.componentClassLabel);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.componentClassTextBox);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.nameLabel);
|
||||
this.splitContainer1.Panel1.Controls.Add(this.nameTextBox);
|
||||
//
|
||||
// splitContainer1.Panel2
|
||||
//
|
||||
this.splitContainer1.Panel2.Controls.Add(this.paramsListViewEx);
|
||||
this.splitContainer1.Size = new System.Drawing.Size(444, 353);
|
||||
this.splitContainer1.SplitterDistance = 80;
|
||||
this.splitContainer1.TabIndex = 6;
|
||||
//
|
||||
// parentComboBox
|
||||
//
|
||||
this.parentComboBox.Enabled = false;
|
||||
this.parentComboBox.FormattingEnabled = true;
|
||||
this.parentComboBox.Location = new System.Drawing.Point(161, 52);
|
||||
this.parentComboBox.Name = "parentComboBox";
|
||||
this.parentComboBox.Size = new System.Drawing.Size(262, 21);
|
||||
this.parentComboBox.TabIndex = 9;
|
||||
//
|
||||
// parentLabel
|
||||
//
|
||||
this.parentLabel.AutoSize = true;
|
||||
this.parentLabel.Location = new System.Drawing.Point(6, 55);
|
||||
this.parentLabel.Name = "parentLabel";
|
||||
this.parentLabel.Size = new System.Drawing.Size(38, 13);
|
||||
this.parentLabel.TabIndex = 8;
|
||||
this.parentLabel.Text = "Parent";
|
||||
//
|
||||
// componentClassLabel
|
||||
//
|
||||
this.componentClassLabel.AutoSize = true;
|
||||
this.componentClassLabel.Location = new System.Drawing.Point(6, 11);
|
||||
this.componentClassLabel.Name = "componentClassLabel";
|
||||
this.componentClassLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.componentClassLabel.TabIndex = 7;
|
||||
this.componentClassLabel.Text = "Component Class";
|
||||
//
|
||||
// componentClassTextBox
|
||||
//
|
||||
this.componentClassTextBox.Enabled = false;
|
||||
this.componentClassTextBox.Location = new System.Drawing.Point(161, 8);
|
||||
this.componentClassTextBox.Name = "componentClassTextBox";
|
||||
this.componentClassTextBox.Size = new System.Drawing.Size(262, 20);
|
||||
this.componentClassTextBox.TabIndex = 6;
|
||||
//
|
||||
// paramsListViewEx
|
||||
//
|
||||
this.paramsListViewEx.AllowColumnReorder = true;
|
||||
this.paramsListViewEx.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.paramsListViewEx.DoubleClickActivation = false;
|
||||
this.paramsListViewEx.Enabled = false;
|
||||
this.paramsListViewEx.FullRowSelect = true;
|
||||
this.paramsListViewEx.GridLines = true;
|
||||
this.paramsListViewEx.LabelWrap = false;
|
||||
this.paramsListViewEx.Location = new System.Drawing.Point(0, 0);
|
||||
this.paramsListViewEx.Name = "paramsListViewEx";
|
||||
this.paramsListViewEx.Size = new System.Drawing.Size(444, 269);
|
||||
this.paramsListViewEx.TabIndex = 0;
|
||||
this.paramsListViewEx.UseCompatibleStateImageBehavior = false;
|
||||
this.paramsListViewEx.View = System.Windows.Forms.View.Details;
|
||||
this.paramsListViewEx.SubItemClicked += new Results.Forms.SubItemEventHandler(this.paramsListViewEx_SubItemClicked);
|
||||
this.paramsListViewEx.SubItemEndEditing += new Results.Forms.SubItemEndEditingEventHandler(this.paramsListViewEx_SubItemEndEditing);
|
||||
//
|
||||
// ComponentCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Name = "ComponentCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(444, 353);
|
||||
this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load);
|
||||
this.splitContainer1.Panel1.ResumeLayout(false);
|
||||
this.splitContainer1.Panel1.PerformLayout();
|
||||
this.splitContainer1.Panel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
|
||||
this.splitContainer1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.SplitContainer splitContainer1;
|
||||
private System.Windows.Forms.ComboBox parentComboBox;
|
||||
private System.Windows.Forms.Label parentLabel;
|
||||
private System.Windows.Forms.Label componentClassLabel;
|
||||
private System.Windows.Forms.TextBox componentClassTextBox;
|
||||
private Results.Forms.ListViewEx paramsListViewEx;
|
||||
}
|
||||
}
|
||||
@@ -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,14 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2017 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// A fraction of the tank volume that is considered to be safe.
|
||||
/// When the estimated test end tank volume exceeds this fraction, tank emptying is forced.
|
||||
/// </summary>
|
||||
public const float TankFullFactor = 0.95f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Config.Entities;
|
||||
using Dirichlet.Numerics;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.ControlBoard
|
||||
{
|
||||
public interface IControlBoard : IDevice, IValveControl
|
||||
{
|
||||
void SpecifyInvertedValves(UInt128 valvesToInvert);
|
||||
|
||||
/// <summary>
|
||||
/// Called on beginning of a test
|
||||
/// </summary>
|
||||
void ClearProcessValues();
|
||||
|
||||
|
||||
///
|
||||
/// Values valid always
|
||||
///
|
||||
UInt128 Route { get; } /// State of valves
|
||||
UInt64 DigitalInputs { get; } /// Inputs
|
||||
|
||||
///
|
||||
/// Values valid during a test
|
||||
///
|
||||
double RefFrequency { get; }
|
||||
double RefFlow { get; }
|
||||
|
||||
///
|
||||
/// Last test results
|
||||
///
|
||||
double TestTime { get; }
|
||||
int RefPulses { get; }
|
||||
|
||||
double TestTimeWM(int wmNr1);
|
||||
int RefPulsesWM(int wmNr1);
|
||||
int PulsesWM(int wmNr1);
|
||||
|
||||
float ValveOpenCloseTime { get; } /// Start valve open or close time in sec
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Select devices used for control and measurement
|
||||
/// </summary>
|
||||
/// <param name="outPath"></param>
|
||||
OutputPath Devices { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns operation which sets the flow. Events:
|
||||
/// </summary>
|
||||
/// <param name="flowLimLo">Lower flow limit</param>
|
||||
/// <param name="flowLimHi">Upper flow limit</param>
|
||||
/// <param name="measuredFlow">Reference to calss keeping current flow value</param>
|
||||
/// <param name="timeout">Timeout in seconds</param>
|
||||
/// <returns>Operation</returns>
|
||||
IOperation SetFlowOp(double flowLimLo, double flowLimHi, TBF.Boxes.DoubleBox measuredFlow, int timeout);
|
||||
|
||||
IOperation StopFlowRegulationOp();
|
||||
|
||||
/// <summary>
|
||||
/// Start a test, Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="iParam">Int32 parameter 1</param>
|
||||
/// <param name="dParam1">Double parameter 1 (alternative lower flow limit)</param>
|
||||
/// <param name="dParam2">Double parameter 2 (alternative upper flow limit)</param>
|
||||
/// <returns>Operation</returns>
|
||||
IOperation StartTestOp(Test test, int iParam = 0, double dParam1 = 0, double dParam2 = 0);
|
||||
|
||||
IOperation ReadDiverterTransitionOp(bool isStart, Sequences.Statistics plotter, int batchNr, string testName, int repetition);
|
||||
|
||||
/// <summary>
|
||||
/// Returns operation with events: Event.MeasurementCompleted or Event.None
|
||||
/// </summary>
|
||||
/// <returns>Operation</returns>
|
||||
IOperation QueryMeasurementEndOp();
|
||||
|
||||
IOperation StopPreviousOp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public enum Command
|
||||
{
|
||||
None = 0, /// Do nothing, just transfer data (route, etc.)
|
||||
Start = 1, /// Start the measurement
|
||||
Stop = 2, /// Stop the measurement
|
||||
ReadDivTransition = 4,
|
||||
ReadExtremasOfPulses = 6,
|
||||
ReadShapesOfPulses = 7,
|
||||
ResetShapesOfPulses = 8,
|
||||
EnduranceCycleParamsUpload = 11,
|
||||
EnduranceCycleStart = 12,
|
||||
EnduranceCycleStop = 13,
|
||||
}
|
||||
|
||||
#if FUZHOU_300 || IZRAEL_200 || TORINO_50 || BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || BADGER_VELKA_TRAT || PUCHONG_200 || SLM_50 || GENESIS || MALTA_WSD25 || SLM_END || WARSAW_END || BERLIN || GELSENWASSER || SLM_150 || PETERSBURG_50 || PETERSBURG_200 || DEWA_300 || ROMA_200 || KEMPNO_50 || BAHRAIN_50 || RUM_MOB || KRAKOW_50 || JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || SENTEC || FUZHOU_100 || CEVAK_200 || IZRAEL_50 || ALZIR_25
|
||||
public enum StatusP : ulong
|
||||
{
|
||||
RefFlowMeterMask = 0x7, /// bits 0,1,2
|
||||
TestCompleted = 0x10, /// bit 4
|
||||
TestInProgress = 0x20, /// bit 5
|
||||
//DiverterError = 0x20,
|
||||
MsrmntWithDivrtr = 0x80, /// bit 7
|
||||
RefPulsesMsrmnt = 0x100, /// bit 8
|
||||
SynchroMethod = 0x800, /// bit 11
|
||||
WaterMeterCalib = 0x1000, /// bit 12
|
||||
EmgcyStopActive = 0x2000, /// bit 13
|
||||
MsrmntGateActive = 0x4000, /// bit 14
|
||||
TimeMeasurement = 0x8000, /// bit 15
|
||||
FrequencyMeasured = 0x80000, /// bit 19
|
||||
CoaxRegValveBusy = 0x200000, /// bit 21
|
||||
ADCError = 0x80000000, /// bit 31
|
||||
TimeoutOccured = 0x100000000, /// bit 32
|
||||
MeretAddresses = 0x200000000, /// bit 33
|
||||
SampleBuferFull = 0x400000000, /// bit 34
|
||||
ErrorTempMeter = 0x10000000000, /// bit 40
|
||||
ErrorPressMeter1 = 0x1000000000000, /// bit 48
|
||||
ErrorPressMeter2 = 0x2000000000000, /// bit 49
|
||||
ErrorPressMeter3 = 0x4000000000000, /// bit 50
|
||||
ErrorPressMeter4 = 0x8000000000000, /// bit 51
|
||||
EndurCycleRunning = 0x200000000000000, /// bit 57
|
||||
}
|
||||
#else // DN100 || MUNICH || FUZHOU_150 || TORUN_50 || CEVAK_40 || MURES_40 || FUZHOU_50
|
||||
public enum StatusP : ulong
|
||||
{
|
||||
RefFlowMeterMask = 0x7,
|
||||
TestInProgress = 0x8,
|
||||
TestCompleted = 0x10,
|
||||
DiverterError = 0x20,
|
||||
MsrmntWithDivrtr = 0x80,
|
||||
RefPulsesMsrmnt = 0x100,
|
||||
SynchroMethod = 0x800,
|
||||
WaterMeterCalib = 0x1000,
|
||||
EmgcyStopActive = 0x2000,
|
||||
MsrmntGateActive = 0x4000,
|
||||
TimeMeasurement = 0x8000,
|
||||
FrequencyMeasured = 0x80000,
|
||||
CoaxRegValveBusy = 0x200000, /// bit 21
|
||||
ADCError = 0x80000000,
|
||||
TimeoutOccured = 0x100000000,
|
||||
MeretAddresses = 0x200000000,
|
||||
SampleBuferFull = 0x400000000,
|
||||
ErrorTempMeter = 0x10000000000,
|
||||
ErrorPressMeter1 = 0x1000000000000,
|
||||
ErrorPressMeter2 = 0x2000000000000,
|
||||
ErrorPressMeter3 = 0x4000000000000,
|
||||
ErrorPressMeter4 = 0x8000000000000,
|
||||
EndurCycleRunning = 0x200000000000000, /// bit 57
|
||||
}
|
||||
#endif
|
||||
|
||||
public enum StopDevs
|
||||
{
|
||||
None = 0,
|
||||
Reference = 0x01, /// bit 0
|
||||
Diverter = 0x02, /// bit 1
|
||||
GatePulse = 0x08, /// bit 3
|
||||
TimeMeasurement = 0x10, /// bit 4
|
||||
BypassDevCoupled2Div = 0x20, /// bit 5
|
||||
RegValveRegulation = 0x80, /// bit 7
|
||||
All = 0xFF,
|
||||
}
|
||||
|
||||
public enum TestMethods
|
||||
{
|
||||
Diverter = 0x01, /// bit 0: 1=Mass method (diverters are used), 0=Volume method
|
||||
FixedStart = 0x02, /// bit 1: 1=fixed start method, 0=flying start method
|
||||
Synchro = 0x04, /// bit 2: 1=Synchro method, 0=Pulse counting
|
||||
MassAndContinue = 0x10, /// bit 4: 1=Method with mass measurement followed by a volume method
|
||||
}
|
||||
|
||||
public enum RegulValveMode : byte
|
||||
{
|
||||
None = 0,
|
||||
PulseWidth = 1, /// Pulse width 0.05 .. 2 sec.
|
||||
TargetPosition = 2, /// Low and high position (=DAC value) limits (0..100%) are specified
|
||||
TargetFrequency = 3, /// Low and high frequency limits (0..2000Hz,0..2200Hz) are specified
|
||||
Stop = 4, /// Stop regulation
|
||||
}
|
||||
|
||||
public enum RegulValveState
|
||||
{
|
||||
Idle = 0,
|
||||
PwOrFreqRegul = 2,
|
||||
DacValueRegul = 3,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class ControlBoardCfg : ComponentCfgBase, IComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ControlBoardCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new ControlBoardCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int ComPortNr;
|
||||
public int VirtualValvesRangeLo;
|
||||
public int VirtualValvesRangeHi;
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ControlBoardCfg()
|
||||
{
|
||||
Name = "CB";
|
||||
ParentName = string.Empty;
|
||||
ComPortNr = 1;
|
||||
VirtualValvesRangeLo = 50;
|
||||
VirtualValvesRangeHi = 59;
|
||||
}
|
||||
|
||||
public ControlBoardCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
this.Factory = factory;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, Com{1}, VVRangeLo={2}, VVRangeHi={3}", Name, ComPortNr, VirtualValvesRangeLo, VirtualValvesRangeHi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
partial class ControlBoardCfgCtrl
|
||||
{
|
||||
/// <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.comPortNrLabel = new System.Windows.Forms.Label();
|
||||
this.comPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.vValveRangeLoTextBox = new System.Windows.Forms.TextBox();
|
||||
this.vValveRangeLoLabel = new System.Windows.Forms.Label();
|
||||
this.vValveRangeHiTextBox = new System.Windows.Forms.TextBox();
|
||||
this.vValveRangeHiLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// comPortNrLabel
|
||||
//
|
||||
this.comPortNrLabel.AutoSize = true;
|
||||
this.comPortNrLabel.Location = new System.Drawing.Point(42, 85);
|
||||
this.comPortNrLabel.Name = "comPortNrLabel";
|
||||
this.comPortNrLabel.Size = new System.Drawing.Size(95, 13);
|
||||
this.comPortNrLabel.TabIndex = 0;
|
||||
this.comPortNrLabel.Text = "Serial port number:";
|
||||
//
|
||||
// comPortNrTextBox
|
||||
//
|
||||
this.comPortNrTextBox.Enabled = false;
|
||||
this.comPortNrTextBox.Location = new System.Drawing.Point(166, 82);
|
||||
this.comPortNrTextBox.Name = "comPortNrTextBox";
|
||||
this.comPortNrTextBox.Size = new System.Drawing.Size(80, 20);
|
||||
this.comPortNrTextBox.TabIndex = 1;
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(163, 26);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 2;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(42, 60);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 3;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(166, 57);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(80, 20);
|
||||
this.nameTextBox.TabIndex = 4;
|
||||
//
|
||||
// vValveRangeLoTextBox
|
||||
//
|
||||
this.vValveRangeLoTextBox.Enabled = false;
|
||||
this.vValveRangeLoTextBox.Location = new System.Drawing.Point(166, 107);
|
||||
this.vValveRangeLoTextBox.Name = "vValveRangeLoTextBox";
|
||||
this.vValveRangeLoTextBox.Size = new System.Drawing.Size(80, 20);
|
||||
this.vValveRangeLoTextBox.TabIndex = 6;
|
||||
//
|
||||
// vValveRangeLoLabel
|
||||
//
|
||||
this.vValveRangeLoLabel.AutoSize = true;
|
||||
this.vValveRangeLoLabel.Location = new System.Drawing.Point(42, 110);
|
||||
this.vValveRangeLoLabel.Name = "vValveRangeLoLabel";
|
||||
this.vValveRangeLoLabel.Size = new System.Drawing.Size(118, 13);
|
||||
this.vValveRangeLoLabel.TabIndex = 5;
|
||||
this.vValveRangeLoLabel.Text = "Virtual valves range Lo:";
|
||||
//
|
||||
// vValveRangeHiTextBox
|
||||
//
|
||||
this.vValveRangeHiTextBox.Enabled = false;
|
||||
this.vValveRangeHiTextBox.Location = new System.Drawing.Point(166, 132);
|
||||
this.vValveRangeHiTextBox.Name = "vValveRangeHiTextBox";
|
||||
this.vValveRangeHiTextBox.Size = new System.Drawing.Size(80, 20);
|
||||
this.vValveRangeHiTextBox.TabIndex = 8;
|
||||
//
|
||||
// vValveRangeHiLabel
|
||||
//
|
||||
this.vValveRangeHiLabel.AutoSize = true;
|
||||
this.vValveRangeHiLabel.Location = new System.Drawing.Point(42, 135);
|
||||
this.vValveRangeHiLabel.Name = "vValveRangeHiLabel";
|
||||
this.vValveRangeHiLabel.Size = new System.Drawing.Size(116, 13);
|
||||
this.vValveRangeHiLabel.TabIndex = 7;
|
||||
this.vValveRangeHiLabel.Text = "Virtual valves range Hi:";
|
||||
//
|
||||
// ControlBoardCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.vValveRangeHiTextBox);
|
||||
this.Controls.Add(this.vValveRangeHiLabel);
|
||||
this.Controls.Add(this.vValveRangeLoTextBox);
|
||||
this.Controls.Add(this.vValveRangeLoLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Controls.Add(this.comPortNrTextBox);
|
||||
this.Controls.Add(this.comPortNrLabel);
|
||||
this.Name = "ControlBoardCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 200);
|
||||
this.Load += new System.EventHandler(this.ControlBoardCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label comPortNrLabel;
|
||||
private System.Windows.Forms.TextBox comPortNrTextBox;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.TextBox vValveRangeLoTextBox;
|
||||
private System.Windows.Forms.Label vValveRangeLoLabel;
|
||||
private System.Windows.Forms.TextBox vValveRangeHiTextBox;
|
||||
private System.Windows.Forms.Label vValveRangeHiLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public partial class ControlBoardCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
ControlBoardCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as ControlBoardCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public ControlBoardCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ControlBoardCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
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;
|
||||
comPortNrTextBox.Text = config.ComPortNr.ToString();
|
||||
vValveRangeLoTextBox.Text = config.VirtualValvesRangeLo.ToString();
|
||||
vValveRangeHiTextBox.Text = config.VirtualValvesRangeHi.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
comPortNrTextBox.Enabled = true;
|
||||
vValveRangeLoTextBox.Enabled = true;
|
||||
vValveRangeHiTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify current user controls for validity.
|
||||
/// Called when user wants to close/save the configuration.
|
||||
/// </summary>
|
||||
/// <returns>See VerifyFlags</returns>
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy <= 0 || dummy > 999)
|
||||
{
|
||||
message += "Control board serial port number is invalid";
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
}
|
||||
if (!int.TryParse(vValveRangeLoTextBox.Text, out dummy) || dummy < 0 || dummy > 63)
|
||||
{
|
||||
message += "Virtual valves range Lo is invalid";
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
}
|
||||
if (!int.TryParse(vValveRangeHiTextBox.Text, out dummy) || dummy < 0 || dummy > 63)
|
||||
{
|
||||
message += "Virtual valves range Hi is invalid";
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save settings to the configuration class.
|
||||
/// </summary>
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
this.Name = nameTextBox.Text;
|
||||
this.config.ComPortNr = int.Parse(comPortNrTextBox.Text);
|
||||
this.config.VirtualValvesRangeLo = int.Parse(vValveRangeLoTextBox.Text);
|
||||
this.config.VirtualValvesRangeHi = int.Parse(vValveRangeHiTextBox.Text);
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,864 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.IO.Ports;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using Dirichlet.Numerics;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class CBoard : ComponentBase, IControlBoard
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(CBoard));
|
||||
public override string ToString() { return string.Format("ControlBoard({0})", Cfg.ToString(1)); }
|
||||
|
||||
const int FiltersCount = 8;
|
||||
|
||||
readonly ControlBoardCfg controlBoardCfg;
|
||||
|
||||
///
|
||||
/// Reference to the control board component
|
||||
///
|
||||
IControlCom controlCom;
|
||||
|
||||
/// <summary>
|
||||
/// Emergency stop signal state updated by RunDevice().
|
||||
/// 'modelessDlg' is notified about the changes and uses this information to change its visibility.
|
||||
/// </summary>
|
||||
//UiBridge.EmergencyStopEventArgs.State emergencyStopState;
|
||||
|
||||
|
||||
///
|
||||
/// Public read only wrappers for Elde software component fields
|
||||
///
|
||||
/// rvNr1 = 1 .. nrRegulValves (one based)
|
||||
/// wmNr0 = 0 .. nrWaterMeters-1 (zero based)
|
||||
/// tmpNr0 = 0 .. nrTempMeters-1 (zero based)
|
||||
/// prsNr0 = 0 .. nrPressureMeters-1 (zero based)
|
||||
///
|
||||
public StatusP StatusP { get { return controlCom.StatusP; } }
|
||||
public int EtPulsesK { get { return controlCom.EtPulsesK; } }
|
||||
public int EtPulses2 { get { return controlCom.EtPulses2; } } /// DEWA_300: pulses from I12
|
||||
public int EtPulses3 { get { return controlCom.EtPulses3; } } /// DEWA_300: pulses from I13
|
||||
public int WMeterReference(int wmNr0) { return controlCom.WMeterReference(wmNr0); }
|
||||
public uint RegulValveDAC(int rvNr0) { return controlCom.RegulValveDAC(rvNr0); }
|
||||
public float Pressure(int prsNr0) { return controlCom.Pressure(prsNr0); }
|
||||
public float Temperature(int tmpNr0) { return controlCom.Temperature(tmpNr0); }
|
||||
public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)controlCom.RegulValveState(rvNr1); }
|
||||
public UInt128 RRoute { get { return controlCom.RRoute; } }
|
||||
public uint DivTime(int id) { return controlCom.DivTime(id); }
|
||||
public uint FmState { get { return controlCom.FmState; } }
|
||||
public uint BeginState(int wmNr0) { return controlCom.BeginState(wmNr0); }
|
||||
public double RefFrequency { get { return controlCom.ReferenceFreq; } } /// In [Hz] 0..2500, nom.=2000
|
||||
public double ReferenceFreqs(int i) { return controlCom.ReferenceFreqs(i); }
|
||||
public double RefFlow { get { return controlCom.ReferenceFlow; } }
|
||||
public float RValvePosition(int rvNr1) { return controlCom.RValvePosition(rvNr1); }
|
||||
public float DivSamples(int time, int divIx0) { return controlCom.DivSamples(time, divIx0); } /// Time unit is 2 ms
|
||||
public int ScopeSamples(int i, int j, int k) { return controlCom.ScopeSamples(i, j, k); }
|
||||
public ulong DigitalInputs { get { return controlCom.DigitalInputs; } }
|
||||
public float AnalogInput(int adcNr0) { return controlCom.AnalogInput(adcNr0); }
|
||||
public uint AnalogInputRaw(int adcNr0, int bank) { return controlCom.AnalogInputRaw(adcNr0, bank); } /// adcNr0: 0=RV1, 1=RV2,... bank: 0=RV, 1=Temp
|
||||
public float ReferenceVolume { get { return controlCom.TotalRefVolume; } }
|
||||
public float VyslExt(int wmNr0, int what) { return controlCom.VyslExt(wmNr0, what); }
|
||||
public uint[] CyclePar { get { return controlCom.CyclePar; } set { controlCom.CyclePar = value; } }
|
||||
public uint[] WMeterCont { get { return controlCom.WMeterCont; } }
|
||||
public bool ManualUIAllowed { get { return controlCom.ManualUIAllowed; } set { controlCom.ManualUIAllowed = value; } }
|
||||
public float ValveOpenCloseTime { get { return controlCom.ValveOpenCloseTime; } }
|
||||
|
||||
/// <summary> Extracted from the StatusP in RunDeviceBefore </summary>
|
||||
public bool EmergencyStop { get { return emergencyStop; } }
|
||||
bool emergencyStop;
|
||||
bool previousEmergencyStop;
|
||||
|
||||
|
||||
///
|
||||
/// IControlBoard interface
|
||||
///
|
||||
public int RefPulses { get { return controlCom.EtPulses(0); } }
|
||||
public double TestTime { get { return (double)controlCom.TTime; } }
|
||||
public int RefPulsesWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? controlCom.EtPulses(wmNr1) : 0; }
|
||||
public int PulsesWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? unwrappedWMPulses[wmNr1] : 0; }
|
||||
public double TestTimeWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? (double)controlCom.ImpulseTime(wmNr1) : 0; }
|
||||
|
||||
|
||||
public void DiverterToTank(int flowMtrNr)
|
||||
{
|
||||
cbCommandQueue.Enqueue(new SendCommandArgs(Command.Start, flowMtrNr, int.MaxValue, int.MaxValue, TestMethods.Diverter | TestMethods.Synchro, StopDevs.None));
|
||||
}
|
||||
///
|
||||
public void DiverterToSink(int flowMtrNr)
|
||||
{
|
||||
cbCommandQueue.Enqueue(new SendCommandArgs(Command.Stop, 0, 0, 0, TestMethods.Diverter,
|
||||
StopDevs.Diverter | StopDevs.GatePulse | StopDevs.Reference | StopDevs.RegValveRegulation));
|
||||
}
|
||||
///
|
||||
public void ReadDiverterTransition(int flowMtrNr)
|
||||
{
|
||||
cbCommandQueue.Enqueue(new SendCommandArgs(Command.ReadDivTransition, flowMtrNr, 0, 0, TestMethods.Diverter, 0));
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialization data updated by constructors of children components
|
||||
/// and sent to 'controlCom2panel' by SendCalibData() method.
|
||||
///
|
||||
#if DEWA_300 || ROMA_200
|
||||
public float[,] TempCalibData = new float[16, 5];
|
||||
#else
|
||||
public float[,] TempCalibData = new float[8, 5];
|
||||
#endif
|
||||
public uint[] DiverterEdge; /// Created and initialized in this.Initialize()
|
||||
public byte MeretProtocol = 0;
|
||||
|
||||
// Array length is the reference flowmeters count plus one
|
||||
#if DN100 || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || SENTEC || CEVAK_200
|
||||
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
|
||||
public byte[] MeretRS485Address = new byte[4];
|
||||
public float[] EtCalib = new float[6] { 1, 1, 1, 1, 1, 1 };
|
||||
#elif PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER || PETERSBURG_200 || RUM_MOB || SLM_150
|
||||
public uint[,] RegValveCalib = new uint[16, 2] { {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500},
|
||||
{100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500} };
|
||||
public byte[] MeretRS485Address = new byte[4];
|
||||
public float[] EtCalib = new float[7] { 1, 1, 1, 1, 1, 1, 1 };
|
||||
#elif DEWA_300
|
||||
public uint[,] RegValveCalib = new uint[16, 2] { {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500},
|
||||
{100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500} };
|
||||
public byte[] MeretRS485Address = new byte[4];
|
||||
public float[] EtCalib = new float[8] { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
#elif ROMA_200
|
||||
public uint[,] RegValveCalib = new uint[16, 2] { {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500},
|
||||
{100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500}, {100,500} };
|
||||
public byte[] MeretRS485Address = new byte[5];
|
||||
public float[] EtCalib = new float[8] { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
#elif MUNICH || TORINO_50 || BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || TORUN_50 || CEVAK_40 || TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || MURES_40 || FUZHOU_50 || SLM_50 || PETERSBURG_50 || KEMPNO_50 || BAHRAIN_50 || KRAKOW_50 || JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || FUZHOU_100 || ALZIR_25
|
||||
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
|
||||
#if IZRAEL_50
|
||||
public byte[] MeretRS485Address = new byte[6];
|
||||
#else
|
||||
public byte[] MeretRS485Address = new byte[4];
|
||||
#endif
|
||||
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
|
||||
#elif IZRAEL_50 || SLM_END
|
||||
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
|
||||
public byte[] MeretRS485Address = new byte[7]; /// Modbus addresses of Pr1, Pr2, Pr3, Pr4, Pr5, Pr6, T9 (Izrael) or Pr1, Pr2, Pr3, Pr4, T9, T10 (SLM END)
|
||||
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
|
||||
#elif WARSAW_END
|
||||
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
|
||||
public byte[] MeretRS485Address = new byte[4];
|
||||
public float[] EtCalib = new float[5] { 1, 1, 1, 1, 1 };
|
||||
#elif MALTA_WSD25
|
||||
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
|
||||
public byte[] MeretRS485Address = new byte[12];
|
||||
public float[] EtCalib = new float[9] { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
#elif BADGER_VELKA_TRAT
|
||||
public uint[,] RegValveCalib = new uint[8,2] {{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500},{100,500}};
|
||||
public byte[] MeretRS485Address = new byte[4];
|
||||
public float[] EtCalib = new float[8] { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
#else
|
||||
/// New benches => no initialization buffers at all
|
||||
public uint[,] RegValveCalib = new uint[0,0];
|
||||
public byte[] MeretRS485Address = new byte[0];
|
||||
public float[] EtCalib = new float[0];
|
||||
#endif
|
||||
|
||||
public uint[] BalanceRange = new uint[2];
|
||||
|
||||
|
||||
|
||||
Queue<SendCommandArgs> cbCommandQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Route: 128-bit word representing the current state of all valves and pumps
|
||||
/// </summary>
|
||||
public UInt128 Route { get { return benchModelRoute; } }
|
||||
UInt128 benchModelRoute;
|
||||
UInt128 valvesToInvert; /// Route = valesToInvert ^ RequiredRouteWithoutInvertedVlaves
|
||||
readonly UInt128 routeMask; /// This mask masks out virtual valves, routeMask is set in the constructor
|
||||
|
||||
|
||||
public OutputPath Devices
|
||||
{
|
||||
set { devices = value; }
|
||||
get { return devices; }
|
||||
}
|
||||
OutputPath devices;
|
||||
|
||||
|
||||
int[] filters;
|
||||
float[] FMFreq;
|
||||
int regConst;
|
||||
int shortImp;
|
||||
|
||||
|
||||
private int[] unwrappedWMPulses; /// Initialized to zeros
|
||||
///
|
||||
private void UnwrapPulses()
|
||||
{
|
||||
for (int i = 1; i <= Config.Data.WMsCount; i++)
|
||||
{
|
||||
UInt16 lowerWord = controlCom.WMeterPulses(i);
|
||||
int uncorrected = (int)(((uint)unwrappedWMPulses[i] & 0xFFFF0000) | lowerWord);
|
||||
if (Math.Abs(uncorrected - unwrappedWMPulses[i]) <= Int16.MaxValue)
|
||||
{
|
||||
unwrappedWMPulses[i] = uncorrected;
|
||||
}
|
||||
else if (Math.Abs(uncorrected + 65536 - unwrappedWMPulses[i]) <= Int16.MaxValue)
|
||||
{
|
||||
unwrappedWMPulses[i] = uncorrected + 65536;
|
||||
}
|
||||
else if (Math.Abs(uncorrected - 65536 - unwrappedWMPulses[i]) <= Int16.MaxValue)
|
||||
{
|
||||
unwrappedWMPulses[i] = uncorrected - 65536;
|
||||
}
|
||||
}
|
||||
}
|
||||
///
|
||||
public void ClearProcessValues()
|
||||
{
|
||||
for (int i = 1; i <= Config.Data.WMsCount; i++)
|
||||
{
|
||||
unwrappedWMPulses[i] = 0;
|
||||
}
|
||||
UnwrapPulses();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set values to be applied during a test
|
||||
/// </summary>
|
||||
/// <param name="filters">Filters for meter pulses</param>
|
||||
/// <param name="pid">PID coefficient for flow control</param>
|
||||
/// <param name="shortPulses">Short pulses mode (0 = off)</param>
|
||||
public void SetFiltersPidShortPulses(int[] filters, float pid, int shortPulses)
|
||||
{
|
||||
this.filters = filters;
|
||||
this.regConst = (int)pid;
|
||||
this.shortImp = shortPulses;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the power of the selected pump
|
||||
/// </summary>
|
||||
/// <param name="index">Pump index 0 .. 5, invalid pump index sets all pumps to 0%</param>
|
||||
/// <param name="power">Power (0.0f .. 100.0f)</param>
|
||||
public void SetFMFreq(int index, double power)
|
||||
{
|
||||
bool pumpPowerChanged = false;
|
||||
|
||||
#if DN100 || MUNICH || FUZHOU_150
|
||||
if ((FMFreq == null) || (FMFreq.Length != 2))
|
||||
{
|
||||
FMFreq = new float[2];
|
||||
pumpPowerChanged = true; /// Forces sending a command using Command.None
|
||||
}
|
||||
#elif SLM_END || WARSAW_END
|
||||
if ((FMFreq == null) || (FMFreq.Length != 4))
|
||||
{
|
||||
FMFreq = new float[4];
|
||||
pumpPowerChanged = true; /// Forces sending a command using Command.None
|
||||
}
|
||||
#else /// all newer benches
|
||||
if ((FMFreq == null) || (FMFreq.Length != 6))
|
||||
{
|
||||
FMFreq = new float[6];
|
||||
pumpPowerChanged = true; /// Forces sending a command using Command.None
|
||||
}
|
||||
#endif
|
||||
|
||||
if (index >= 0 && index < FMFreq.Length)
|
||||
{
|
||||
if (FMFreq[index] != power)
|
||||
{
|
||||
FMFreq[index] = (float)power;
|
||||
|
||||
pumpPowerChanged = true; /// Forces sending a command using Command.None
|
||||
|
||||
string s = string.Format("FMFreq=[{0}{1}{2}{3}{4}{5}]", FMFreq[0].ToString(),
|
||||
(FMFreq.Length > 1) ? ("," + FMFreq[1].ToString()) : "",
|
||||
(FMFreq.Length > 2) ? ("," + FMFreq[2].ToString()) : "",
|
||||
(FMFreq.Length > 3) ? ("," + FMFreq[3].ToString()) : "",
|
||||
(FMFreq.Length > 4) ? ("," + FMFreq[4].ToString()) : "",
|
||||
(FMFreq.Length > 5) ? ("," + FMFreq[5].ToString()) : "");
|
||||
log.Warn(s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.ErrorFormat("Wrong FM pump: index = {0}, power = {1}", index, power);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void UpdateWeights()
|
||||
{
|
||||
/// Mettler-Toledo scales
|
||||
for (int i = 0; i < MettlerToledo.Standard.BalanceDev.BalancesCount; i++)
|
||||
{
|
||||
controlCom.SetWeight(i, MettlerToledo.Standard.BalanceDev.Masses[i]);
|
||||
}
|
||||
|
||||
/// Mettler-Toledo-multi scales (Badger Brno, ...)
|
||||
for (int i = 0; i < MettlerToledo.Multi.BalanceDev.BalancesCount; i++)
|
||||
{
|
||||
controlCom.SetWeight(i, MettlerToledo.Multi.BalanceDev.Masses[i]);
|
||||
}
|
||||
|
||||
/// Tanks (CEVAK, ...)
|
||||
int firstTankIx = Math.Max(MettlerToledo.Standard.BalanceDev.BalancesCount, MettlerToledo.Multi.BalanceDev.BalancesCount);
|
||||
|
||||
for (int i = 0; i < Various.TankWithLevelMsrmnt.Tank.TanksCount; i++)
|
||||
{
|
||||
controlCom.SetWeight(firstTankIx + i, Various.TankWithLevelMsrmnt.Tank.Tanks[i].Volume);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Display value in ELDE component, update UI
|
||||
/// </summary>
|
||||
/// <param name="sParam">String parameter</param>
|
||||
/// <param name="iParam">Integer parameter</param>
|
||||
/// <param name="value">Value to be displayed</param>
|
||||
public void UpdateUI(string sParam, int iParam, double value)
|
||||
{
|
||||
if (sParam == "ReservoirTemp")
|
||||
{
|
||||
controlCom.SetReservoirTemp(iParam, (float)value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public CBoard()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public CBoard(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
controlBoardCfg = cfg as ControlBoardCfg;
|
||||
|
||||
/// Buffers used in UnwrapPulses() and PulsesWM(wmNr1)
|
||||
unwrappedWMPulses = new int[Config.Data.WMsCount + 1];
|
||||
|
||||
cbCommandQueue = new Queue<SendCommandArgs>();
|
||||
lastSentFilters = new uint[FiltersCount];
|
||||
|
||||
#if DN100 || MUNICH || FUZHOU_150
|
||||
FMFreq = new float[2] { 0, 0 }; /// Nr. of pumps: Fuzhou150=2, Fuzhou300=6, newer=6
|
||||
#elif SLM_END || WARSAW_END
|
||||
FMFreq = new float[4] { 0, 0, 0, 0 };
|
||||
#else /// all newer benches
|
||||
FMFreq = new float[6] { 0, 0, 0, 0, 0, 0 };
|
||||
#endif
|
||||
emergencyStop = false;
|
||||
previousEmergencyStop = false;
|
||||
|
||||
routeMask = 0;
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
if (i < controlBoardCfg.VirtualValvesRangeLo || i > controlBoardCfg.VirtualValvesRangeHi)
|
||||
{
|
||||
routeMask = routeMask | ((UInt128)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specific pre-initialization for control board only
|
||||
/// </summary>
|
||||
/// <param name="eldeComponent"></param>
|
||||
public void SpecifyInvertedValves(UInt128 valvesToInvert)
|
||||
{
|
||||
this.valvesToInvert = valvesToInvert;
|
||||
this.benchModelRoute = valvesToInvert;
|
||||
|
||||
if (controlBoardCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
controlCom = new ControlComSim();
|
||||
}
|
||||
else
|
||||
{
|
||||
// controlCom = new ControlComWrap(eldeComponent);
|
||||
|
||||
/// Default number of scales (and BalanceRange length) is 2.
|
||||
/// If there are more scales, BalanceRange length is larger.
|
||||
// int scalesCnt = Math.Max(2, tankCapacities.Length);
|
||||
// BalanceRange = new uint[scalesCnt];
|
||||
// for (int i = 0; i < scalesCnt; i++)
|
||||
// {
|
||||
// BalanceRange[i] = (uint)((i < tankCapacities.Length) ? tankCapacities[i] : 0);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Initialize this device</summary>
|
||||
public void Initialize()
|
||||
{
|
||||
int divertersCount = Rig.Elde.Diverter.Diverter.DivertersCount;
|
||||
|
||||
DiverterEdge = new uint[divertersCount];
|
||||
for (int i = 0; i < divertersCount; i++)
|
||||
{
|
||||
DiverterEdge[i] = (uint)Rig.Elde.Diverter.Diverter.Diverters[i].ThresholdGate;
|
||||
controlCom.SetDivLimit(i, (uint)Rig.Elde.Diverter.Diverter.Diverters[i].ThresholdLo,
|
||||
(uint)Rig.Elde.Diverter.Diverter.Diverters[i].ThresholdHi);
|
||||
}
|
||||
|
||||
controlCom.SendCalibData(RegValveCalib,
|
||||
MeretRS485Address,
|
||||
controlBoardCfg.ComPortNr,
|
||||
TempCalibData,
|
||||
EtCalib,
|
||||
DiverterEdge,
|
||||
BalanceRange,
|
||||
MeretProtocol);
|
||||
|
||||
log.FatalFormat("Successfully initialized device {0}", ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run this device
|
||||
/// </summary>
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if (DebugLevel == DebugMode.Simulate) return;
|
||||
controlCom.RunDeviceBefore();
|
||||
UnwrapPulses();
|
||||
}
|
||||
|
||||
///
|
||||
/// Used in RunDeviceAfter() when sending commands
|
||||
///
|
||||
UInt128 lastSentRoute;
|
||||
uint[] lastSentFilters;
|
||||
float[] lastSentFMFreq;
|
||||
int lastsentRegConst;
|
||||
int lastSentShortImp;
|
||||
|
||||
/// <summary>
|
||||
/// Run this device
|
||||
/// </summary>
|
||||
public void RunDeviceAfter()
|
||||
{
|
||||
if (DebugLevel == DebugMode.Simulate) return;
|
||||
|
||||
|
||||
previousEmergencyStop = emergencyStop;
|
||||
emergencyStop = (controlCom.StatusP & StatusP.EmgcyStopActive) != 0;
|
||||
///
|
||||
if (emergencyStop)
|
||||
{
|
||||
/// Modify the queue in case of an emergency stop
|
||||
cbCommandQueue.Clear();
|
||||
cbCommandQueue.Enqueue(new SendCommandArgs(Command.Stop, 0, 0, 0, 0, StopDevs.All));
|
||||
}
|
||||
///
|
||||
if (emergencyStop && !previousEmergencyStop)
|
||||
{
|
||||
/// Stop the cycle - Press 'STOP' button in the BenchControlPanel
|
||||
TBF.UiBridge.Bridge.Ui2Bench(TBF.UiBridge.UI2BenchCmd.Stop);
|
||||
|
||||
Program.MainWnd.Invoke(new ShowEmergencyStopFormDlgt(ShowEmergencyStopForm));
|
||||
}
|
||||
else if (!emergencyStop && previousEmergencyStop)
|
||||
{
|
||||
UiBridge.Bridge.OnEmergencyStopChanged(this, UiBridge.EmergencyStopEventArgs.State.CloseForm);
|
||||
}
|
||||
|
||||
|
||||
UpdateWeights();
|
||||
|
||||
|
||||
/// Prepare uintFilters array and evaluate changes
|
||||
uint[] uintFilters = new uint[FiltersCount];
|
||||
uintFilters[0] = (filters != null && filters.Length > 0) ? (uint)filters[0] : 0;
|
||||
bool filtersAreDifferent = (uintFilters[0] != lastSentFilters[0]);
|
||||
for (int i = 1; i < FiltersCount; i++)
|
||||
{
|
||||
uintFilters[i] = (filters != null && filters.Length > i) ? (uint)filters[i] : uintFilters[i - 1];
|
||||
filtersAreDifferent |= (uintFilters[i] != lastSentFilters[i]);
|
||||
}
|
||||
|
||||
/// Evaluate FMFreq changes
|
||||
bool fmFreqsAreDifferent = false;
|
||||
if ((FMFreq == null) || (lastSentFMFreq == null) || (FMFreq.Length != lastSentFMFreq.Length))
|
||||
{
|
||||
fmFreqsAreDifferent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < FMFreq.Length; i++)
|
||||
{
|
||||
if (FMFreq[i] != lastSentFMFreq[i])
|
||||
{
|
||||
fmFreqsAreDifferent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cbCommandQueue.Count > 0)
|
||||
{
|
||||
///
|
||||
/// There is a command in the queue
|
||||
///
|
||||
controlCom.SendCommand(cbCommandQueue.Dequeue(), (benchModelRoute & routeMask), uintFilters, FMFreq, regConst, shortImp);
|
||||
|
||||
lastSentRoute = (benchModelRoute & routeMask);
|
||||
lastsentRegConst = regConst;
|
||||
lastSentShortImp = shortImp;
|
||||
|
||||
/// Deep copy of arrays lastSentFilters and lastSentFMFreq
|
||||
if ((lastSentFilters == null) || (lastSentFilters.Length != uintFilters.Length)) lastSentFilters = new uint[(uintFilters == null) ? 0 : uintFilters.Length];
|
||||
for (int i = 0; i < lastSentFilters.Length; i++) lastSentFilters[i] = uintFilters[i];
|
||||
if ((lastSentFMFreq == null) || (lastSentFMFreq.Length != FMFreq.Length)) lastSentFMFreq = new float[(FMFreq == null) ? 0 : FMFreq.Length];
|
||||
for (int i = 0; i < lastSentFMFreq.Length; i++) lastSentFMFreq[i] = FMFreq[i];
|
||||
}
|
||||
else if (((benchModelRoute & routeMask) != lastSentRoute) ||
|
||||
filtersAreDifferent ||
|
||||
fmFreqsAreDifferent ||
|
||||
(lastsentRegConst != regConst) ||
|
||||
(lastSentShortImp != shortImp))
|
||||
{
|
||||
///
|
||||
/// Command queue is mepty, but 'route', pump frequency, PID coef., filters or shortImp have changed
|
||||
///
|
||||
controlCom.SendCommand(new SendCommandArgs(Command.None, 0, 0, 0, 0, 0), (benchModelRoute & routeMask), uintFilters, FMFreq, regConst, shortImp);
|
||||
|
||||
lastSentRoute = (benchModelRoute & routeMask);
|
||||
lastsentRegConst = regConst;
|
||||
lastSentShortImp = shortImp;
|
||||
|
||||
/// Deep copy of arrays lastSentFilters and lastSentFMFreq
|
||||
if ((lastSentFilters == null) || (lastSentFilters.Length != uintFilters.Length)) lastSentFilters = new uint[(uintFilters == null) ? 0 : uintFilters.Length];
|
||||
for (int i = 0; i < lastSentFilters.Length; i++) lastSentFilters[i] = uintFilters[i];
|
||||
if ((lastSentFMFreq == null) || (lastSentFMFreq.Length != FMFreq.Length)) lastSentFMFreq = new float[(FMFreq == null) ? 0 : FMFreq.Length];
|
||||
for (int i = 0; i < lastSentFMFreq.Length; i++) lastSentFMFreq[i] = FMFreq[i];
|
||||
}
|
||||
|
||||
controlCom.RunDeviceAfter();
|
||||
}
|
||||
|
||||
/// <summary>Stop this device</summary>
|
||||
public void StopDevice() { }
|
||||
public void StopDevice2() { }
|
||||
|
||||
|
||||
delegate void ShowEmergencyStopFormDlgt();
|
||||
///
|
||||
void ShowEmergencyStopForm()
|
||||
{
|
||||
(new TBF.UI.Shared.EmergencyStopForm()).Show();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the control board.
|
||||
/// </summary>
|
||||
/// <param name="cmd">See ControlBoard.Command enum</param>
|
||||
/// <param name="refFlowmtrNr">Number of the etalon/reference (1..5)</param>
|
||||
/// <param name="route">State of valves, 128-bit word</param>
|
||||
/// <param name="totalRefPulses">kolko impulzov ma trvat skuska</param>
|
||||
/// <param name="testMethods">See ControlBoard.TestMethods enum</param>
|
||||
/// <param name="filterConstant">0 = No filtering (0..255)</param>
|
||||
/// <param name="regConst">Coefficient used to control reg. valves (1..100)</param>
|
||||
/// <param name="shortImp">0 = default value, 1 = spec. processing of very short pulses</param>
|
||||
/// <param name="stopDevs">What to stop</param>
|
||||
public void SendCommand(Command cmd, int refFlowmtrNr, int totalRefPulses, int massRefPulses,
|
||||
TestMethods testMethods, StopDevs stopDevs)
|
||||
{
|
||||
cbCommandQueue.Enqueue(new SendCommandArgs(cmd, refFlowmtrNr, totalRefPulses, massRefPulses, testMethods, stopDevs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set valves to new positions.
|
||||
/// </summary>
|
||||
/// <param name="valvesToOpen">'ulong' with bits of valves to open set to '1'</param>
|
||||
/// <param name="valvesToClose">'ulong' with bits of valves to close set to '1'</param>
|
||||
/// <returns>'ulong' with bits of valves that have changed set to '1'</returns>
|
||||
public UInt128 SetValves(UInt128 valvesToOpen, UInt128 valvesToClose, IList<TBF.Rig.BuiltIn.ValveEx.Valve> extendedValves)
|
||||
{
|
||||
UInt128 oldRoute = benchModelRoute;
|
||||
benchModelRoute = (((benchModelRoute ^ valvesToInvert) | valvesToOpen) & (~valvesToClose)) ^ valvesToInvert;
|
||||
foreach (var extV in extendedValves) extV.UpdateRoute(ref benchModelRoute);
|
||||
log.DebugFormat("SetValves(x,x), new route = {0}", Utils.RouteToStr(benchModelRoute));
|
||||
return oldRoute ^ benchModelRoute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set Route to value returned by RRoute. Take virtual valves into account.
|
||||
/// </summary>
|
||||
/// <returns>'ulong' with bits of valves that have changed set to '1'</returns>
|
||||
public UInt128 SyncRoute()
|
||||
{
|
||||
UInt128 oldRoute = benchModelRoute;
|
||||
benchModelRoute = (RRoute & routeMask) | (benchModelRoute & (~routeMask));
|
||||
log.DebugFormat("SyncRoute(), new route = {0}", Utils.RouteToStr(benchModelRoute));
|
||||
return oldRoute ^ benchModelRoute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Regulation valves control.
|
||||
/// </summary>
|
||||
/// <param name="valveNo">Regulation valve nr. (1..5)</param>
|
||||
/// <param name="valveMode">Valve regulation mode, see the enum</param>
|
||||
/// <param name="valveValue">Target position or target frequency or pulse duration</param>
|
||||
/// <param name="stableTime">Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.</param>
|
||||
public void ValveMove(int valveNo, RegulValveMode valveMode, double[] valveValue, int stableTime)
|
||||
{
|
||||
controlCom.ValveMove(valveNo, valveMode, valveValue, stableTime);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Open one valve and/or close one valve.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="valveOpen">Valve to be opened</param>
|
||||
/// <param name="valveClose">Valve to be closed</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation SetValvesOp(IValve valveOpen, IValve valveClose)
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, valveOpen, valveClose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open and/or close multiple valves.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="valvesOpen">A list of valves to be opened</param>
|
||||
/// <param name="valvesClose">A list of valves to be closed</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation SetValvesOp(IList<IValve> valvesOpen, IList<IValve> valvesClose)
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, valvesOpen, valvesClose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open start/stop valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation OpenStartValveOp()
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, true, devices);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close start/stop valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation CloseStartValveOp()
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, false, devices);
|
||||
}
|
||||
|
||||
public IOperation SetFlowOp(double reqrdFlowLo, double reqrdFlowHi, TBF.Boxes.DoubleBox measuredFlow, int timeout)
|
||||
{
|
||||
if (Devices.RegValve == null || Devices.FlowMeter == null) return null;
|
||||
|
||||
return Devices.RegValve.SetFlowOp(Devices.FlowMeter, reqrdFlowLo, reqrdFlowHi, measuredFlow, timeout);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Start a test, Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="iParam">Int32 parameter 1</param>
|
||||
/// <param name="dParam1">Double parameter 1 (alternative lower flow limit)</param>
|
||||
/// <param name="dParam2">Double parameter 2 (alternative upper flow limit)</param>
|
||||
/// <returns>Operation</returns>
|
||||
public IOperation StartTestOp(Test test, int iParam = 0, double dParam1 = 0, double dParam2 = 0)
|
||||
{
|
||||
if (controlBoardCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
return new Operations.ReturnGivenEventOp(Event.MeasurementStarted);
|
||||
}
|
||||
|
||||
/// Get total number of pulses
|
||||
int totalPulses = Convert.ToInt32(Math.Round(test.Volume / devices.FlowMeter.LtrPerPulse));
|
||||
|
||||
/// Get method class string
|
||||
string methodClass;
|
||||
if (!StateMachine.TestMethod2Class.TryGetValue(test.Name, out methodClass)) return null;
|
||||
|
||||
if (methodClass.Contains("TestMethods.Adjustment."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.CombinedWithDetection."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), dParam1, dParam2, totalPulses);
|
||||
}
|
||||
if (methodClass == "TestMethods.DiverterTest")
|
||||
{
|
||||
if (iParam == 0) return null;
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses / iParam);
|
||||
}
|
||||
if (methodClass == "TestMethods.Dummy")
|
||||
{
|
||||
}
|
||||
if (methodClass == "TestMethods.Endurance")
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FixedStart."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, 2 * totalPulses, 10);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FixedStartAdvanced."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, 2 * totalPulses, 10);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FixedStartDefferedEval."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, 2 * totalPulses, 10);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FixedStartMassCollDeferredEval."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, 2 * totalPulses, 10);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FixedStartMassCollection."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.FixedStart), test.Qfrom, test.Qto, 2 * totalPulses, 10);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FixedStartTankCollection."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, (totalPulses * 5 / 4), 10);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FlyingStart."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FlyingStartFirstRepetWithMassColl."))
|
||||
{
|
||||
TestMethods tm = (iParam == 1) ? (TestMethods.Diverter | TestMethods.Synchro) : TestMethods.Synchro;
|
||||
return new StartMeasurementOp(this, devices, tm, test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FlyingStartMassCollComparative."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FlyingStartMassCollection."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FlyingStartMassCollProlonged."))
|
||||
{
|
||||
if (iParam == 0) return null;
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses, iParam);
|
||||
}
|
||||
if (methodClass.Contains("TestMethods.FlyingStartTankCollection."))
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, (TestMethods.Diverter | TestMethods.Synchro), test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass == "TestMethods.PulsesTest")
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
if (methodClass == "TestMethods.PulsesTestManual")
|
||||
{
|
||||
return new StartMeasurementOp(this, devices, TestMethods.Synchro, test.Qfrom, test.Qto, totalPulses);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the measurement.
|
||||
/// Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flow meter</param>
|
||||
/// <param name="readers">An array of register readers</param>
|
||||
/// <param name="refPulses">Number of reference pulses to complete the test</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation StartProlongedMeasurementOp(OutputPath outputPath,
|
||||
double requiredFlowLo, double requiredFlowHi,
|
||||
int totalRefPulses, int massRefPulses, int delayBeforeFlowRegulation = 0)
|
||||
{
|
||||
if (controlBoardCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
return new Operations.ReturnGivenEventOp(Event.MeasurementStarted);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new StartMeasurementOp(this, outputPath, TestMethods.Diverter | TestMethods.Synchro | TestMethods.MassAndContinue,
|
||||
requiredFlowLo, requiredFlowHi, totalRefPulses, massRefPulses, delayBeforeFlowRegulation);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read diverter samples from the control board and calculated the transition time.
|
||||
/// Events: Event.None
|
||||
/// </summary>
|
||||
/// <param name="div">Diverter</param>
|
||||
/// <param name="runsCountWhenSendingCmd">State machine ticks from test start/end when diverter read command is issued (obsolete)</param>
|
||||
/// <param name="runsCountWhenReadingDiv">State machine ticks from test start/end when diverter samples are read</param>
|
||||
/// <param name="transitionTimeSec">FloatBox for the resulting transition time in s</param>
|
||||
/// <param name="plotter">Statistics for plotting diverter transitions</param>
|
||||
/// <param name="batchNr">Batch number</param>
|
||||
/// <param name="testName">Test name (without repetitions)</param>
|
||||
/// <param name="repetition">Repetition number</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation ReadDiverterTransitionOp(bool isStart, Sequences.Statistics plotter, int batchNr, string testName, int repetition)
|
||||
{
|
||||
if (controlBoardCfg.DebugLevel == DebugMode.Simulate) return new Operations.ReturnGivenEventOp(Event.None);
|
||||
|
||||
return new ReadDiverterTransitionOp(this, devices.Diverter, 1, 3, isStart, plotter, batchNr, testName, repetition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries th econtrol board whether the measurement was completed.
|
||||
/// Events: MeasurementCompleted or None
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation QueryMeasurementEndOp()
|
||||
{
|
||||
return new QueryMeasurementEndOp(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop controls board flow regulation operation
|
||||
/// Events: FlowRegulationStopped
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation StopFlowRegulationOp()
|
||||
{
|
||||
return new StopFlowRegulationOp(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the previous control board operation (diverter, gate, etc.)
|
||||
/// Events: PreviousStopped
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation StopPreviousOp()
|
||||
{
|
||||
return new StopPreviousOp(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends commands to the control board.
|
||||
/// Events: Event.None, Event.CommandCompleted
|
||||
/// </summary>
|
||||
/// <param name="commandOnStartOp">Command sent to CB when this operation starts</param>
|
||||
/// <param name="commandOnStopOp">Command sent to CB when this operation stops</param>
|
||||
/// <param name="testMethod">Test method parameter</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation ExecuteCommandOp(Command commandOnStartOp, Command commandOnStopOp, TestMethods testMethod)
|
||||
{
|
||||
return new ExecuteCommandOp(this, commandOnStartOp, commandOnStopOp, testMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Dirichlet.Numerics;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class ControlComSim : IControlCom
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ControlComSim));
|
||||
public override string ToString() { return string.Format("ControlComSim"); }
|
||||
|
||||
StatusP statusP;
|
||||
public StatusP StatusP { get { return statusP; } }
|
||||
|
||||
double referenceFreq = 650.0;
|
||||
public double ReferenceFreq { get { return referenceFreq; } }
|
||||
public double ReferenceFreqs(int i) { return 0; }
|
||||
|
||||
int[] etPulses = new int[Config.Data.WMsCount + 1];
|
||||
public int EtPulses(int wmNr1)
|
||||
{
|
||||
return etPulses[wmNr1];
|
||||
}
|
||||
|
||||
public int EtPulsesK { get { return 1; } }
|
||||
public int EtPulses2 { get { return 0; } }
|
||||
public int EtPulses3 { get { return 0; } }
|
||||
|
||||
double[] errFactor = new double[Config.Data.WMsCount + 1]; /// Internal
|
||||
double[] wMeterPulsesF = new double[Config.Data.WMsCount + 1]; /// Internal
|
||||
|
||||
UInt16[] wMeterPulses = new UInt16[Config.Data.WMsCount + 1]; /// Rounded from wMeterPulsesF
|
||||
public UInt16 WMeterPulses(int wmNr1)
|
||||
{
|
||||
return wMeterPulses[wmNr1];
|
||||
}
|
||||
|
||||
int[] wMeterReference = new int[Config.Data.WMsCount + 1];
|
||||
public int WMeterReference(int wmNr1)
|
||||
{
|
||||
return wMeterReference[wmNr1];
|
||||
}
|
||||
|
||||
public uint RegulValveDAC(int rvNr0) { return 0; }
|
||||
|
||||
public float Pressure(int prsNr0) { return 0; }
|
||||
public float Temperature(int tmpNr0) { return (float)(20 + tmpNr0); }
|
||||
public RegulValveState RegulValveState(int rvNr1) { return 0; }
|
||||
|
||||
public UInt128 RRoute { get { return simRoute; } }
|
||||
|
||||
public uint DivTime(int id) { return 0; }
|
||||
public void SetDivLimit(int divNo, uint limLoPct, uint limHiPct) { }
|
||||
|
||||
float tTime = 1;
|
||||
public float TTime { get { return tTime; } }
|
||||
public float ImpulseTime(int wmNr1) { return tTime; }
|
||||
|
||||
public uint FmState { get { return 0; } }
|
||||
public uint BeginState(int wmNr0) { return 0; }
|
||||
|
||||
double referenceFlow;
|
||||
public double ReferenceFlow { get { return referenceFlow; } }
|
||||
|
||||
public float RValvePosition(int rvNr1) { return 0; }
|
||||
public float DivSamples(int ms, int divIx0) { return 0; }
|
||||
public int ScopeSamples(int i, int j, int k) { return 0; }
|
||||
public ulong DigitalInputs { get { return 0; } }
|
||||
public float AnalogInput(int adcNr0) { return 0; }
|
||||
public uint AnalogInputRaw(int adcNr0, int bank) { return 0; } /// bank0=RV, bank1=Temp
|
||||
public float TotalRefVolume { get { return 0; } }
|
||||
public float VyslExt(int wmNr0, int what) { return 0; }
|
||||
public void SetWeight(int pos, double mass) { return; } /// not available in sim. mode
|
||||
|
||||
public uint[] CyclePar { get { return cyclePar; } set { cyclePar = value; } } /// dummy
|
||||
public uint[] WMeterCont { get { return wMeterCont; } } /// dummy
|
||||
|
||||
public float ValveOpenCloseTime { get { return 0.001f; } }
|
||||
///
|
||||
public bool ManualUIAllowed
|
||||
{
|
||||
get { return manualUIAllowed; }
|
||||
set { manualUIAllowed = value; }
|
||||
}
|
||||
bool manualUIAllowed = true;
|
||||
|
||||
public void SetReservoirTemp(int nr, float temp) { }
|
||||
|
||||
|
||||
///
|
||||
/// Private initialization data updated by contructors of children components
|
||||
/// and sent to 'controlCom2panel' by SendCalibData() method.
|
||||
///
|
||||
uint[,] regValveCalib;
|
||||
byte[] meretRS485Address;
|
||||
float[,] tempCalibData;
|
||||
float[] etCalib;
|
||||
uint[] diverterEdge;
|
||||
uint[] balanceRange;
|
||||
byte meretProtocol;
|
||||
|
||||
|
||||
uint[] cyclePar;
|
||||
uint[] wMeterCont;
|
||||
|
||||
///
|
||||
/// Private values set by SendCommand()
|
||||
///
|
||||
Command cmd;
|
||||
int refFlowmtrNr;
|
||||
UInt128 simRoute;
|
||||
int totalRefPulses;
|
||||
int massRefPulses;
|
||||
TestMethods testMethods;
|
||||
uint[] filterConstants;
|
||||
float[] FMFreq;
|
||||
int regConst;
|
||||
int shortImp;
|
||||
StopDevs stopDevs;
|
||||
|
||||
///
|
||||
/// Private values set by ValveMove()
|
||||
///
|
||||
int regulValveNo;
|
||||
RegulValveMode regulValveMode;
|
||||
double[] regulValveValue;
|
||||
|
||||
Random rand;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public ControlComSim()
|
||||
{
|
||||
rand = new Random();
|
||||
cyclePar = new uint[163];
|
||||
wMeterCont = new uint[3] { 1, 2, 3 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends calibration and configuration data to the control board.
|
||||
/// </summary>
|
||||
/// <param name="rvCalib">Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2</param>
|
||||
/// <param name="meretA">Meret address, index = 0..1, value typ. 99 and 100</param>
|
||||
/// <param name="usedCom">COM port number of the control board (typ. 1)</param>
|
||||
/// <param name="tempCalib">Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr</param>
|
||||
/// <param name="etCalib">Etalon nominal values</param>
|
||||
/// <param name="divEdge">Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%)</param>
|
||||
public void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol)
|
||||
{
|
||||
log.Info("SendCalibData(...)");
|
||||
|
||||
this.regValveCalib = rvCalib;
|
||||
this.meretRS485Address = meretA;
|
||||
this.tempCalibData = tempCalib;
|
||||
this.etCalib = etCalib;
|
||||
this.diverterEdge = divEdge;
|
||||
this.balanceRange = balanceRange;
|
||||
this.meretProtocol = meretProtocol;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a command to the control board.
|
||||
/// </summary>
|
||||
/// <param name="cmd">See ControlBoard.Command enum</param>
|
||||
/// <param name="refFlowmtrNr">Number of the etalon/reference (1..5)</param>
|
||||
/// <param name="route">State of valves, 128-bit word</param>
|
||||
/// <param name="refPulses">kolko impulzov ma trvat skuska</param>
|
||||
/// <param name="testMethods">See ControlBoard.TestMethods enum</param>
|
||||
/// <param name="filterConstant">0 = No filtering (0..255)</param>
|
||||
/// <param name="fmFreq">Freq.inverter control (not applicable in DT100, Munich)</param>
|
||||
/// <param name="regConst">Coefficient used to control reg. valves (1..100)</param>
|
||||
/// <param name="shortImp">0 = default value, 1 = spec. processing of very short pulses</param>
|
||||
/// <param name="stopDevs">What to stop</param>
|
||||
public void SendCommand(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp)
|
||||
{
|
||||
log.InfoFormat("SendCommand(Cmd={0},Ref#={1},Route={2} {3} {4} {5},TotalPls={6},MassPls={7},TstM={8},filt={9},FM=[{10}{11}{12}{13}{14}{15}],Reg={16},ShrtImp={17},Stop={18})",
|
||||
sendCommandArgs.Cmd, sendCommandArgs.RefFlowmtrNr, /// 0, 1
|
||||
((route >> 48) & 0xFFFF).ToString("X4"), /// 2
|
||||
((route >> 32) & 0xFFFF).ToString("X4"), /// 3
|
||||
((route >> 16) & 0xFFFF).ToString("X4"), /// 4
|
||||
(route & 0xFFFF).ToString("X4"), /// 5
|
||||
totalRefPulses, massRefPulses, testMethods, filterConstants, /// 6, 7, 8, 9
|
||||
fmFreq[0].ToString(), /// 10
|
||||
(fmFreq.Length > 1) ? ("," + fmFreq[1].ToString()) : "", /// 11
|
||||
(fmFreq.Length > 2) ? ("," + fmFreq[2].ToString()) : "", /// 12
|
||||
(fmFreq.Length > 3) ? ("," + fmFreq[3].ToString()) : "", /// 13
|
||||
(fmFreq.Length > 4) ? ("," + fmFreq[4].ToString()) : "", /// 14
|
||||
(fmFreq.Length > 5) ? ("," + fmFreq[5].ToString()) : "", /// 15
|
||||
regConst, shortImp, stopDevs); /// 16, 17, 18
|
||||
///
|
||||
/// Simulation
|
||||
///
|
||||
Command lastCmd = this.cmd;
|
||||
this.cmd = sendCommandArgs.Cmd;
|
||||
this.refFlowmtrNr = sendCommandArgs.RefFlowmtrNr;
|
||||
|
||||
#if FUZHOU_300
|
||||
///
|
||||
/// The following code deals with the situation that all FM controlled pums share bit #39.
|
||||
/// In settings the bits of pumps should be sent as follows: P1=50, P2=51, P3=52, P4=53, P5=54 and P7=55
|
||||
/// (in FUZHOU_300 the FM pump bit should be set set to value FMIndex+50).
|
||||
///
|
||||
bool bit39 = (route & 0x00FC000000000000) != 0; /// true if any of bits 50 through 55 is set
|
||||
route = route & 0xFF03FFFFFFFFFFFF;
|
||||
if (bit39) route = route | 0x0000008000000000;
|
||||
log.DebugFormat("SendCommand route = {0}", Utils.RouteToStr(route));
|
||||
#endif
|
||||
TestBenchSim.SimRoute = this.simRoute = route;
|
||||
this.totalRefPulses = sendCommandArgs.TotalRefPulses;
|
||||
this.massRefPulses = sendCommandArgs.MassRefPulses;
|
||||
this.testMethods = sendCommandArgs.TestMethods;
|
||||
this.stopDevs = sendCommandArgs.StopDevs;
|
||||
this.filterConstants = filterConstants;
|
||||
this.FMFreq = fmFreq;
|
||||
this.regConst = regConst;
|
||||
this.shortImp = shortImp;
|
||||
|
||||
#pragma warning disable
|
||||
statusP = (StatusP)(((ulong)statusP & (ulong)0xFFFFFFFFFFFFFFF8L) | (ulong)refFlowmtrNr);
|
||||
#pragma warning restore
|
||||
|
||||
if (cmd == Command.Start && lastCmd != Command.Start )
|
||||
{
|
||||
statusP |= StatusP.TestInProgress;
|
||||
///
|
||||
/// Clear all counters
|
||||
///
|
||||
if (etPulses != null) { for (int i = 0; i < etPulses.Length; i++) etPulses[i] = 0; }
|
||||
if (wMeterPulses != null) { for (int i = 0; i < wMeterPulses.Length; i++) wMeterPulses[i] = 0; }
|
||||
if (wMeterPulsesF != null) { for (int i = 0; i < wMeterPulsesF.Length; i++) wMeterPulsesF[i] = 0; }
|
||||
if (wMeterReference != null) { for (int i = 0; i < wMeterReference.Length; i++) wMeterReference[i] = 0; }
|
||||
if (errFactor != null)
|
||||
{
|
||||
for (int i = 0; i < errFactor.Length; i++) errFactor[i] = ((float)rand.Next(100) + 950.0f) / 1000.0f;
|
||||
}
|
||||
tTime = 0;
|
||||
}
|
||||
else if (cmd == Command.Stop)
|
||||
{
|
||||
statusP = 0;
|
||||
//statusP &= ~StatusP.Running;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Control of regulating valves.
|
||||
/// </summary>
|
||||
/// <param name="regulValveNo">Regulating valve nr. (1..5)</param>
|
||||
/// <param name="regulValveMode">???</param>
|
||||
/// <param name="regulValveValue">???</param>
|
||||
/// <param name="stableTime">Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.</param>
|
||||
public void ValveMove(int regulValveNo, RegulValveMode regulValveMode, double[] regulValveValue, int stableTime)
|
||||
{
|
||||
log.InfoFormat("ValveMove({0}, {1}, [{2},{3}], {4})", regulValveNo, regulValveMode, regulValveValue[0], regulValveValue[1], stableTime);
|
||||
|
||||
this.regulValveNo = regulValveNo;
|
||||
this.regulValveMode = regulValveMode;
|
||||
this.regulValveValue = regulValveValue;
|
||||
}
|
||||
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
log.DebugFormat("RunDeviceBefore() ... regV#={0}, flowM#{1}, statusP={2}", regulValveNo, refFlowmtrNr, statusP.ToString("X"));
|
||||
TestBenchSim.RunDevice(regulValveNo, refFlowmtrNr, statusP);
|
||||
|
||||
log.DebugFormat("refFreq={0}", referenceFreq);
|
||||
|
||||
tTime += 1.0f;
|
||||
|
||||
float Qnom = (regulValveNo > 0) ? etCalib[regulValveNo] : 0;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case Command.None:
|
||||
break;
|
||||
|
||||
case Command.Start:
|
||||
if ((testMethods & TestMethods.Diverter) == TestMethods.Diverter)
|
||||
{
|
||||
TestBenchSim.SetSimDiverter(true);
|
||||
}
|
||||
break;
|
||||
|
||||
case Command.Stop:
|
||||
if ((testMethods & TestMethods.Diverter) == TestMethods.Diverter)
|
||||
{
|
||||
TestBenchSim.SetSimDiverter(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (regulValveMode)
|
||||
{
|
||||
case RegulValveMode.TargetFrequency:
|
||||
double targetFlow = ((regulValveValue[0] + regulValveValue[1]) / 2.0) * (Qnom / 2000.0);
|
||||
TestBenchSim.UpdateSimFlow(targetFlow);
|
||||
|
||||
//if (referenceFreq < valveValue[0]) referenceFreq += ((float)rand.Next(20) + 10.0f) / 2.0f;
|
||||
//else if (referenceFreq > valveValue[1]) referenceFreq -= ((float)rand.Next(20) + 10.0f) / 2.0f;
|
||||
//else referenceFreq += ((float)rand.Next(10) - 5.0f) / 2.0f;
|
||||
referenceFreq = TestBenchSim.GetSimFlow() * 2000.0 / Qnom;
|
||||
if (referenceFreq < 0) referenceFreq = 0;
|
||||
if (referenceFreq > 2500) referenceFreq = 2500;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
referenceFlow = referenceFreq / 2000.0;
|
||||
|
||||
bool stopTest = false;
|
||||
if (cmd == Command.Start)
|
||||
{
|
||||
double pwFactor = 1.0;
|
||||
|
||||
/// Increment reference flow meters
|
||||
for (int i = 0; i <= Config.Data.WMsCount; i++)
|
||||
{
|
||||
etPulses[i] += (int)referenceFreq;
|
||||
if (etPulses[i] > totalRefPulses)
|
||||
{
|
||||
pwFactor = 1.0 - (etPulses[i] - totalRefPulses) / referenceFreq;
|
||||
etPulses[i] = totalRefPulses;
|
||||
stopTest = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Increment water meters
|
||||
double flowLtrPerSec = TestBenchSim.GetSimFlow() / 1800.0;
|
||||
for (int i = 1; i <= Config.Data.WMsCount; i++)
|
||||
{
|
||||
float wmPulsesPerLiter = 0;
|
||||
if ((Rig.Sequences.ProcessData.RegisterReaders[i - 1] != null) &&
|
||||
(Rig.Sequences.ProcessData.BatchRslts.Batch.WaterMeters.Count >= i) &&
|
||||
(Rig.Sequences.ProcessData.BatchRslts.Batch.WaterMeters[i - 1] != null))
|
||||
{
|
||||
wmPulsesPerLiter = (float)Rig.Sequences.ProcessData.RegisterReaders[i-1].PulsesPerLtr;
|
||||
}
|
||||
wMeterPulsesF[i] += errFactor[i] * pwFactor * ((float)rand.Next(100) + 450.0f) * wmPulsesPerLiter * flowLtrPerSec;
|
||||
wMeterPulses[i] = (UInt16)wMeterPulsesF[i];
|
||||
}
|
||||
|
||||
if (etPulses[0] > totalRefPulses)
|
||||
{
|
||||
statusP |= StatusP.TestCompleted;
|
||||
statusP &= ~StatusP.TestInProgress;
|
||||
}
|
||||
}
|
||||
|
||||
if (stopTest)
|
||||
{
|
||||
TestBenchSim.SetSimDiverter(false);
|
||||
statusP = (statusP | StatusP.TestCompleted);
|
||||
statusP = (statusP & ~StatusP.TestInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
StatusP lastStatusP;
|
||||
UInt128 lastRoute;
|
||||
|
||||
public void RunDeviceAfter()
|
||||
{
|
||||
StatusP bufferedStatusP = StatusP;
|
||||
if (lastStatusP != bufferedStatusP)
|
||||
{
|
||||
string statusPStr = ((ulong)bufferedStatusP).ToString("x16");
|
||||
log.InfoFormat("RunDeviceAfter() StatusP = {0}", statusPStr);
|
||||
Program.MainWnd.UpdateStatusP(statusPStr);
|
||||
lastStatusP = bufferedStatusP;
|
||||
}
|
||||
|
||||
UInt128 bufferedRoute = simRoute;
|
||||
if (lastRoute != bufferedRoute)
|
||||
{
|
||||
string routeStr = bufferedRoute.ToString("x16");
|
||||
log.InfoFormat("RunDeviceAfter() Route = {0}", routeStr);
|
||||
Program.MainWnd.UpdateRoute(routeStr);
|
||||
lastRoute = bufferedRoute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
///
|
||||
/// Copyright (c) 2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class ExecuteCommandOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ExecuteCommandOp));
|
||||
public override string ToString() { return string.Format("ExecuteCommandOp( command={0}, testMethod={1} )", commandOnStartOp, testMethod); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
readonly Command commandOnStartOp;
|
||||
readonly Command commandOnStopOp;
|
||||
readonly TestMethods testMethod;
|
||||
|
||||
bool started = false;
|
||||
|
||||
///
|
||||
/// Internal states of this operation
|
||||
///
|
||||
enum OpState
|
||||
{
|
||||
StartingCommand,
|
||||
CommandStarted,
|
||||
OpCompleted,
|
||||
}
|
||||
OpState opState;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Starts the measurement.
|
||||
/// Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="controlBoard">Control board component reference</param>
|
||||
/// <param name="outputPath">Specifies used components</param>
|
||||
/// <param name="testMethod">Test method</param>
|
||||
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
|
||||
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
|
||||
public ExecuteCommandOp(CBoard controlBoard, Command commandOnStartOp, Command commandOnStopOp, TestMethods testMethod)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("controlBoardDev");
|
||||
|
||||
this.controlBoard = controlBoard;
|
||||
this.commandOnStartOp = commandOnStartOp;
|
||||
this.commandOnStopOp = commandOnStopOp;
|
||||
this.testMethod = testMethod;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
controlBoard.SyncRoute();
|
||||
controlBoard.SendCommand(commandOnStartOp, 0, 0, 0, testMethod, StopDevs.None);
|
||||
opState = OpState.StartingCommand;
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.FlowInDone or Event.FlowOutDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (opState == OpState.StartingCommand)
|
||||
{
|
||||
StatusP statusP = controlBoard.StatusP;
|
||||
log.DebugFormat("statusP = {0} {1} {2} {3}",
|
||||
(((ulong)statusP >> 48) & 0xFFFF).ToString("X4"),
|
||||
(((ulong)statusP >> 32) & 0xFFFF).ToString("X4"),
|
||||
(((ulong)statusP >> 16) & 0xFFFF).ToString("X4"),
|
||||
((ulong)statusP & 0xFFFF).ToString("X4"));
|
||||
|
||||
log.Info("Run() - StartingCommand");
|
||||
opState = OpState.CommandStarted;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.CommandStarted)
|
||||
{
|
||||
log.InfoFormat("Run() - CommandStarted");
|
||||
opState = OpState.OpCompleted;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.OpCompleted)
|
||||
{
|
||||
return Event.CommandCompleted;
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (commandOnStopOp != Command.None)
|
||||
{
|
||||
controlBoard.SyncRoute();
|
||||
controlBoard.SendCommand(commandOnStopOp, 0, 0, 0, testMethod, StopDevs.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
/// <summary>Max. number of components of this class in the system</summary>
|
||||
public int MaxCount { get { return 1; } }
|
||||
|
||||
public IComponent DummyComponent() { return new CBoard(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new CBoard(cfg); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ControlBoardCfg(this); }
|
||||
|
||||
public IComponentCfgCtrl CreateCfgCtrl() { return new ControlBoardCfgCtrl(); }
|
||||
|
||||
public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList<Generic.IComponent> components)
|
||||
{
|
||||
return new CBoard((ControlBoardCfg)config);
|
||||
}
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ControlBoardCfg.Serializer, component, this);
|
||||
}
|
||||
|
||||
public void ResetStaticProperties() { CBoard.ResetStaticProperties(); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using Dirichlet.Numerics;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
interface IControlCom
|
||||
{
|
||||
StatusP StatusP { get; }
|
||||
int EtPulses(int wmNr1);
|
||||
int EtPulsesK { get; }
|
||||
int EtPulses2 { get; }
|
||||
int EtPulses3 { get; }
|
||||
UInt16 WMeterPulses(int wmNr1);
|
||||
int WMeterReference(int wmNr0);
|
||||
uint RegulValveDAC(int rvNr0);
|
||||
float Pressure(int prsNr0);
|
||||
float Temperature(int tmpNr0);
|
||||
RegulValveState RegulValveState(int rvNr1);
|
||||
UInt128 RRoute { get; }
|
||||
uint DivTime(int id); /// 50% id=0, 10% id=1, 90% id=2
|
||||
float TTime { get; }
|
||||
float ImpulseTime(int WMNr1);
|
||||
uint FmState { get; }
|
||||
uint BeginState(int wmNr0);
|
||||
double ReferenceFreq { get; }
|
||||
double ReferenceFreqs(int i); /// Frequences for doble/tripple flowmeter
|
||||
double ReferenceFlow { get; }
|
||||
float RValvePosition(int rvNr1);
|
||||
float DivSamples(int time, int divIx0); /// time unit is 2 ms
|
||||
int ScopeSamples(int i, int j, int k);
|
||||
ulong DigitalInputs { get; }
|
||||
float AnalogInput(int adcNr0);
|
||||
uint AnalogInputRaw(int adcNr0, int bank);
|
||||
float TotalRefVolume { get; }
|
||||
float VyslExt(int wmNr0, int what);
|
||||
void SetWeight(int pos, double mass);
|
||||
uint[] CyclePar { get; set; }
|
||||
uint[] WMeterCont { get; }
|
||||
bool ManualUIAllowed { get; set; }
|
||||
float ValveOpenCloseTime { get; }
|
||||
void SetDivLimit(int divNr, uint limLoPct, uint limHiPct);
|
||||
|
||||
void SetReservoirTemp(int nr, float temp);
|
||||
|
||||
/// <summary>
|
||||
/// Sends calibration and configuration data to the control board.
|
||||
/// </summary>
|
||||
/// <param name="rvCalib">Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2</param>
|
||||
/// <param name="meretA">Meret address, index = 0..1, value typ. 99 and 100</param>
|
||||
/// <param name="usedCom">COM port number of the control board (typ. 1)</param>
|
||||
/// <param name="tempCalib">Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr</param>
|
||||
/// <param name="etCalib">Etalon nominal values</param>
|
||||
/// <param name="divEdge">Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%)</param>
|
||||
/// <param name="balanceRange">TODO</param>
|
||||
/// <param name="meretProtocol">TODO</param>
|
||||
void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a command that is regularly sent to the control board by SendCommand.
|
||||
/// </summary>
|
||||
/// <param name="sendCommandArgs">Arguments, see SendCommandArgs class</param>
|
||||
/// <param name="route">State of valves, 128-bit word</param>
|
||||
/// <param name="filterConstants">Array with length=8 of filter costants (0..255, 0 = no filtering)</param>
|
||||
/// <param name="fmFreq">Freq.inverter control (not applicable in DT100, Munich)</param>
|
||||
/// <param name="regConst">PID coefficient for flow control</param>
|
||||
/// <param name="shortImp">0 = default value, 1 = spec. processing of very short pulses</param>
|
||||
void SendCommand(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp);
|
||||
|
||||
/// <summary>
|
||||
/// Control of regulating valves.
|
||||
/// </summary>
|
||||
/// <param name="valveNo">Regulating valve nr. (1..5)</param>
|
||||
/// <param name="valveMode">???</param>
|
||||
/// <param name="valveValue">???</param>
|
||||
/// <param name="stableTime">Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.</param>
|
||||
void ValveMove(int valveNo, RegulValveMode valveMode, double[] valveValue, int stableTime);
|
||||
|
||||
void RunDeviceBefore();
|
||||
void RunDeviceAfter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class QueryMeasurementEndOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(QueryMeasurementEndOp));
|
||||
public override string ToString() { return string.Format("QueryMeasurementEndOp()"); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
|
||||
bool done;
|
||||
|
||||
/// <summary>
|
||||
/// Events: MeasurementCompleted
|
||||
/// </summary>
|
||||
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
|
||||
public QueryMeasurementEndOp(CBoard controlBoardDev)
|
||||
{
|
||||
if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev");
|
||||
this.controlBoard = controlBoardDev;
|
||||
done = false;
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary> Start this operation </summary>
|
||||
public void Start()
|
||||
{
|
||||
done = false;
|
||||
}
|
||||
|
||||
/// <summary> Run this operation </summary>
|
||||
/// <returns>
|
||||
/// Event.FlowInDone or Event.FlowOutDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (done) return Event.MeasurementCompleted;
|
||||
|
||||
if (0 != (controlBoard.StatusP & StatusP.TestCompleted))
|
||||
{
|
||||
done = true;
|
||||
return Event.MeasurementCompleted;
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
/// <summary> Stop this operation </summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class ReadDiverterTransitionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ReadDiverterTransitionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("ReadDiverterTransitionOp(.,{0},{1},{2},...)", div.Name, runsCountWhenSendingCmd, runsCountWhenReadingDiv);
|
||||
}
|
||||
|
||||
const int SamplesCount = 240; /// Should be less then or equal to 256
|
||||
float[] samples;
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
readonly GenericDevices.IDiverter div;
|
||||
readonly bool toTank;
|
||||
readonly int runsCountWhenSendingCmd;
|
||||
readonly int runsCountWhenReadingDiv;
|
||||
readonly Sequences.Statistics plotter;
|
||||
readonly int batchNr;
|
||||
readonly string testName;
|
||||
readonly int repetition;
|
||||
|
||||
int counter;
|
||||
bool cmdSent = false;
|
||||
bool divRead = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Starts the measurement.
|
||||
/// Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="controlBoard">Control board component reference</param>
|
||||
/// <param name="outputPath">Specifies used components</param>
|
||||
/// <param name="method">Test method</param>
|
||||
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
|
||||
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
|
||||
public ReadDiverterTransitionOp(CBoard controlBoard, GenericDevices.IDiverter div, int runsCountWhenSendingCmd, int runsCountWhenReadingDiv, bool toTank,
|
||||
Sequences.Statistics plotter, int batchNr, string testName, int repetition)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("controlBoardDev");
|
||||
if (div == null) throw new ArgumentNullException("div");
|
||||
if (runsCountWhenSendingCmd < 0) throw new ArgumentNullException("runsCountWhenSendingCmd");
|
||||
if (runsCountWhenReadingDiv <= runsCountWhenSendingCmd) throw new ArgumentNullException("runsCountWhenReadingDiv");
|
||||
|
||||
this.controlBoard = controlBoard;
|
||||
this.div = div;
|
||||
this.runsCountWhenSendingCmd = runsCountWhenSendingCmd;
|
||||
this.runsCountWhenReadingDiv = runsCountWhenReadingDiv;
|
||||
this.toTank = toTank;
|
||||
this.plotter = plotter;
|
||||
this.batchNr = batchNr;
|
||||
this.testName = testName;
|
||||
this.repetition = repetition;
|
||||
|
||||
samples = new float[SamplesCount];
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
counter = 0;
|
||||
|
||||
if (runsCountWhenSendingCmd == 0 && div.DiverterNr > 0)
|
||||
{
|
||||
SendCommand();
|
||||
log.DebugFormat("Start() ... Sending a command to read diverter {0}", div.Name);
|
||||
}
|
||||
|
||||
if (plotter != null)
|
||||
{
|
||||
plotter.Start(batchNr, testName, repetition);
|
||||
log.DebugFormat("Start() ... plotter.Start({0}, {1}, {2})", batchNr, testName, repetition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.FlowInDone or Event.FlowOutDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
counter++;
|
||||
|
||||
if (counter == runsCountWhenSendingCmd && div.DiverterNr > 0)
|
||||
{
|
||||
SendCommand();
|
||||
log.DebugFormat("Run() ... Sending a command to read diverter {0}", div.Name);
|
||||
}
|
||||
else if (counter == runsCountWhenReadingDiv && div.DiverterNr > 0)
|
||||
{
|
||||
if (plotter == null)
|
||||
{
|
||||
ReadDiverterTransitionTimes();
|
||||
log.DebugFormat("Run() ... Reading diverter {0} transition times: {1}s", div.Name, (toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.DebugFormat("Run() ... Reading diverter {0} samples", div.Name);
|
||||
for (int i = 0; i < SamplesCount; i++)
|
||||
{
|
||||
float oneSample = controlBoard.DivSamples(i, div.DiverterNr - 1);
|
||||
samples[i] = oneSample;
|
||||
plotter.Update(oneSample);
|
||||
}
|
||||
plotter.Stop();
|
||||
|
||||
log.DebugFormat("Run() ... Calculating diverter {0} transition times: {1}s", div.Name, (toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val);
|
||||
CalculateDiverterTransitionTimes();
|
||||
}
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
log.DebugFormat("Stop()");
|
||||
}
|
||||
|
||||
void SendCommand()
|
||||
{
|
||||
controlBoard.SyncRoute();
|
||||
controlBoard.SendCommand(Command.ReadDivTransition, 0, 0, 0, 0, StopDevs.None);
|
||||
cmdSent = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Diverter transition time is read from the control board
|
||||
/// </summary>
|
||||
/// <returns>true (always)</returns>
|
||||
bool ReadDiverterTransitionTimes()
|
||||
{
|
||||
(toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val = (float)controlBoard.DivTime(2) - (float)controlBoard.DivTime(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Diverter transition time is calculated from ADC samples and threshold levels
|
||||
/// </summary>
|
||||
/// <returns>true when transition time calculated OK</returns>
|
||||
bool CalculateDiverterTransitionTimes()
|
||||
{
|
||||
bool startedRising = false;
|
||||
bool startedFalling = false;
|
||||
bool stopped = false;
|
||||
|
||||
int transitionStartIdx = 0;
|
||||
int transitionEndIdx = 0;
|
||||
|
||||
float level = samples[0];
|
||||
for (int i = 1; i < SamplesCount; i++)
|
||||
{
|
||||
if (!startedRising && !startedFalling)
|
||||
{
|
||||
if (level <= div.ThresholdLo && samples[i] > div.ThresholdLo)
|
||||
{
|
||||
transitionStartIdx = i;
|
||||
startedRising = true;
|
||||
}
|
||||
else if (level >= div.ThresholdHi && samples[i] < div.ThresholdHi)
|
||||
{
|
||||
transitionStartIdx = i;
|
||||
startedFalling = true;
|
||||
}
|
||||
}
|
||||
else if (startedRising && !stopped && level < div.ThresholdHi && samples[i] >= div.ThresholdHi)
|
||||
{
|
||||
transitionEndIdx = i;
|
||||
stopped = true;
|
||||
break;
|
||||
}
|
||||
else if (startedFalling && !stopped && level > div.ThresholdLo && samples[i] <= div.ThresholdLo)
|
||||
{
|
||||
transitionEndIdx = i;
|
||||
stopped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((startedRising || startedFalling) && stopped)
|
||||
{
|
||||
(toTank ? div.SwitchTimeStart : div.SwitchTimeEnd).Val = 0.002f * (float)(transitionEndIdx - transitionStartIdx); /// 2 ms per sample
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
///
|
||||
/// Copyright (c) 2017 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class ReadFlowOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ReadFlowOp));
|
||||
public override string ToString() { return string.Format("ReadFlowOp({0},.,.,{1})", flowMeter.Idx1, eventDone); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly GenericDevices.IFlowMeter flowMeter;
|
||||
readonly CBoard controlBoard;
|
||||
readonly DoubleBox flowBox;
|
||||
readonly Event eventDone;
|
||||
|
||||
/// <summary>
|
||||
/// Events: FlowInDone, FlowOutDone or Error
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flow meter reference</param>
|
||||
/// <param name="flowBox">Reference to the measured flow variable, value is in bar</param>
|
||||
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
|
||||
public ReadFlowOp(GenericDevices.IFlowMeter flowMeter, CBoard controlBoard, ref DoubleBox flowBox, Event eventDone)
|
||||
{
|
||||
if (flowMeter == null || controlBoard == null) throw new ArgumentNullException();
|
||||
|
||||
this.flowMeter = flowMeter;
|
||||
this.controlBoard = controlBoard;
|
||||
this.eventDone = eventDone;
|
||||
this.flowBox = flowBox;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
public ReadFlowOp(GenericDevices.IFlowMeter flowMeter, CBoard controlBoard, ref DoubleBox flowBox)
|
||||
: this(flowMeter, controlBoard, ref flowBox, Event.FlowMeasurementDone)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.FlowInDone or Event.FlowOutDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if ((int)(controlBoard.StatusP & StatusP.RefFlowMeterMask) == flowMeter.Idx1)
|
||||
{
|
||||
flowBox.Val = flowMeter.ReadFlow();
|
||||
return eventDone;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.Error;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using Dirichlet.Numerics;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class SendCommandArgs
|
||||
{
|
||||
public Command Cmd;
|
||||
public int RefFlowmtrNr;
|
||||
public int TotalRefPulses;
|
||||
public int MassRefPulses;
|
||||
public TestMethods TestMethods;
|
||||
public StopDevs StopDevs;
|
||||
|
||||
public SendCommandArgs()
|
||||
{
|
||||
}
|
||||
|
||||
public SendCommandArgs(Command cmd, int refFlowmtrNr, int totalRefPulses, int massRefPulses,
|
||||
TestMethods testMethods, StopDevs stopDevs)
|
||||
{
|
||||
Cmd = cmd;
|
||||
RefFlowmtrNr = refFlowmtrNr;
|
||||
TotalRefPulses = totalRefPulses;
|
||||
MassRefPulses = massRefPulses;
|
||||
TestMethods = testMethods;
|
||||
StopDevs = stopDevs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class StartMeasurementOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(StartMeasurementOp));
|
||||
public override string ToString() { return string.Format("StartMeasurementOp(ref={0},pulses={1})", flowMeterNr, totalRefPulses); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
readonly IRegValve regulValve;
|
||||
readonly int regulValveNr;
|
||||
readonly int regulValveStableTime;
|
||||
readonly int flowMeterNr;
|
||||
readonly double nominalFlow;
|
||||
readonly double maximalFlow;
|
||||
readonly double reqFlowLo;
|
||||
readonly double reqFlowHi;
|
||||
readonly int totalRefPulses; /// Number of reference pulses for a complete test
|
||||
readonly int massRefPulses; /// Number of reference pulses for mass collection
|
||||
readonly int delayBeforeFlowRegulation; /// Delay before flow control starts in seconds
|
||||
readonly TestMethods testMethod;
|
||||
readonly int diverterNr;
|
||||
|
||||
///
|
||||
/// Internal states of this operation
|
||||
///
|
||||
enum OpState
|
||||
{
|
||||
StartingTest,
|
||||
ResendCommand,
|
||||
WaitingBeforeValveMove,
|
||||
StartingFlowRegulation,
|
||||
OpCompleted,
|
||||
}
|
||||
OpState opState;
|
||||
|
||||
|
||||
int delayStartTime; /// StateMachine.Time snapshot when delay before flow regulation starts
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Starts the measurement.
|
||||
/// Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="controlBoard">Control board component reference</param>
|
||||
/// <param name="outputPath">Specifies used components</param>
|
||||
/// <param name="method">Test method</param>
|
||||
/// <param name="totalRefPulses">Test duration in number of reference flowmeter pulses</param>
|
||||
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
|
||||
public StartMeasurementOp(CBoard controlBoard, OutputPath outputPath, TestMethods method,
|
||||
double requiredFlowLo, double requiredFlowHi, int refPulses, int delayBeforeFlowRegulation = 0)
|
||||
: this(controlBoard, outputPath, method, requiredFlowLo, requiredFlowHi, refPulses, refPulses, delayBeforeFlowRegulation)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the measurement.
|
||||
/// Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="controlBoard">Control board component reference</param>
|
||||
/// <param name="outputPath">Specifies used components</param>
|
||||
/// <param name="method">Test method</param>
|
||||
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
|
||||
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
|
||||
public StartMeasurementOp(CBoard controlBoard, OutputPath outputPath, TestMethods method,
|
||||
double requiredFlowLo, double requiredFlowHi, int totalRefPulses, int massRefPulses, int delayBeforeFlowRegulation = 0)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("controlBoardDev");
|
||||
this.controlBoard = controlBoard;
|
||||
|
||||
if (outputPath.FlowMeter == null) throw new ArgumentNullException("Flow meter is missing");
|
||||
flowMeterNr = outputPath.FlowMeter.Idx1;
|
||||
|
||||
this.regulValve = outputPath.RegValve;
|
||||
if (regulValve is Elde.RegulValve.RegulValve)
|
||||
{
|
||||
Elde.RegulValve.RegulValve rv = outputPath.RegValve as Elde.RegulValve.RegulValve;
|
||||
regulValveNr = rv.Idx1;
|
||||
regulValveStableTime = rv.StableTime;
|
||||
}
|
||||
else if (regulValve is Elde.RegulValveCoax.RegulValve)
|
||||
{
|
||||
Elde.RegulValveCoax.RegulValve rv = outputPath.RegValve as Elde.RegulValveCoax.RegulValve;
|
||||
regulValveNr = rv.Idx1;
|
||||
regulValveStableTime = rv.StableTime;
|
||||
}
|
||||
else if (!(regulValve is Dummy.RegulValve.RegulValve))
|
||||
{
|
||||
throw new ArgumentNullException("Regulation valve is not compatible with Elde Control Board");
|
||||
}
|
||||
|
||||
if (outputPath.Diverter is Elde.Diverter.Diverter)
|
||||
{
|
||||
diverterNr = (outputPath.Diverter as Elde.Diverter.Diverter).DiverterNr;
|
||||
}
|
||||
|
||||
nominalFlow = outputPath.FlowMeter.NominalFlow;
|
||||
maximalFlow = 1.25 * nominalFlow;
|
||||
|
||||
this.testMethod = method;
|
||||
this.reqFlowLo = requiredFlowLo;
|
||||
this.reqFlowHi = requiredFlowHi;
|
||||
this.totalRefPulses = totalRefPulses;
|
||||
this.massRefPulses = massRefPulses;
|
||||
this.delayBeforeFlowRegulation = delayBeforeFlowRegulation;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
void SendStartCommand()
|
||||
{
|
||||
controlBoard.SyncRoute();
|
||||
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || BADGER_VELKA_TRAT || SLM_50
|
||||
int flowMeterIdxAndDiv = flowMeterNr + 16 * diverterNr;
|
||||
#elif BADGER_STREDNA_TRAT
|
||||
int flowMeterIdxAndDiv = flowMeterNr + 8 * (diverterNr - 1);
|
||||
#elif FILIPINY_50
|
||||
int flowMeterIdxAndDiv = flowMeterNr + ((flowMeterNr == 3) ? (4 * (diverterNr - 1)) : 0);
|
||||
#elif GELSENWASSER
|
||||
int flowMeterIdxAndDiv = flowMeterNr + ((diverterNr == 2) ? 16 : 0);
|
||||
#else
|
||||
int flowMeterIdxAndDiv = flowMeterNr;
|
||||
#endif
|
||||
log.InfoFormat("Start() : SendCommand(Cmd.Start, {0}, route, {1}, {1}, {2}, Stop.None)",
|
||||
flowMeterIdxAndDiv, totalRefPulses, testMethod);
|
||||
|
||||
controlBoard.SendCommand(Command.Start, flowMeterIdxAndDiv, totalRefPulses, massRefPulses, testMethod, StopDevs.None);
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
SendStartCommand();
|
||||
opState = OpState.StartingTest;
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.FlowInDone or Event.FlowOutDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (opState == OpState.StartingTest)
|
||||
{
|
||||
StatusP statusP = controlBoard.StatusP;
|
||||
log.DebugFormat("statusP = {0} {1} {2} {3}",
|
||||
(((ulong)statusP >> 48) & 0xFFFF).ToString("X4"),
|
||||
(((ulong)statusP >> 32) & 0xFFFF).ToString("X4"),
|
||||
(((ulong)statusP >> 16) & 0xFFFF).ToString("X4"),
|
||||
((ulong)statusP & 0xFFFF).ToString("X4"));
|
||||
|
||||
if ((statusP & StatusP.TestInProgress) != 0)
|
||||
{
|
||||
log.Info("Test started");
|
||||
if (delayBeforeFlowRegulation > 0)
|
||||
{
|
||||
delayStartTime = StateMachine.Time;
|
||||
opState = OpState.WaitingBeforeValveMove;
|
||||
}
|
||||
else
|
||||
{
|
||||
opState = OpState.StartingFlowRegulation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//opState = OpState.ResendCommand;
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ResendCommand)
|
||||
{
|
||||
SendStartCommand();
|
||||
opState = OpState.StartingTest;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.WaitingBeforeValveMove)
|
||||
{
|
||||
if (StateMachine.Time - delayStartTime >= delayBeforeFlowRegulation)
|
||||
{
|
||||
opState = OpState.StartingFlowRegulation;
|
||||
}
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.StartingFlowRegulation)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
if ((reqFlowLo >= reqFlowHi) || (reqFlowLo > maximalFlow) || (reqFlowHi <= 0))
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
|
||||
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi);
|
||||
|
||||
double freqLo = 2000.0 * reqFlowLo / nominalFlow;
|
||||
double freqHi = 2000.0 * reqFlowHi / nominalFlow;
|
||||
if (regulValve.IsCoax)
|
||||
{
|
||||
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
|
||||
new double[2] { (freqLo + freqHi) / 2, (freqLo + freqHi) / 2 },
|
||||
regulValveStableTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
|
||||
new double[2] { freqLo, freqHi },
|
||||
regulValveStableTime);
|
||||
}
|
||||
|
||||
opState = OpState.OpCompleted;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.OpCompleted)
|
||||
{
|
||||
return Event.MeasurementStarted;
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
class StopFlowRegulationOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(StopFlowRegulationOp));
|
||||
public override string ToString() { return string.Format("StopFlowRegulationOp(.)"); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
readonly int flowMeterNr;
|
||||
|
||||
/// <summary>
|
||||
/// Stop the previous control board operation (diverter, gate, etc.)
|
||||
/// Events: None or PreviousStopped
|
||||
/// </summary>
|
||||
/// <param name="controlBoardDev">Control board component reference</param>
|
||||
public StopFlowRegulationOp(CBoard controlBoardDev)
|
||||
{
|
||||
if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev");
|
||||
this.controlBoard = controlBoardDev;
|
||||
|
||||
if (controlBoardDev.Devices.FlowMeter == null) throw new ArgumentNullException("Flow meter is missing");
|
||||
flowMeterNr = controlBoardDev.Devices.FlowMeter.Idx1;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
void SendStopFlowRegulationCommand()
|
||||
{
|
||||
controlBoard.SyncRoute();
|
||||
controlBoard.SendCommand(Command.Stop, flowMeterNr, 0, 0, 0, StopDevs.RegValveRegulation);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
SendStopFlowRegulationCommand();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>Event.FlowRegulationStopped</returns>
|
||||
public Event Run()
|
||||
{
|
||||
return Event.FlowRegulationStopped;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
public class StopPreviousOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(StopPreviousOp));
|
||||
public override string ToString() { return string.Format("StopPreviousOp(.)"); }
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
|
||||
///
|
||||
/// Internal states of this operation
|
||||
///
|
||||
enum OpState
|
||||
{
|
||||
Idle = 0,
|
||||
CheckIfStopped,
|
||||
ResendCommand,
|
||||
Stopped,
|
||||
}
|
||||
OpState opState;
|
||||
|
||||
/// <summary>
|
||||
/// Stop the previous control board operation (diverter, gate, etc.)
|
||||
/// Events: None or PreviousStopped
|
||||
/// </summary>
|
||||
/// <param name="controlBoardDev">Control board component reference</param>
|
||||
public StopPreviousOp(CBoard controlBoardDev)
|
||||
{
|
||||
if (controlBoardDev == null) throw new ArgumentNullException("controlBoardDev");
|
||||
this.controlBoard = controlBoardDev;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
void SendStopCommand()
|
||||
{
|
||||
controlBoard.SyncRoute();
|
||||
controlBoard.SendCommand(Command.Stop, 0, 0, 0, TestMethods.Diverter,
|
||||
StopDevs.Diverter | StopDevs.GatePulse | StopDevs.Reference | StopDevs.RegValveRegulation);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
SendStopCommand();
|
||||
opState = OpState.CheckIfStopped;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.None or Event.PreviousStopped
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (opState == OpState.CheckIfStopped)
|
||||
{
|
||||
if ((controlBoard.StatusP & (StatusP.TestCompleted | StatusP.TestInProgress)) == 0)
|
||||
{
|
||||
opState = OpState.Stopped;
|
||||
return Event.PreviousStopped;
|
||||
}
|
||||
else
|
||||
{
|
||||
opState = OpState.ResendCommand;
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (opState == OpState.ResendCommand)
|
||||
{
|
||||
if ((controlBoard.StatusP & (StatusP.TestCompleted | StatusP.TestInProgress)) == 0)
|
||||
{
|
||||
opState = OpState.Stopped;
|
||||
return Event.PreviousStopped;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendStopCommand();
|
||||
opState = OpState.CheckIfStopped;
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (opState == OpState.Stopped)
|
||||
{
|
||||
return Event.PreviousStopped;
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
opState = OpState.Idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,774 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using Dirichlet.Numerics;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Legacy
|
||||
{
|
||||
/// <summary>
|
||||
/// Test bench model inherited by all classes for the simulation of devices.
|
||||
/// Define DN100, MUNICH or nothing.
|
||||
/// </summary>
|
||||
public static class TestBenchSim
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(TestBenchSim));
|
||||
|
||||
///
|
||||
/// Incremented in RunDevice() depending on diverters and valves
|
||||
///
|
||||
public static double Mass1sim; /// Volume in [ltr] or mass in [kg] in the tank1 on the balance1, filled by the diverter1
|
||||
public static double Mass2sim; /// Volume in [ltr] or mass in [kg] in the tank2 on the balance2, filled by the diverter2
|
||||
|
||||
///
|
||||
/// Set by regulation valves
|
||||
///
|
||||
public static double Flow1sim; /// flow in [m3/h] through RV1
|
||||
public static double Flow2sim; /// flow in [m3/h] through RV2
|
||||
public static double Flow3sim; /// flow in [m3/h] through RV3
|
||||
public static double Flow4sim; /// flow in [m3/h] through RV4
|
||||
public static double Flow5sim; /// flow in [m3/h] through RV5
|
||||
public static double Flow6sim; /// flow in [m3/h] through RV5
|
||||
|
||||
///
|
||||
/// Valves and diverters
|
||||
///
|
||||
public static UInt128 SimRoute;
|
||||
public static bool Div1sim;
|
||||
public static bool Div2sim;
|
||||
public static bool Div3sim;
|
||||
|
||||
static int regulValveNo; /// 0=undefined, 1..5
|
||||
static int refFlowmtrNo; /// 0=undefined, 1..4
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Mass1sim = 0; /// Initialize tanks
|
||||
Mass2sim = 0;
|
||||
Flow1sim = 0; /// Initialize regulation valves
|
||||
Flow2sim = 0;
|
||||
Flow3sim = 0;
|
||||
Flow4sim = 0;
|
||||
Flow5sim = 0;
|
||||
Flow6sim = 0;
|
||||
SimRoute = 0; /// Initialize other valves
|
||||
Div1sim = false;
|
||||
Div2sim = false;
|
||||
Div3sim = false;
|
||||
}
|
||||
|
||||
#if DN100
|
||||
/// Paths modulating the flows
|
||||
const ulong K5 = (1L << 0);
|
||||
const ulong K7 = (1L << 1);
|
||||
const ulong K10 = (1L << 2);
|
||||
const ulong K13 = (1L << 3);
|
||||
const ulong K16 = (1L << 4);
|
||||
const ulong K2 = (1L << 5);
|
||||
const ulong EmptyValve1 = (1L << 17);
|
||||
const ulong EmptyValve2 = (1L << 18);
|
||||
const ulong Vl5 = (1L << 21);
|
||||
const ulong Path1 = K2 | K5 | K7;
|
||||
const ulong Path2 = K2 | K5 | K10;
|
||||
const ulong Path3 = K2 | K5 | K13;
|
||||
const ulong Path4 = K2 | K5 | K16;
|
||||
const ulong Path5 = K2 | K5 | Vl5;
|
||||
#elif MUNICH
|
||||
const ulong VL11 = (1L << 0);
|
||||
const ulong VL13 = (1L << 1);
|
||||
const ulong VL21 = (1L << 2);
|
||||
const ulong VL23 = (1L << 3);
|
||||
const ulong VZ1 = (1L << 4);
|
||||
const ulong VP2 = (1L << 5);
|
||||
const ulong VP4 = (1L << 6);
|
||||
const ulong VP5 = (1L << 7);
|
||||
|
||||
const ulong VP6 = (1L << 8);
|
||||
const ulong VL12 = (1L << 9);
|
||||
const ulong VL22 = (1L << 10);
|
||||
const ulong VI11 = (1L << 11);
|
||||
const ulong VI12 = (1L << 12);
|
||||
const ulong VI13 = (1L << 13);
|
||||
const ulong VI21 = (1L << 14);
|
||||
const ulong VI22 = (1L << 15);
|
||||
|
||||
const ulong VI2P = (1L << 16);
|
||||
const ulong VI31 = (1L << 17);
|
||||
const ulong VI32 = (1L << 18);
|
||||
const ulong VI3P = (1L << 19);
|
||||
const ulong VI41 = (1L << 20);
|
||||
const ulong VI42 = (1L << 21);
|
||||
const ulong VI43 = (1L << 22);
|
||||
const ulong VI4P = (1L << 23);
|
||||
|
||||
const ulong VB1 = (1L << 24);
|
||||
const ulong VB1a = (1L << 25);
|
||||
const ulong VB2 = (1L << 26);
|
||||
const ulong VB2a = (1L << 27);
|
||||
const ulong VM1 = (1L << 28);
|
||||
const ulong VM2 = (1L << 29);
|
||||
const ulong VM3 = (1L << 30);
|
||||
const ulong VM4 = ((ulong)1 << 31);
|
||||
|
||||
const ulong Pump1 = ((ulong)1 << 32);
|
||||
const ulong Block = ((ulong)1 << 33);
|
||||
const ulong VZ8 = ((ulong)1 << 37);
|
||||
|
||||
const ulong EmptyValve1 = VB1 | VB1a;
|
||||
const ulong EmptyValve2 = VB2 | VB2a;
|
||||
|
||||
const ulong Path1 = VZ1 | VL12 | VI11 | VI13;
|
||||
const ulong Path2 = VZ1 | VL11 | VL12 | VI21 | VI22 | VI13;
|
||||
const ulong Path3 = VZ1 | VL11 | VL12 | VI31 | VI32;
|
||||
const ulong Path4 = VZ1 | VL11 | VL12 | VI41 | VI42;
|
||||
const ulong Path5 = VZ1 | VL11 | VL12 | VI41 | VI43;
|
||||
#elif FUZHOU_150
|
||||
const ulong VL11 = (1L << 2);
|
||||
const ulong VL13 = (1L << 3);
|
||||
const ulong VL4 = (1L << 4);
|
||||
const ulong VZ6 = (1L << 5);
|
||||
const ulong VZ7 = (1L << 6);
|
||||
const ulong VP5 = (1L << 7);
|
||||
|
||||
const ulong VP6 = (1L << 8);
|
||||
const ulong VL12 = (1L << 9);
|
||||
const ulong VZ14 = (1L << 10);
|
||||
const ulong VI11 = (1L << 11);
|
||||
const ulong VI12 = (1L << 12);
|
||||
const ulong VI13 = (1L << 13);
|
||||
const ulong VI21 = (1L << 14);
|
||||
const ulong VI22 = (1L << 15);
|
||||
|
||||
const ulong VI2p = (1L << 16);
|
||||
const ulong VI31 = (1L << 17);
|
||||
const ulong VI32 = (1L << 18);
|
||||
const ulong VI3p = (1L << 19);
|
||||
const ulong VI41 = (1L << 20);
|
||||
const ulong VI42 = (1L << 21);
|
||||
const ulong VI43 = (1L << 22);
|
||||
const ulong VI4p = (1L << 23);
|
||||
|
||||
const ulong VB1 = (1L << 24);
|
||||
const ulong VB1a = (1L << 25);
|
||||
const ulong VB2 = (1L << 26);
|
||||
const ulong VB2a = (1L << 27);
|
||||
const ulong VM1 = (1L << 28);
|
||||
const ulong VM2 = (1L << 29);
|
||||
const ulong VM3 = (1L << 20);
|
||||
|
||||
const ulong Pump1 = ((ulong)1 << 32);
|
||||
const ulong Pump4 = ((ulong)1 << 33);
|
||||
const ulong Pump2 = ((ulong)1 << 37);
|
||||
const ulong Pump3 = ((ulong)1 << 38);
|
||||
const ulong Pump5 = ((ulong)1 << 39);
|
||||
|
||||
const ulong EmptyValve1 = VB1 | VB1a;
|
||||
const ulong EmptyValve2 = VB2 | VB2a;
|
||||
|
||||
const ulong Path1 = VL12 | VI11 | VI13;
|
||||
const ulong Path2 = VL12 | VI21 | VI22 | VI13;
|
||||
const ulong Path3 = VL12 | VI31 | VI32;
|
||||
const ulong Path4 = VL12 | VI41 | VI42;
|
||||
const ulong Path5 = VL12 | VI41 | VI43;
|
||||
#elif FUZHOU_300
|
||||
const ulong VL11 = (1L << 2);
|
||||
const ulong VL13 = (1L << 3);
|
||||
const ulong VL4 = (1L << 4);
|
||||
const ulong VZ6 = (1L << 5);
|
||||
const ulong VZ7 = (1L << 6);
|
||||
const ulong VP5 = (1L << 7);
|
||||
|
||||
const ulong VP6 = (1L << 8);
|
||||
const ulong VL12 = (1L << 9);
|
||||
const ulong VZ14 = (1L << 10);
|
||||
const ulong VI11 = (1L << 11);
|
||||
const ulong VI12 = (1L << 12);
|
||||
const ulong VI13 = (1L << 13);
|
||||
const ulong VI21 = (1L << 14);
|
||||
const ulong VI22 = (1L << 15);
|
||||
|
||||
const ulong VI2p = (1L << 16);
|
||||
const ulong VI31 = (1L << 17);
|
||||
const ulong VI32 = (1L << 18);
|
||||
const ulong VI3p = (1L << 19);
|
||||
const ulong VI41 = (1L << 20);
|
||||
const ulong VI42 = (1L << 21);
|
||||
const ulong VI43 = (1L << 22);
|
||||
const ulong VI4p = (1L << 23);
|
||||
|
||||
const ulong VB1 = (1L << 24);
|
||||
const ulong VB1a = (1L << 25);
|
||||
const ulong VB2 = (1L << 26);
|
||||
const ulong VB2a = (1L << 27);
|
||||
const ulong VM1 = (1L << 28);
|
||||
const ulong VM2 = (1L << 29);
|
||||
const ulong VM3 = (1L << 20);
|
||||
|
||||
const ulong Pump1 = ((ulong)1 << 32);
|
||||
const ulong Pump4 = ((ulong)1 << 33);
|
||||
const ulong Pump2 = ((ulong)1 << 37);
|
||||
const ulong Pump3 = ((ulong)1 << 38);
|
||||
const ulong Pump5 = ((ulong)1 << 39);
|
||||
|
||||
const ulong EmptyValve1 = VB1 | VB1a;
|
||||
const ulong EmptyValve2 = VB2 | VB2a;
|
||||
|
||||
const ulong Path1 = VL12 | VI11 | VI13;
|
||||
const ulong Path2 = VL12 | VI21 | VI22 | VI13;
|
||||
const ulong Path3 = VL12 | VI31 | VI32;
|
||||
const ulong Path4 = VL12 | VI41 | VI42;
|
||||
const ulong Path5 = VL12 | VI41 | VI43;
|
||||
#elif IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER
|
||||
const ulong VM11 = (1L << 4);
|
||||
const ulong VM12 = (1L << 5);
|
||||
const ulong VM21 = (1L << 6);
|
||||
const ulong VM22 = (1L << 7);
|
||||
|
||||
const ulong VZ14 = (1L << 8);
|
||||
const ulong VZ13 = (1L << 9);
|
||||
const ulong VL11 = (1L << 10);
|
||||
const ulong VL13 = (1L << 11);
|
||||
const ulong VL4 = (1L << 12);
|
||||
const ulong VZ6 = (1L << 13);
|
||||
const ulong VZ7 = (1L << 14);
|
||||
const ulong VP5 = (1L << 15);
|
||||
|
||||
const ulong VP6 = (1L << 16);
|
||||
const ulong VL12 = (1L << 17);
|
||||
const ulong VL51 = (1L << 18);
|
||||
const ulong VL53 = (1L << 19);
|
||||
const ulong VI11 = (1L << 20);
|
||||
const ulong VI12 = (1L << 21);
|
||||
const ulong VI13 = (1L << 22);
|
||||
const ulong VV1 = (1L << 23);
|
||||
|
||||
const ulong VI21 = (1L << 25);
|
||||
const ulong VI22 = (1L << 26);
|
||||
const ulong VI2p = (1L << 27);
|
||||
const ulong VI31 = (1L << 28);
|
||||
const ulong VI32 = (1L << 29);
|
||||
const ulong VI3p = (1L << 30);
|
||||
const ulong VI41 = (1L << 31);
|
||||
|
||||
const ulong VI42 = (1L << 32);
|
||||
const ulong VI4p = (1L << 33);
|
||||
const ulong VI43 = (1L << 37);
|
||||
|
||||
const ulong VM1 = (1L << 50);
|
||||
const ulong VM2 = (1L << 51);
|
||||
const ulong VM3 = (1L << 52);
|
||||
|
||||
const ulong VB1 = (1L << 41);
|
||||
const ulong VB1a = (1L << 42);
|
||||
const ulong VB2 = (1L << 43);
|
||||
const ulong VB2a = (1L << 44);
|
||||
|
||||
const ulong Pump1 = (1L << 48);
|
||||
const ulong Pump4 = (1L << 49);
|
||||
const ulong Pump2 = (1L << 38);
|
||||
const ulong Pump3 = (1L << 39);
|
||||
const ulong Pump5 = (1L << 40);
|
||||
|
||||
const ulong EmptyValve1 = VB1 | VB1a;
|
||||
const ulong EmptyValve2 = VB2 | VB2a;
|
||||
|
||||
const ulong Path1 = VL12 | VI11 | VI13;
|
||||
const ulong Path2 = VL12 | VI21 | VI22 | VI13;
|
||||
const ulong Path3 = VL12 | VI31 | VI32;
|
||||
const ulong Path4 = VL12 | VI41 | VI42;
|
||||
const ulong Path5 = VL12 | VI41 | VI43;
|
||||
#elif BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT
|
||||
const ulong VZ34 = (1L << 0);
|
||||
const ulong VZ35 = (1L << 1);
|
||||
const ulong VZ39 = (1L << 2);
|
||||
const ulong VZ37 = (1L << 3);
|
||||
const ulong VZ38 = (1L << 4);
|
||||
const ulong VL31 = (1L << 5);
|
||||
const ulong VV1 = (1L << 6);
|
||||
const ulong VS33 = (1L << 7);
|
||||
|
||||
const ulong VS31 = (1L << 8);
|
||||
const ulong VS32 = (1L << 9);
|
||||
const ulong VV2 = (1L << 10);
|
||||
const ulong VL32 = (1L << 11);
|
||||
const ulong VI31 = (1L << 12);
|
||||
const ulong VI32 = (1L << 13);
|
||||
const ulong VI33 = (1L << 14);
|
||||
const ulong VI34 = (1L << 15);
|
||||
|
||||
const ulong DIV1 = (1L << 16);
|
||||
const ulong DIV2 = (1L << 17);
|
||||
const ulong VB1 = (1L << 18);
|
||||
const ulong VB1a = (1L << 19);
|
||||
const ulong VB2 = (1L << 20);
|
||||
const ulong VB2a = (1L << 21);
|
||||
const ulong P1 = (1L << 22);
|
||||
const ulong P2 = (1L << 23);
|
||||
|
||||
const ulong EmptyValve1 = VB1 | VB1a;
|
||||
const ulong EmptyValve2 = VB2 | VB2a;
|
||||
|
||||
const ulong Path1 = VI31;
|
||||
const ulong Path2 = VI32;
|
||||
const ulong Path3 = VI33;
|
||||
const ulong Path4 = VI34;
|
||||
const ulong Path5 = 0;
|
||||
#elif CEVAK_40 || MURES_40 || FUZHOU_50 || SLM_50 || MALTA_WSD25
|
||||
const ulong VL11 = (1L << 0);
|
||||
const ulong VL13 = (1L << 1);
|
||||
const ulong VL18 = (1L << 2);
|
||||
const ulong VZ12 = (1L << 3);
|
||||
const ulong VL15 = (1L << 4);
|
||||
const ulong VL21 = (1L << 5);
|
||||
const ulong VL23 = (1L << 6);
|
||||
const ulong VL28 = (1L << 7);
|
||||
|
||||
const ulong VZ5 = (1L << 8);
|
||||
const ulong VI1 = (1L << 9);
|
||||
const ulong VI2 = (1L << 10);
|
||||
const ulong VI3 = (1L << 11);
|
||||
const ulong VZ9 = (1L << 12);
|
||||
const ulong VBa = (1L << 13);
|
||||
const ulong VB = (1L << 14);
|
||||
const ulong DIV1 = (1L << 15);
|
||||
|
||||
const ulong P1 = (1L << 16);
|
||||
const ulong P2 = (1L << 17);
|
||||
const ulong VL9 = (1L << 18);
|
||||
const ulong VV1 = (1L << 19);
|
||||
const ulong VV2 = (1L << 20);
|
||||
const ulong VZ6 = (1L << 21);
|
||||
const ulong VV3 = (1L << 22);
|
||||
const ulong Gate = (1L << 23);
|
||||
|
||||
const ulong EmptyValve1 = VB | VBa;
|
||||
const ulong EmptyValve2 = 0x0000FFFFFFFFFFFF;
|
||||
|
||||
const ulong Path1 = VI1;
|
||||
const ulong Path2 = VI2;
|
||||
const ulong Path3 = VI3;
|
||||
const ulong Path4 = 0;
|
||||
const ulong Path5 = 0;
|
||||
#elif TORINO_50
|
||||
const ulong nic1 = (1L << 0);
|
||||
const ulong nic2 = (1L << 1);
|
||||
const ulong VL11 = (1L << 2);
|
||||
const ulong VL13 = (1L << 3);
|
||||
const ulong VL18 = (1L << 4);
|
||||
const ulong VZ13 = (1L << 5);
|
||||
const ulong VL15 = (1L << 6);
|
||||
const ulong VZ10 = (1L << 7);
|
||||
|
||||
const ulong VZ6 = (1L << 8);
|
||||
const ulong VV1 = (1L << 9);
|
||||
const ulong VV4 = (1L << 10);
|
||||
const ulong VL12 = (1L << 11);
|
||||
const ulong VI1 = (1L << 12);
|
||||
const ulong VI2 = (1L << 13);
|
||||
const ulong VI3 = (1L << 14);
|
||||
const ulong VI4 = (1L << 15);
|
||||
|
||||
const ulong VB1 = (1L << 16);
|
||||
const ulong VB1a = (1L << 17);
|
||||
const ulong VB2 = (1L << 18);
|
||||
const ulong VB2a = (1L << 19);
|
||||
const ulong DIV1 = (1L << 20);
|
||||
const ulong DIV2 = (1L << 21);
|
||||
const ulong P1 = (1L << 22);
|
||||
const ulong P3 = (1L << 23);
|
||||
|
||||
const ulong P2 = (1L << 24);
|
||||
|
||||
const ulong EmptyValve1 = VB1 | VB1a;
|
||||
const ulong EmptyValve2 = VB2 | VB2a;
|
||||
|
||||
const ulong Path1 = VI1;
|
||||
const ulong Path2 = VI2;
|
||||
const ulong Path3 = VI3;
|
||||
const ulong Path4 = VI4;
|
||||
const ulong Path5 = 0;
|
||||
#elif TORUN_50 || TURA_IPERL || TURA_IPERL_NEW
|
||||
const ulong VL11 = (1L << 0);
|
||||
const ulong VL13 = (1L << 1);
|
||||
const ulong VL15 = (1L << 2);
|
||||
const ulong VL21 = (1L << 3);
|
||||
const ulong VL23 = (1L << 4);
|
||||
const ulong VL18 = (1L << 5);
|
||||
const ulong VL28 = (1L << 6);
|
||||
const ulong VZ5 = (1L << 7);
|
||||
|
||||
const ulong VZ6 = (1L << 8);
|
||||
const ulong DIV1 = (1L << 9);
|
||||
const ulong DIV2 = (1L << 10);
|
||||
const ulong P1 = (1L << 11);
|
||||
const ulong P2 = (1L << 12);
|
||||
const ulong P3 = (1L << 13);
|
||||
const ulong DIV3 = (1L << 14);
|
||||
const ulong rez1 = (1L << 15);
|
||||
|
||||
const ulong nic1 = (1L << 16);
|
||||
const ulong nic2 = (1L << 17);
|
||||
const ulong VI1 = (1L << 18);
|
||||
const ulong VI2 = (1L << 19);
|
||||
const ulong VI3 = (1L << 20);
|
||||
const ulong VI4 = (1L << 21);
|
||||
const ulong VI5 = (1L << 22);
|
||||
const ulong VB1 = (1L << 23);
|
||||
|
||||
const ulong VV12 = (1L << 24);
|
||||
const ulong VV22 = (1L << 25);
|
||||
const ulong VI6 = (1L << 26);
|
||||
const ulong VV3 = (1L << 27);
|
||||
const ulong VB2 = (1L << 28);
|
||||
|
||||
const ulong EmptyValve1 = VB1;
|
||||
const ulong EmptyValve2 = VB2;
|
||||
|
||||
const ulong Path1 = VI1;
|
||||
const ulong Path2 = VI2;
|
||||
const ulong Path3 = VI3;
|
||||
const ulong Path4 = VI4;
|
||||
const ulong Path5 = VI5;
|
||||
const ulong Path6 = VI6;
|
||||
#elif TURA_SPECIAL
|
||||
const ulong VL11 = (1L << 0);
|
||||
const ulong VL13 = (1L << 1);
|
||||
const ulong VL15 = (1L << 2);
|
||||
const ulong VL21 = (1L << 3);
|
||||
const ulong VL23 = (1L << 4);
|
||||
const ulong VL18 = (1L << 5);
|
||||
const ulong VL28 = (1L << 6);
|
||||
const ulong VZ5 = (1L << 7);
|
||||
|
||||
const ulong VZ6 = (1L << 8);
|
||||
const ulong DIV1 = (1L << 9);
|
||||
const ulong DIV2 = (1L << 10);
|
||||
const ulong P1 = (1L << 11);
|
||||
const ulong P2 = (1L << 12);
|
||||
const ulong P3 = (1L << 13);
|
||||
const ulong DIV3 = (1L << 14);
|
||||
const ulong rez1 = (1L << 15);
|
||||
|
||||
const ulong nic1 = (1L << 16);
|
||||
const ulong nic2 = (1L << 17);
|
||||
const ulong VI1 = (1L << 18);
|
||||
const ulong VI2 = (1L << 19);
|
||||
const ulong VI3 = (1L << 20);
|
||||
const ulong VI4 = (1L << 21);
|
||||
const ulong VI5 = (1L << 22);
|
||||
const ulong VB1 = (1L << 23);
|
||||
|
||||
const ulong VV12 = (1L << 24);
|
||||
const ulong VV22 = (1L << 25);
|
||||
const ulong VI6 = (1L << 26);
|
||||
const ulong VV3 = (1L << 27);
|
||||
const ulong VB2 = (1L << 28);
|
||||
|
||||
const ulong EmptyValve1 = VB1;
|
||||
const ulong EmptyValve2 = VB2;
|
||||
|
||||
const ulong Path1 = VI1;
|
||||
const ulong Path2 = VI2;
|
||||
const ulong Path3 = VI3;
|
||||
const ulong Path4 = VI4;
|
||||
const ulong Path5 = VI5;
|
||||
const ulong Path6 = VI6;
|
||||
#else
|
||||
/// Paths modulating the flows
|
||||
const ulong V1 = (1L << 1);
|
||||
const ulong V2 = (1L << 2);
|
||||
const ulong V3 = (1L << 3);
|
||||
const ulong V3b = (1L << 4);
|
||||
const ulong V4 = (1L << 5);
|
||||
const ulong V4b = (1L << 6);
|
||||
const ulong V5 = (1L << 7);
|
||||
const ulong V5b = (1L << 8);
|
||||
const ulong EmptyValve1 = (1L << 9); // =Ve1
|
||||
const ulong EmptyValve2 = (1L << 10); // =Ve2
|
||||
const ulong Path1 = V1 | V3 | V3b | V4 | V4b;
|
||||
const ulong Path2 = V2 | V3 | V3b | V5 | V5b;
|
||||
const ulong Path3 = 0;
|
||||
const ulong Path4 = 0;
|
||||
const ulong Path5 = 0;
|
||||
#endif
|
||||
/// <summary>Run this device</summary>
|
||||
public static void RunDevice(int regulValveNo, int refFlowmtrNo, StatusP statusP)
|
||||
{
|
||||
TestBenchSim.regulValveNo = regulValveNo;
|
||||
TestBenchSim.refFlowmtrNo = refFlowmtrNo;
|
||||
double time = 1.0;
|
||||
|
||||
#if DN100
|
||||
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
|
||||
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
|
||||
if (Div2sim && (SimRoute & Path3) == Path3) Mass2sim += DiffKg(Flow3sim, time);
|
||||
if (Div2sim && (SimRoute & Path4) == Path4) Mass2sim += DiffKg(Flow4sim, time);
|
||||
if (Div1sim && (SimRoute & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time);
|
||||
#elif MUNICH || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER
|
||||
if (Div1sim && (SimRoute & Path1) == Path1)
|
||||
{
|
||||
double diff = DiffKg(Flow1sim, time);
|
||||
Mass1sim += diff;
|
||||
log.WarnFormat("Path1: Div1, Mass1+={0}kg, flow={1}m3/h, Mass1={2}kg", diff, Flow1sim, Mass1sim);
|
||||
}
|
||||
if (Div1sim && (SimRoute & Path2) == Path2)
|
||||
{
|
||||
double diff = DiffKg(Flow2sim, time);
|
||||
Mass1sim += diff;
|
||||
log.WarnFormat("Path2: Div1, Mass1 += {0}kg, flow={1}m3/h, Mass1={2}kg", diff, Flow1sim, Mass1sim);
|
||||
}
|
||||
if (Div2sim && (SimRoute & Path3) == Path3)
|
||||
{
|
||||
double diff = DiffKg(Flow3sim, time);
|
||||
Mass2sim += diff;
|
||||
log.WarnFormat("Path3: Div2, Mass2 += {0}kg, flow={1}m3/h, Mass2={2}kg", diff, Flow1sim, Mass2sim);
|
||||
}
|
||||
if (Div3sim && (SimRoute & Path4) == Path4)
|
||||
{
|
||||
double diff = DiffKg(Flow4sim, time);
|
||||
Mass2sim += diff;
|
||||
log.WarnFormat("Path4: Div3, Mass2 += {0}kg, flow={1}m3/h, Mass2={2}kg", diff, Flow1sim, Mass2sim);
|
||||
}
|
||||
if (Div3sim && (SimRoute & Path5) == Path5)
|
||||
{
|
||||
double diff = DiffKg(Flow5sim, time);
|
||||
Mass2sim += diff;
|
||||
log.WarnFormat("Path5: Div3, Mass2 += {0}kg, flow={1}m3/h, Mass2={2}kg", diff, Flow1sim, Mass2sim);
|
||||
}
|
||||
#elif BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT || TORINO_50 /// Path1,2 do WT1, Path3,4 do WT2
|
||||
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
|
||||
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
|
||||
if (Div2sim && (SimRoute & Path3) == Path3) Mass2sim += DiffKg(Flow3sim, time);
|
||||
if (Div2sim && (SimRoute & Path4) == Path4) Mass2sim += DiffKg(Flow4sim, time);
|
||||
#elif CEVAK_40 || MURES_40 || FUZHOU_50 || SLM_50 || MALTA_WSD25 /// Path1,2,3 do WT1
|
||||
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
|
||||
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
|
||||
if (Div1sim && (SimRoute & Path3) == Path3) Mass1sim += DiffKg(Flow3sim, time);
|
||||
#elif TORUN_50 || TURA_IPERL || TURA_IPERL_NEW /// Path1,2,3,4,5 do WT1, Path6 do WT2
|
||||
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
|
||||
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
|
||||
if (Div1sim && (SimRoute & Path3) == Path3) Mass1sim += DiffKg(Flow3sim, time);
|
||||
if (Div2sim && (SimRoute & Path4) == Path4) Mass1sim += DiffKg(Flow4sim, time);
|
||||
if (Div2sim && (SimRoute & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time);
|
||||
if (Div3sim && (SimRoute & Path6) == Path6) Mass2sim += DiffKg(Flow4sim, time);
|
||||
#elif TURA_SPECIAL
|
||||
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
|
||||
if (Div1sim && (SimRoute & Path2) == Path2) Mass1sim += DiffKg(Flow2sim, time);
|
||||
if (Div1sim && (SimRoute & Path3) == Path3) Mass1sim += DiffKg(Flow3sim, time);
|
||||
if (Div2sim && (SimRoute & Path4) == Path4) Mass1sim += DiffKg(Flow4sim, time);
|
||||
if (Div2sim && (SimRoute & Path5) == Path5) Mass1sim += DiffKg(Flow5sim, time);
|
||||
if (Div3sim && (SimRoute & Path6) == Path6) Mass2sim += DiffKg(Flow4sim, time);
|
||||
#else
|
||||
if (Div1sim && (SimRoute & Path1) == Path1) Mass1sim += DiffKg(Flow1sim, time);
|
||||
if (Div2sim && (SimRoute & Path2) == Path2) Mass2sim += DiffKg(Flow2sim, time);
|
||||
#endif
|
||||
|
||||
if ((SimRoute & EmptyValve1) == EmptyValve1) Mass1sim -= DiffKg(100.0, time);
|
||||
if (Mass1sim < 0) Mass1sim = 0;
|
||||
|
||||
if ((SimRoute & EmptyValve2) == EmptyValve2) Mass2sim -= DiffKg(10.0, time);
|
||||
if (Mass2sim < 0) Mass2sim = 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the mass change from the flow and the time period
|
||||
/// </summary>
|
||||
/// <param name="flowM3H">Flow in [m3/h]</param>
|
||||
/// <param name="timeSec">Time period in [s]</param>
|
||||
/// <returns>Mass change in [kg]</returns>
|
||||
static double DiffKg(double flowM3H, double timeSec)
|
||||
{
|
||||
return timeSec * flowM3H / 3.6;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the simulated mass. Use the balance range to distinguish the balances.
|
||||
/// </summary>
|
||||
/// <param name="balanceNr">0-based balance number</param>
|
||||
/// <returns>Simulated mass reading [kg]</returns>
|
||||
public static double GetSimMass(int balanceNr)
|
||||
{
|
||||
if (balanceNr == 0) return Mass1sim;
|
||||
else if (balanceNr == 1) return Mass2sim;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the simulated diverter. Use the nominal flow to distinguish the path.
|
||||
/// </summary>
|
||||
/// <param name="toTank">Diverter state: true = to the tank</param>
|
||||
/// <param name="nominalFlow">Nominal flow of the path [m3/h]</param>
|
||||
public static void SetSimDiverter(bool toTank)
|
||||
{
|
||||
#if DN100
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 5:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
Div2sim = toTank;
|
||||
break;
|
||||
default:
|
||||
if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#elif MUNICH || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || GELSENWASSER
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
case 3:
|
||||
Div2sim = toTank;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
Div3sim = toTank;
|
||||
break;
|
||||
default:
|
||||
//if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#elif BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || TORINO_50
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
Div2sim = toTank;
|
||||
break;
|
||||
default:
|
||||
if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#elif BADGER_VELKA_TRAT
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 7:
|
||||
case 2:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
case 3:
|
||||
Div2sim = toTank;
|
||||
break;
|
||||
default:
|
||||
if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#elif CEVAK_40 || MURES_40 || FUZHOU_50 || SLM_50 || MALTA_WSD25
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
default:
|
||||
if (toTank) { /* throw (new Exception()); */ }
|
||||
break;
|
||||
}
|
||||
#elif TORUN_50 || TURA_IPERL || TURA_IPERL_NEW
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
Div2sim = toTank;
|
||||
break;
|
||||
case 6:
|
||||
Div3sim = toTank;
|
||||
break;
|
||||
default:
|
||||
if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#elif TURA_SPECIAL
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
Div1sim = toTank;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
Div2sim = toTank;
|
||||
break;
|
||||
case 6:
|
||||
Div3sim = toTank;
|
||||
break;
|
||||
default:
|
||||
if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1: Div1sim = toTank; break;
|
||||
case 2: Div2sim = toTank; break;
|
||||
default:
|
||||
if (toTank) { throw (new Exception()); }
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the simulated flow in [m3/h].
|
||||
/// </summary>
|
||||
/// <returns>Simulated flow [m3/h]</returns>
|
||||
public static double GetSimFlow()
|
||||
{
|
||||
switch (refFlowmtrNo)
|
||||
{
|
||||
case 1: return ((SimRoute & Path1) == Path1) ? Flow1sim : 0;
|
||||
case 2: return ((SimRoute & Path2) == Path2) ? Flow2sim : 0;
|
||||
case 3: return ((SimRoute & Path3) == Path3) ? Flow3sim : 0;
|
||||
case 4: return (((SimRoute & Path4) == Path4) ? Flow4sim : 0) +
|
||||
(((SimRoute & Path5) == Path5) ? Flow5sim : 0);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Update simulated flow. Use the nominal flow to distinguish the path.
|
||||
/// </summary>
|
||||
/// <param name="targetFlow">Target flow [m3/h]</param>
|
||||
/// <param name="nominalFlow">Nominal flow of the path [m3/h]</param>
|
||||
public static void UpdateSimFlow(double targetFlow)
|
||||
{
|
||||
double A = 0.7; /// higher value -> slower regulation
|
||||
double B = 1.0 - A;
|
||||
|
||||
switch (regulValveNo)
|
||||
{
|
||||
case 1: Flow1sim = A * Flow1sim + B * targetFlow; break;
|
||||
case 2: Flow2sim = A * Flow2sim + B * targetFlow; break;
|
||||
case 3: Flow3sim = A * Flow3sim + B * targetFlow; break;
|
||||
case 4: Flow4sim = A * Flow4sim + B * targetFlow; break;
|
||||
case 5: Flow5sim = A * Flow5sim + B * targetFlow; break;
|
||||
case 6: Flow6sim = A * Flow6sim + B * targetFlow; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
///
|
||||
/// Copyright (c) 2020 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.ControlBoard.Papouch
|
||||
{
|
||||
partial class CBoardCfgCtrl
|
||||
{
|
||||
/// <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.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.vValveRangeLoTextBox = new System.Windows.Forms.TextBox();
|
||||
this.vValveRangeLoLabel = new System.Windows.Forms.Label();
|
||||
this.vValveRangeHiTextBox = new System.Windows.Forms.TextBox();
|
||||
this.vValveRangeHiLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.modbusAddressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.modbusAddressLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameLabel = new System.Windows.Forms.Label();
|
||||
this.variantComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.variantLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(175, 26);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 2;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(42, 60);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 3;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(178, 57);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.nameTextBox.TabIndex = 4;
|
||||
//
|
||||
// vValveRangeLoTextBox
|
||||
//
|
||||
this.vValveRangeLoTextBox.Enabled = false;
|
||||
this.vValveRangeLoTextBox.Location = new System.Drawing.Point(178, 161);
|
||||
this.vValveRangeLoTextBox.Name = "vValveRangeLoTextBox";
|
||||
this.vValveRangeLoTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.vValveRangeLoTextBox.TabIndex = 6;
|
||||
//
|
||||
// vValveRangeLoLabel
|
||||
//
|
||||
this.vValveRangeLoLabel.AutoSize = true;
|
||||
this.vValveRangeLoLabel.Location = new System.Drawing.Point(42, 164);
|
||||
this.vValveRangeLoLabel.Name = "vValveRangeLoLabel";
|
||||
this.vValveRangeLoLabel.Size = new System.Drawing.Size(118, 13);
|
||||
this.vValveRangeLoLabel.TabIndex = 5;
|
||||
this.vValveRangeLoLabel.Text = "Virtual valves range Lo:";
|
||||
//
|
||||
// vValveRangeHiTextBox
|
||||
//
|
||||
this.vValveRangeHiTextBox.Enabled = false;
|
||||
this.vValveRangeHiTextBox.Location = new System.Drawing.Point(178, 186);
|
||||
this.vValveRangeHiTextBox.Name = "vValveRangeHiTextBox";
|
||||
this.vValveRangeHiTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.vValveRangeHiTextBox.TabIndex = 8;
|
||||
//
|
||||
// vValveRangeHiLabel
|
||||
//
|
||||
this.vValveRangeHiLabel.AutoSize = true;
|
||||
this.vValveRangeHiLabel.Location = new System.Drawing.Point(42, 189);
|
||||
this.vValveRangeHiLabel.Name = "vValveRangeHiLabel";
|
||||
this.vValveRangeHiLabel.Size = new System.Drawing.Size(116, 13);
|
||||
this.vValveRangeHiLabel.TabIndex = 7;
|
||||
this.vValveRangeHiLabel.Text = "Virtual valves range Hi:";
|
||||
//
|
||||
// parentNameComboBox
|
||||
//
|
||||
this.parentNameComboBox.Enabled = false;
|
||||
this.parentNameComboBox.FormattingEnabled = true;
|
||||
this.parentNameComboBox.Location = new System.Drawing.Point(178, 83);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.parentNameComboBox.TabIndex = 10;
|
||||
//
|
||||
// modbusAddressTextBox
|
||||
//
|
||||
this.modbusAddressTextBox.Enabled = false;
|
||||
this.modbusAddressTextBox.Location = new System.Drawing.Point(178, 136);
|
||||
this.modbusAddressTextBox.Name = "modbusAddressTextBox";
|
||||
this.modbusAddressTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.modbusAddressTextBox.TabIndex = 12;
|
||||
//
|
||||
// modbusAddressLabel
|
||||
//
|
||||
this.modbusAddressLabel.AutoSize = true;
|
||||
this.modbusAddressLabel.Location = new System.Drawing.Point(42, 140);
|
||||
this.modbusAddressLabel.Name = "modbusAddressLabel";
|
||||
this.modbusAddressLabel.Size = new System.Drawing.Size(86, 13);
|
||||
this.modbusAddressLabel.TabIndex = 11;
|
||||
this.modbusAddressLabel.Text = "Modbus Address";
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(42, 86);
|
||||
this.parentNameLabel.Name = "parentNameLabel";
|
||||
this.parentNameLabel.Size = new System.Drawing.Size(69, 13);
|
||||
this.parentNameLabel.TabIndex = 9;
|
||||
this.parentNameLabel.Text = "Parent Name";
|
||||
//
|
||||
// variantComboBox
|
||||
//
|
||||
this.variantComboBox.Enabled = false;
|
||||
this.variantComboBox.FormattingEnabled = true;
|
||||
this.variantComboBox.Location = new System.Drawing.Point(178, 110);
|
||||
this.variantComboBox.Name = "variantComboBox";
|
||||
this.variantComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.variantComboBox.TabIndex = 14;
|
||||
//
|
||||
// variantLabel
|
||||
//
|
||||
this.variantLabel.AutoSize = true;
|
||||
this.variantLabel.Location = new System.Drawing.Point(42, 113);
|
||||
this.variantLabel.Name = "variantLabel";
|
||||
this.variantLabel.Size = new System.Drawing.Size(40, 13);
|
||||
this.variantLabel.TabIndex = 13;
|
||||
this.variantLabel.Text = "Variant";
|
||||
//
|
||||
// CBoardCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.variantComboBox);
|
||||
this.Controls.Add(this.variantLabel);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.modbusAddressTextBox);
|
||||
this.Controls.Add(this.modbusAddressLabel);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.vValveRangeHiTextBox);
|
||||
this.Controls.Add(this.vValveRangeHiLabel);
|
||||
this.Controls.Add(this.vValveRangeLoTextBox);
|
||||
this.Controls.Add(this.vValveRangeLoLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "CBoardCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(400, 300);
|
||||
this.Load += new System.EventHandler(this.ControlBoardCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.TextBox vValveRangeLoTextBox;
|
||||
private System.Windows.Forms.Label vValveRangeLoLabel;
|
||||
private System.Windows.Forms.TextBox vValveRangeHiTextBox;
|
||||
private System.Windows.Forms.Label vValveRangeHiLabel;
|
||||
private System.Windows.Forms.ComboBox parentNameComboBox;
|
||||
private System.Windows.Forms.TextBox modbusAddressTextBox;
|
||||
private System.Windows.Forms.Label modbusAddressLabel;
|
||||
private System.Windows.Forms.Label parentNameLabel;
|
||||
private System.Windows.Forms.ComboBox variantComboBox;
|
||||
private System.Windows.Forms.Label variantLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
///
|
||||
/// Copyright (c) 2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Papouch
|
||||
{
|
||||
public partial class CBoardCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
PapouchCBCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as PapouchCBCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public CBoardCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ControlBoardCfgCtrl_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 Modbus.Common.Factory)
|
||||
{
|
||||
parentNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (QuidoVariant v = 0; v < QuidoVariant.Count; v++) variantComboBox.Items.Add(v.ToString());
|
||||
|
||||
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;
|
||||
variantComboBox.Text = config.Variant.ToString();
|
||||
modbusAddressTextBox.Text = config.ModbusAddress.ToString();
|
||||
vValveRangeLoTextBox.Text = config.VirtualValvesRangeLo.ToString();
|
||||
vValveRangeHiTextBox.Text = config.VirtualValvesRangeHi.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
variantComboBox.Enabled = true;
|
||||
modbusAddressTextBox.Enabled = true;
|
||||
vValveRangeLoTextBox.Enabled = true;
|
||||
vValveRangeHiTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify current user controls for validity.
|
||||
/// Called when user wants to close/save the configuration.
|
||||
/// </summary>
|
||||
/// <returns>See VerifyFlags</returns>
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Parent Name'";
|
||||
}
|
||||
if (!variantComboBox.Items.Contains(variantComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Variant'";
|
||||
}
|
||||
if (!int.TryParse(modbusAddressTextBox.Text, out dummy) || dummy < 0 || dummy > 255)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Modbus Address' should be between 0 and 255";
|
||||
}
|
||||
if (!int.TryParse(vValveRangeLoTextBox.Text, out dummy) || dummy < 0 || dummy > 63)
|
||||
{
|
||||
message += "Virtual valves range Lo is invalid";
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
}
|
||||
if (!int.TryParse(vValveRangeHiTextBox.Text, out dummy) || dummy < 0 || dummy > 63)
|
||||
{
|
||||
message += "Virtual valves range Hi is invalid";
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save settings to the configuration class.
|
||||
/// </summary>
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
this.Name = nameTextBox.Text;
|
||||
config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
|
||||
for (QuidoVariant v = 0; v < QuidoVariant.Count; v++)
|
||||
{
|
||||
if (variantComboBox.Text == v.ToString()) { config.Variant = v; break; }
|
||||
}
|
||||
config.ModbusAddress = (byte)int.Parse(modbusAddressTextBox.Text);
|
||||
config.VirtualValvesRangeLo = int.Parse(vValveRangeLoTextBox.Text);
|
||||
config.VirtualValvesRangeHi = int.Parse(vValveRangeHiTextBox.Text);
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,30 @@
|
||||
///
|
||||
/// Copyright (c) 2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Papouch
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { PapouchCB.ResetStaticProperties(); }
|
||||
|
||||
/// <summary>Max. number of components of this class in the system</summary>
|
||||
public int MaxCount { get { return 1; } }
|
||||
|
||||
public IComponent DummyComponent() { return new PapouchCB(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new PapouchCB(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new PapouchCBCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(PapouchCBCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
///
|
||||
/// Copyright (c) 2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using Dirichlet.Numerics;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using TBF.Rig.Modbus;
|
||||
using TBF.Rig.Sequences;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Papouch
|
||||
{
|
||||
public class PapouchCB : ComponentBase, IControlBoard, IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(PapouchCB));
|
||||
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
|
||||
|
||||
readonly PapouchCBCfg cbCfg;
|
||||
readonly GenericDevices.IModbus modbus;
|
||||
|
||||
UInt32 currentOutputs;
|
||||
bool outputsInitialized;
|
||||
DateTime lastOutputsChange;
|
||||
int lastStateMachineTime = 0;
|
||||
///
|
||||
UInt128 benchModelRoute;
|
||||
UInt128 valvesToInvert; /// Route = valesToInvert ^ RequiredRouteWithoutInvertedVlaves
|
||||
readonly UInt128 routeMask; /// This mask masks out virtual valves, routeMask is set in the constructor
|
||||
///
|
||||
OutputPath devices;
|
||||
|
||||
|
||||
enum SelectedOp
|
||||
{
|
||||
None,
|
||||
SetFlow,
|
||||
QueryMeasurementEnd,
|
||||
}
|
||||
SelectedOp scheduledOp;
|
||||
SelectedOp runningOp;
|
||||
///
|
||||
bool opCompleted; /// true = Operation was completed and waits for Stop();
|
||||
|
||||
|
||||
public PapouchCB()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public PapouchCB(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
cbCfg = cfg as PapouchCBCfg;
|
||||
|
||||
modbus = (GenericDevices.IModbus)TbfComponents.FindComponent(cfg.ParentName, components);
|
||||
if (modbus == null) throw new Exception("Cannot find " + Name + " parent");
|
||||
|
||||
routeMask = 0;
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
if (i < cbCfg.VirtualValvesRangeLo || i > cbCfg.VirtualValvesRangeHi)
|
||||
{
|
||||
routeMask = routeMask | ((UInt128)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
TBF.UiBridge.Bridge.RouteChangeHandler += delegate(object sndr, TBF.UiBridge.RouteChangeArgs args)
|
||||
{
|
||||
UInt128 mask = ((UInt128)1) << args.BitNr;
|
||||
if ((benchModelRoute & mask) == 0)
|
||||
{
|
||||
benchModelRoute |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
benchModelRoute &= (~mask);
|
||||
}
|
||||
};
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public void SpecifyInvertedValves(UInt128 valvesToInvert)
|
||||
{
|
||||
this.valvesToInvert = valvesToInvert;
|
||||
this.benchModelRoute = valvesToInvert;
|
||||
}
|
||||
|
||||
///
|
||||
/// IDevice interface
|
||||
///
|
||||
public void Initialize()
|
||||
{
|
||||
outputsInitialized = false;
|
||||
runningOp = SelectedOp.None;
|
||||
}
|
||||
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if (cbCfg.DebugLevel == Config.Entities.DebugMode.Simulate) return;
|
||||
|
||||
if (modbus.ReceivedTelegrams[cbCfg.ModbusAddress].Count > 0)
|
||||
{
|
||||
byte[] telegram = modbus.ReceivedTelegrams[cbCfg.ModbusAddress].Dequeue();
|
||||
|
||||
if ((telegram.Length >= 8) && (telegram[1] == 0x11) && (telegram[2] == telegram.Length - 5))
|
||||
{
|
||||
int msgLen = telegram.Length - 7;
|
||||
byte modbusAddress = telegram[3];
|
||||
string msg = Encoding.ASCII.GetString(telegram, 5, msgLen);
|
||||
string s = string.Format("QuidoRS detected: Address={0}, Message={1}", modbusAddress, msg);
|
||||
Debug.WriteLine(s);
|
||||
log.Warn(s);
|
||||
}
|
||||
|
||||
if ((telegram.Length == 6) && (telegram[1] == 0x02) && (telegram[2] == telegram.Length - 5))
|
||||
{
|
||||
int inputData = telegram[3];
|
||||
string s = string.Format("QuidoRS inputs: {0}", inputData);
|
||||
Debug.WriteLine(s);
|
||||
log.Warn(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RunDeviceAfter()
|
||||
{
|
||||
if (currentOutputs != (UInt32)(benchModelRoute & 0xFFFFFFFF) || !outputsInitialized || (StateMachine.Time - lastStateMachineTime) >= 3)
|
||||
{
|
||||
SetOutputs((UInt32)(benchModelRoute & 0xFFFFFFFF));
|
||||
}
|
||||
else
|
||||
{
|
||||
RequestInputs();
|
||||
}
|
||||
|
||||
ProcessData.UpdateMeasuredValuesAndSetpoints();
|
||||
TBF.UiBridge.Bridge.OnStateMachineTick(this, new TBF.UiBridge.StateMachineTickEventArgs(benchModelRoute,
|
||||
ProcessData.MsrmntAvailableFlags,
|
||||
ProcessData.MeasuredValues,
|
||||
ProcessData.AltStrings,
|
||||
ProcessData.Setpoints));
|
||||
}
|
||||
|
||||
public void StopDevice()
|
||||
{
|
||||
SendOutputs(0);
|
||||
}
|
||||
|
||||
public void StopDevice2() { }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set outputs of QuidoRS board
|
||||
/// </summary>
|
||||
/// <param name="outputs">output value</param>
|
||||
public void SetOutputs(UInt32 outputs)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
currentOutputs = outputs;
|
||||
}
|
||||
SendOutputs(currentOutputs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set bit(s) specified by a bitMask. Leave other bits unaffeced.
|
||||
/// </summary>
|
||||
/// <param name="bitMask">Specifies bit(s) to set</param>
|
||||
/// <param name="outputs">output value</param>
|
||||
public void SetBit(UInt32 bitMask)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
currentOutputs = currentOutputs | bitMask;
|
||||
}
|
||||
SendOutputs(currentOutputs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset bit(s) specified by a bitMask. Leave other bits unaffeced.
|
||||
/// </summary>
|
||||
/// <param name="bitMask">Specifies bit(s) to reset</param>
|
||||
/// <param name="outputs">output value</param>
|
||||
public void ResetBit(UInt32 bitMask)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
currentOutputs = currentOutputs & (~bitMask);
|
||||
}
|
||||
SendOutputs(currentOutputs);
|
||||
}
|
||||
|
||||
private void RequestInputs()
|
||||
{
|
||||
byte addr = cbCfg.ModbusAddress;
|
||||
byte cmd = (byte)Function.ReadSingleInput;
|
||||
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 2, 0, 0 });
|
||||
}
|
||||
|
||||
private void SendOutputs(UInt32 outputs)
|
||||
{
|
||||
byte addr = cbCfg.ModbusAddress;
|
||||
byte cmd = (byte)Function.ForceMultipleCoils;
|
||||
byte dataLo = (byte)(outputs & 0xFF);
|
||||
byte data2 = (byte)(outputs >> 8);
|
||||
byte data3 = (byte)(outputs >> 16);
|
||||
byte dataHi = (byte)(outputs >> 24);
|
||||
|
||||
if (cbCfg.Variant == QuidoVariant.QuidoRS_4_4)
|
||||
{
|
||||
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 4, 1, dataLo, 0, 0 });
|
||||
}
|
||||
else if (cbCfg.Variant == QuidoVariant.QuidoRS_8_8)
|
||||
{
|
||||
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 8, 1, dataLo, 0, 0 });
|
||||
}
|
||||
else if (cbCfg.Variant == QuidoVariant.QuidoRS_2_16)
|
||||
{
|
||||
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 16, 2, dataLo, data2, 0, 0 });
|
||||
}
|
||||
else if (cbCfg.Variant == QuidoVariant.QuidoRS_2_32)
|
||||
{
|
||||
modbus.SendMessage(new byte[] { addr, cmd, 0, 0, 0, 32, 4, dataLo, data2, data3, dataHi, 0, 0 });
|
||||
}
|
||||
|
||||
outputsInitialized = true;
|
||||
lastOutputsChange = DateTime.Now;
|
||||
lastStateMachineTime = StateMachine.Time;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// IControlBoard interface
|
||||
///
|
||||
|
||||
public OutputPath Devices
|
||||
{
|
||||
set { devices = value; }
|
||||
get { return devices; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Route: 128-bit word representing the current state of all valves and pumps
|
||||
/// </summary>
|
||||
public UInt128 Route { get { return benchModelRoute; } }
|
||||
|
||||
public UInt64 DigitalInputs { get { return 0; } }
|
||||
|
||||
public double RefFrequency { get { return 0; } }
|
||||
public double RefFlow { get { return 0; } }
|
||||
|
||||
///
|
||||
/// Last test result
|
||||
///
|
||||
public int RefPulses { get { return 0; } }
|
||||
public double TestTime { get { return 1.0; } }
|
||||
public int RefPulsesWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? 0 : 0; }
|
||||
public int PulsesWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? 0 : 0; }
|
||||
public double TestTimeWM(int wmNr1) { return (wmNr1 > 0 && wmNr1 <= Config.Data.WMsCount) ? 1.0 : 1.0; }
|
||||
|
||||
|
||||
public void ClearProcessValues() { }
|
||||
|
||||
/// <summary>
|
||||
/// Set valves to new positions.
|
||||
/// </summary>
|
||||
/// <param name="valvesToOpen">'UInt128' with bits of valves to open set to '1'</param>
|
||||
/// <param name="valvesToClose">'UInt128' with bits of valves to close set to '1'</param>
|
||||
/// <returns>'UInt128' with bits of valves that have changed set to '1'</returns>
|
||||
public UInt128 SetValves(UInt128 valvesToOpen, UInt128 valvesToClose, IList<BuiltIn.ValveEx.Valve> extendedValves)
|
||||
{
|
||||
UInt128 oldRoute = benchModelRoute;
|
||||
benchModelRoute = (((benchModelRoute ^ valvesToInvert) | valvesToOpen) & (~valvesToClose)) ^ valvesToInvert;
|
||||
foreach (var extV in extendedValves) extV.UpdateRoute(ref benchModelRoute);
|
||||
log.DebugFormat("SetValves(x,x), new route = {0}", Utils.RouteToStr(benchModelRoute));
|
||||
UInt128 retVal = oldRoute ^ benchModelRoute;
|
||||
|
||||
log.DebugFormat("{0}.SetValves({1}, {2}) returns {3}", Name, valvesToOpen.ToString("X"), valvesToClose.ToString("X"), retVal.ToString("X"));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open one valve and/or close one valve.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="valveOpen">Valve to be opened</param>
|
||||
/// <param name="valveClose">Valve to be closed</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation SetValvesOp(IValve valveOpen, IValve valveClose)
|
||||
{
|
||||
IOperation op = new BuiltIn.SetValvesOp(this, valveOpen, valveClose);
|
||||
log.DebugFormat("{0}.SetValvesOp(vO, vC) returns {1}", Name, (op != null) ? op.ToString() : "null");
|
||||
return op;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open and/or close multiple valves.
|
||||
/// Events: ValvesSet
|
||||
/// </summary>
|
||||
/// <param name="valvesOpen">A list of valves to be opened</param>
|
||||
/// <param name="valvesClose">A list of valves to be closed</param>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation SetValvesOp(IList<IValve> valvesOpen, IList<IValve> valvesClose)
|
||||
{
|
||||
IOperation op = new BuiltIn.SetValvesOp(this, valvesOpen, valvesClose);
|
||||
log.DebugFormat("{0}.SetValvesOp(vlvsO, vlvsC) returns {1}", Name, (op != null) ? op.ToString() : "null");
|
||||
return op;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open start/stop valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation OpenStartValveOp()
|
||||
{
|
||||
IOperation op = new BuiltIn.SetValvesOp(this, true, devices);
|
||||
log.DebugFormat("{0}.OpenStartValveOp({1}) returns {2}", Name, devices.StartValve1.Name, (op != null) ? op.ToString() : "null");
|
||||
return op;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close start/stop valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation CloseStartValveOp()
|
||||
{
|
||||
IOperation op = new BuiltIn.SetValvesOp(this, false, devices);
|
||||
log.DebugFormat("{0}.CloseStartValveOp({1}) returns {2}", Name, devices.StartValve1.Name, (op != null) ? op.ToString() : "null");
|
||||
return op;
|
||||
}
|
||||
|
||||
public float ValveOpenCloseTime { get { return 0.1f; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns operation to display a prompt message to set the flow.
|
||||
/// </summary>
|
||||
/// <param name="reqrdFlowLo">Lower limit</param>
|
||||
/// <param name="reqrdFlowHi">Upper limit</param>
|
||||
/// <param name="measuredFlow">Reference to a box for the measured flow or null</param>
|
||||
/// <param name="timeout">Flow set timeout</param>
|
||||
/// <returns>Operation</returns>
|
||||
public IOperation SetFlowOp(double reqrdFlowLo, double reqrdFlowHi, TBF.Boxes.DoubleBox measuredFlow, int timeout)
|
||||
{
|
||||
string loLimStr = reqrdFlowLo.ToString(Config.Utils.SignificantDigitsToFmt(reqrdFlowLo, 2));
|
||||
string hiLimStr = reqrdFlowHi.ToString(Config.Utils.SignificantDigitsToFmt(reqrdFlowHi, 2));
|
||||
this.promptMsg = string.Format("Set flow measured by {0} withing {1} and {2} m3/h by regulation valve {3}",
|
||||
devices.FlowMeter.Name, loLimStr, hiLimStr, devices.RegValve.Name);
|
||||
this.backColor = System.Drawing.Color.LightSalmon;
|
||||
|
||||
scheduledOp = SelectedOp.SetFlow;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOperation StopFlowRegulationOp()
|
||||
{
|
||||
return new Operations.ReturnGivenEventOp(Event.FlowRegulationStopped);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a test, Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="iParam">Int32 parameter 1</param>
|
||||
/// <param name="dParam1">Double parameter 1 (alternative lower flow limit)</param>
|
||||
/// <param name="dParam2">Double parameter 2 (alternative upper flow limit)</param>
|
||||
/// <returns>Operation</returns>
|
||||
public IOperation StartTestOp(Test test, int iParam = 0, double dParam1 = 0, double dParam2 = 0)
|
||||
{
|
||||
currentTest = test;
|
||||
return new Operations.ReturnGivenEventOp(Event.MeasurementStarted);
|
||||
}
|
||||
|
||||
public IOperation QueryMeasurementEndOp()
|
||||
{
|
||||
scheduledOp = SelectedOp.QueryMeasurementEnd;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOperation ReadDiverterTransitionOp(bool isStart, Sequences.Statistics plotter, int batchNr, string testName, int repetition)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IOperation StopPreviousOp()
|
||||
{
|
||||
return new Operations.ReturnGivenEventOp(Event.PreviousStopped);
|
||||
}
|
||||
|
||||
|
||||
Test currentTest;
|
||||
|
||||
string promptMsg;
|
||||
System.Drawing.Color backColor;
|
||||
TBF.Rig.Operations.MessageBoxForm messageBoxForm;
|
||||
///
|
||||
delegate void MessageBoxFormDlgt(PapouchCB myRef);
|
||||
///
|
||||
void OpenFormDlg(PapouchCB myRef)
|
||||
{
|
||||
myRef.messageBoxForm = new TBF.Rig.Operations.MessageBoxForm(promptMsg, backColor);
|
||||
messageBoxForm.Show();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Start selected operation
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (scheduledOp == SelectedOp.None || runningOp != SelectedOp.None)
|
||||
{
|
||||
throw new Exception("Sequence error");
|
||||
}
|
||||
|
||||
runningOp = scheduledOp;
|
||||
scheduledOp = SelectedOp.None;
|
||||
|
||||
if (runningOp == SelectedOp.SetFlow)
|
||||
{
|
||||
Program.MainWnd.Invoke(new MessageBoxFormDlgt(OpenFormDlg), this);
|
||||
}
|
||||
else if (runningOp == SelectedOp.QueryMeasurementEnd)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Run selected operation
|
||||
/// </summary>
|
||||
/// <returns>Event.None or Event.FlowReached or Event.MeasurementCompleted </returns>
|
||||
public Event Run()
|
||||
{
|
||||
if (runningOp == SelectedOp.SetFlow)
|
||||
{
|
||||
if (opCompleted || messageBoxForm.Completed)
|
||||
{
|
||||
opCompleted = true;
|
||||
messageBoxForm = null;
|
||||
return Event.FlowReached;
|
||||
}
|
||||
}
|
||||
else if (runningOp == SelectedOp.QueryMeasurementEnd)
|
||||
{
|
||||
if (opCompleted) return Event.MeasurementCompleted;
|
||||
|
||||
double currentMass = TBF.Rig.Sequences.ProcessData.Mass.Val;
|
||||
|
||||
if (currentMass - TBF.Rig.Sequences.ProcessData.StartMass.Val >= currentTest.Volume)
|
||||
{
|
||||
opCompleted = true;
|
||||
return Event.MeasurementCompleted;
|
||||
}
|
||||
}
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop this operation
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (runningOp == SelectedOp.SetFlow)
|
||||
{
|
||||
if (messageBoxForm != null)
|
||||
{
|
||||
messageBoxForm.OnCloseThisForm(this, null);
|
||||
messageBoxForm = null;
|
||||
}
|
||||
}
|
||||
|
||||
runningOp = SelectedOp.None;
|
||||
opCompleted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
///
|
||||
/// Copyright (c) 2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Papouch
|
||||
{
|
||||
public enum QuidoVariant
|
||||
{
|
||||
QuidoRS_4_4,
|
||||
QuidoRS_8_8,
|
||||
QuidoRS_2_16,
|
||||
QuidoRS_2_32,
|
||||
Count
|
||||
}
|
||||
|
||||
public class PapouchCBCfg : ComponentCfgBase, Generic.IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(PapouchCBCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new CBoardCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public byte ModbusAddress; /// 1..254
|
||||
public QuidoVariant Variant; /// QuidoRS_2_16, QuidoRS_4_4 or QuidoRS_8_8
|
||||
public int VirtualValvesRangeLo;
|
||||
public int VirtualValvesRangeHi;
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
PapouchCBCfg()
|
||||
{
|
||||
Name = "CB";
|
||||
ParentName = "Modbus";
|
||||
ModbusAddress = 1;
|
||||
Variant = QuidoVariant.QuidoRS_2_32;
|
||||
VirtualValvesRangeLo = 50;
|
||||
VirtualValvesRangeHi = 59;
|
||||
}
|
||||
|
||||
public PapouchCBCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
this.Factory = factory;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("name={0}({1}) address={2} variant={3} vvLo={4} vvHi={5}",
|
||||
Name,
|
||||
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
|
||||
ModbusAddress,
|
||||
Variant,
|
||||
VirtualValvesRangeLo,
|
||||
VirtualValvesRangeHi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using Dirichlet.Numerics;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public enum ActionID
|
||||
{
|
||||
/// Basic
|
||||
ChangeRoute = 1, /// Change digital outputs (route)
|
||||
MeasureFlow = 2, /// Activate a flow meter to measure the flow
|
||||
SetFlow = 4, /// Set flow
|
||||
StartTest = 8, /// Start a test
|
||||
StopTest = 0x10, /// Stop a test or a flow regulation
|
||||
RegVlvIncrMove = 0x20,
|
||||
RegVlvMoveToPos = 0x40,
|
||||
RegVlvStop = 0x80,
|
||||
SwitchDiverter = 0x100, /// Switch diverter to tank/sink
|
||||
|
||||
/// Advanced
|
||||
GetDiverterTransitionData,
|
||||
GetScopeAnalyzerData,
|
||||
ResetScopeAnalyzer,
|
||||
GetSwitchCounterData,
|
||||
}
|
||||
|
||||
public class Action
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Action));
|
||||
|
||||
public ActionID ActionId { get; set; }
|
||||
public ulong Route { get; set; } /// ChangeRoute argument
|
||||
public int FlowMId { get; set; } /// SetFlow, MeasureFlow and StartTest argument
|
||||
public int RegVId { get; set; } /// SetFlow and StartTest argument
|
||||
public int DivId { get; set; } /// StartTest and SwitchDiverter argument
|
||||
public bool IsSyncMethod { get; set; } /// StartTest argument
|
||||
public bool IsDivUsed { get; set; } /// StartTest argument
|
||||
public bool ToTank { get; set; } /// SwitchDiverter argument
|
||||
public int TotalPulsesCount { get; set; } /// StartTest argument
|
||||
public int MassPulsesCount { get; set; } /// StartTest argument
|
||||
public RegValveMode RegVMode { get; set; } /// SetFlow, RegVlvIncrMove, RegVlvMoveToPos, RegVlvStop
|
||||
public int RVMovePar1 { get; set; } /// SetFlow, RegVlvIncrMove, RegVlvMoveToPos
|
||||
public int RVMovePar2 { get; set; } /// SetFlow, RegVlvIncrMove, RegVlvMoveToPos
|
||||
public int PID { get; set; } /// SetFlow
|
||||
public int TolerRV { get; set; } /// SetFlow
|
||||
public int StabTime { get; set; } /// SetFlow
|
||||
public int DivThreshold { get; set; } /// StartTest argument
|
||||
int StartStop { get; set; } /// Implicitly used by StartTest and StopTest: -1=not defined, 0=stop, 1=start
|
||||
|
||||
|
||||
public Action()
|
||||
{
|
||||
/// Values -1 indicate the related arguments are not used yet
|
||||
FlowMId = -1;
|
||||
RegVId = -1;
|
||||
DivId = -1;
|
||||
RegVMode = RegValveMode.None;
|
||||
StartStop = -1;
|
||||
|
||||
/// These values are used by one action type only. No conflicts possible
|
||||
Route = 0;
|
||||
TotalPulsesCount = 0;
|
||||
MassPulsesCount = 0;
|
||||
RVMovePar1 = 0;
|
||||
RVMovePar2 = 0;
|
||||
}
|
||||
|
||||
|
||||
public bool IsStart()
|
||||
{
|
||||
return (ActionId & (ActionID.SetFlow | ActionID.StartTest)) != 0;
|
||||
}
|
||||
|
||||
public bool IsStop()
|
||||
{
|
||||
return (ActionId & ActionID.StopTest) != 0;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action ChangeRoute(ulong route)
|
||||
{
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.ChangeRoute,
|
||||
Route = route,
|
||||
};
|
||||
}
|
||||
void SetChangeRouteArgs(Action action)
|
||||
{
|
||||
Route = action.Route;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedChangeRouteArgs(Action newAction)
|
||||
{
|
||||
return Route == newAction.Route;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action MeasureFlow(int flowMeterId)
|
||||
{
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.MeasureFlow,
|
||||
FlowMId = flowMeterId,
|
||||
};
|
||||
}
|
||||
void SetMeasureFlowArgs(Action action)
|
||||
{
|
||||
FlowMId = action.FlowMId;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedMeasureFlowArgs(Action newAction)
|
||||
{
|
||||
return (FlowMId == -1 || FlowMId == newAction.FlowMId);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action SetFlow(int flowMeterId, int regValveId, double freqLo, double freqHi,
|
||||
int pid, int tolerRV, int stabTime)
|
||||
{
|
||||
int rvMovePar1 = Convert.ToInt32(Math.Round(13.1072 * freqLo));
|
||||
int rvMovePar2 = Convert.ToInt32(Math.Round(13.1072 * freqHi));
|
||||
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.SetFlow,
|
||||
FlowMId = flowMeterId,
|
||||
RegVId = regValveId,
|
||||
RegVMode = RegValveMode.TargetFrequency,
|
||||
RVMovePar1 = rvMovePar1,
|
||||
RVMovePar2 = rvMovePar2,
|
||||
PID = pid,
|
||||
TolerRV = tolerRV,
|
||||
StabTime = stabTime,
|
||||
};
|
||||
}
|
||||
void SetSetFlowArgs(Action action)
|
||||
{
|
||||
FlowMId = action.FlowMId;
|
||||
RegVId = action.RegVId;
|
||||
RegVMode = action.RegVMode;
|
||||
RVMovePar1 = action.RVMovePar1;
|
||||
RVMovePar2 = action.RVMovePar2;
|
||||
PID = action.PID;
|
||||
TolerRV = action.TolerRV;
|
||||
StabTime = action.StabTime;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedSetFlowArgs(Action newAction)
|
||||
{
|
||||
return (FlowMId == -1 || FlowMId == newAction.FlowMId) &&
|
||||
(RegVId == -1 || RegVId == newAction.RegVId) &&
|
||||
(RegVMode == RegValveMode.None || RegVMode == newAction.RegVMode) &&
|
||||
(RVMovePar1 == -1 || RVMovePar1 == newAction.RVMovePar1) &&
|
||||
(RVMovePar2 == -1 || RVMovePar2 == newAction.RVMovePar2);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action StartTest(int flowMId, int divId, int divThreshold, bool isSyncMethod,
|
||||
bool isDivUsed, int totalPulsesCount, int massPulsesCount = -1)
|
||||
{
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.StartTest,
|
||||
FlowMId = flowMId,
|
||||
DivId = divId,
|
||||
DivThreshold = divThreshold,
|
||||
IsSyncMethod = isSyncMethod,
|
||||
IsDivUsed = isDivUsed,
|
||||
TotalPulsesCount = totalPulsesCount,
|
||||
MassPulsesCount = (massPulsesCount == -1) ? totalPulsesCount : massPulsesCount,
|
||||
StartStop = 1,
|
||||
};
|
||||
}
|
||||
void SetStartTestArgs(Action action)
|
||||
{
|
||||
FlowMId = action.FlowMId;
|
||||
DivId = action.DivId;
|
||||
DivThreshold = action.DivThreshold;
|
||||
IsSyncMethod = action.IsSyncMethod;
|
||||
IsDivUsed = action.IsDivUsed;
|
||||
TotalPulsesCount = action.TotalPulsesCount;
|
||||
MassPulsesCount = action.MassPulsesCount;
|
||||
StartStop = 1;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedStartTestArgs(Action newAction)
|
||||
{
|
||||
return (FlowMId == -1 || FlowMId == newAction.FlowMId) &&
|
||||
(DivId == -1 || DivId == newAction.DivId) &&
|
||||
(StartStop == -1 || StartStop == 1);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action StopTest()
|
||||
{
|
||||
return new Action()
|
||||
{
|
||||
ActionId = ActionID.StopTest,
|
||||
StartStop = 0,
|
||||
};
|
||||
}
|
||||
void SetStopTestArgs(Action action)
|
||||
{
|
||||
StartStop = 0;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedStopTestArgs(Action action)
|
||||
{
|
||||
return (StartStop == -1 || StartStop == 0);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action RegVlvIncrMove(int regValveId, double timeSec)
|
||||
{
|
||||
int rvMovePar = Math.Abs(Convert.ToInt32(Math.Round(timeSec / 0.050))); /// Step is 50 ms
|
||||
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.RegVlvIncrMove,
|
||||
RegVId = regValveId,
|
||||
RegVMode = (timeSec >= 0) ? RegValveMode.PulseWidth : (RegValveMode.PulseWidth | RegValveMode.NegPulseWidth),
|
||||
RVMovePar1 = rvMovePar,
|
||||
RVMovePar2 = rvMovePar,
|
||||
};
|
||||
}
|
||||
void SetRegVlvIncrMoveArgs(Action action)
|
||||
{
|
||||
RegVId = action.RegVId;
|
||||
RegVMode = action.RegVMode;
|
||||
RVMovePar1 = action.RVMovePar1;
|
||||
RVMovePar2 = action.RVMovePar2;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedRegVlvIncrMoveArgs(Action newAction)
|
||||
{
|
||||
return (RegVId == -1 || RegVId == newAction.RegVId) &&
|
||||
(RegVMode == RegValveMode.None || RegVMode == newAction.RegVMode);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action RegVlvMoveToPos(int regValveId, double positionLo, double positionHi = -1)
|
||||
{
|
||||
int rvMovePar1, rvMovePar2; /// TODO
|
||||
///
|
||||
if (positionHi < 0)
|
||||
{
|
||||
/// Center position specified, calculate a range
|
||||
rvMovePar1 = 0; // TODO
|
||||
rvMovePar2 = 0; // TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Lower and upper range of position specified
|
||||
rvMovePar1 = 0; // TODO
|
||||
rvMovePar2 = 0; // TODO
|
||||
}
|
||||
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.RegVlvMoveToPos,
|
||||
RegVId = regValveId,
|
||||
RegVMode = RegValveMode.TargetPosition,
|
||||
RVMovePar1 = rvMovePar1,
|
||||
RVMovePar2 = rvMovePar2,
|
||||
};
|
||||
}
|
||||
void SetRegVlvMoveToPosArgs(Action action)
|
||||
{
|
||||
RegVId = action.RegVId;
|
||||
RegVMode = action.RegVMode;
|
||||
RVMovePar1 = action.RVMovePar1;
|
||||
RVMovePar2 = action.RVMovePar2;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedRegVlvMoveToPosArgs(Action newAction)
|
||||
{
|
||||
return (RegVId == -1 || RegVId == newAction.RegVId) &&
|
||||
(RegVMode == RegValveMode.None || RegVMode == newAction.RegVMode);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action RegVlvStop(int regValveId)
|
||||
{
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.RegVlvStop,
|
||||
RegVId = regValveId,
|
||||
RegVMode = RegValveMode.Stop,
|
||||
RVMovePar1 = 0,
|
||||
RVMovePar2 = 0,
|
||||
};
|
||||
}
|
||||
void SetRegVlvStopArgs(Action action)
|
||||
{
|
||||
RegVId = action.RegVId;
|
||||
RegVMode = action.RegVMode;
|
||||
RVMovePar1 = action.RVMovePar1;
|
||||
RVMovePar2 = action.RVMovePar2;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedRegVlvStopArgs(Action newAction)
|
||||
{
|
||||
return (RegVId == -1 || RegVId == newAction.RegVId) &&
|
||||
(RegVMode == RegValveMode.None || RegVMode == newAction.RegVMode);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action SwitchDiverter(int divId, bool toTank)
|
||||
{
|
||||
return new Action
|
||||
{
|
||||
ActionId = ActionID.SwitchDiverter,
|
||||
DivId = divId,
|
||||
ToTank = toTank,
|
||||
};
|
||||
}
|
||||
void SetSwitchDiverterArgs(Action action)
|
||||
{
|
||||
DivId = action.DivId;
|
||||
ToTank = action.ToTank;
|
||||
}
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments (true = yes)
|
||||
bool CheckSharedSwitchDiverterArgs(Action action)
|
||||
{
|
||||
return (DivId == -1 || DivId == action.DivId);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
void SetArgs(Action action)
|
||||
{
|
||||
ActionId |= action.ActionId;
|
||||
|
||||
switch (action.ActionId)
|
||||
{
|
||||
case ActionID.ChangeRoute: SetChangeRouteArgs(action); return;
|
||||
case ActionID.MeasureFlow: SetMeasureFlowArgs(action); return;
|
||||
case ActionID.SetFlow: SetSetFlowArgs(action); return;
|
||||
case ActionID.StartTest: SetStartTestArgs(action); return;
|
||||
case ActionID.StopTest: SetStopTestArgs(action); return;
|
||||
case ActionID.RegVlvIncrMove: SetRegVlvIncrMoveArgs(action); return;
|
||||
case ActionID.RegVlvMoveToPos: SetRegVlvMoveToPosArgs(action); return;
|
||||
case ActionID.RegVlvStop: SetRegVlvStopArgs(action); return;
|
||||
case ActionID.SwitchDiverter: SetSwitchDiverterArgs(action); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether new action arguments are compatible with alredy collected arguments
|
||||
/// </summary>
|
||||
/// <param name="action">Action to be executed together with already collected actions</param>
|
||||
/// <returns>true when compatible</returns>
|
||||
bool CheckSharedArgs(Action action)
|
||||
{
|
||||
switch (action.ActionId)
|
||||
{
|
||||
case ActionID.ChangeRoute: return CheckSharedChangeRouteArgs(action);
|
||||
case ActionID.MeasureFlow: return CheckSharedMeasureFlowArgs(action);
|
||||
case ActionID.SetFlow: return CheckSharedSetFlowArgs(action);
|
||||
case ActionID.StartTest: return CheckSharedStartTestArgs(action);
|
||||
case ActionID.StopTest: return CheckSharedStopTestArgs(action);
|
||||
case ActionID.RegVlvIncrMove: return CheckSharedRegVlvIncrMoveArgs(action);
|
||||
case ActionID.RegVlvMoveToPos: return CheckSharedRegVlvMoveToPosArgs(action);
|
||||
case ActionID.RegVlvStop: return CheckSharedRegVlvStopArgs(action);
|
||||
case ActionID.SwitchDiverter: return CheckSharedSwitchDiverterArgs(action);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------------------------
|
||||
public static Action FetchNonConflictingActions(Queue<Action> queue)
|
||||
{
|
||||
log.Debug("Fetching non conflicting actions:");
|
||||
|
||||
if (queue == null || queue.Count == 0) return null;
|
||||
|
||||
Action resultA = queue.Dequeue();
|
||||
log.Debug(resultA.ToString());
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var peekA = queue.Peek();
|
||||
if ((resultA.ActionId & peekA.ActionId) == 0 && resultA.CheckSharedArgs(peekA) == true)
|
||||
{
|
||||
/// ActionId would not be repeated and arguments are compatible => apply the new action
|
||||
resultA.SetArgs(peekA);
|
||||
log.Debug(peekA.ToString());
|
||||
queue.Dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Leave actions in the queue and quit the loop as the next scheduled action is incompatible
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return resultA;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string args;
|
||||
switch (ActionId)
|
||||
{
|
||||
case ActionID.ChangeRoute:
|
||||
args = string.Format("Route={0}", Route.ToString("X16"));
|
||||
break;
|
||||
case ActionID.MeasureFlow:
|
||||
args = string.Format("Etalon={0}", FlowMId);
|
||||
break;
|
||||
case ActionID.SetFlow:
|
||||
args = string.Format("Etalon={0} RV={1} Par1={2} Par2={3}", FlowMId, RegVId, RVMovePar1, RVMovePar2);
|
||||
break;
|
||||
case ActionID.StartTest:
|
||||
args = string.Format("Etalon={0} TotalP={1} MassP={2}", FlowMId, TotalPulsesCount, MassPulsesCount);
|
||||
break;
|
||||
case ActionID.RegVlvIncrMove:
|
||||
args = string.Format("Time={0}ms", (RegVMode & RegValveMode.NegPulseWidth) != 0 ? -50 * RVMovePar1 : 50 * RVMovePar1);
|
||||
break;
|
||||
case ActionID.RegVlvMoveToPos:
|
||||
args = string.Format("Position={0}%", 0); /// TODO
|
||||
break;
|
||||
default:
|
||||
args = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
return string.Format(" {0} {1}", ActionId, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class DivTransitionData
|
||||
{
|
||||
public const int MessageLen = 255;
|
||||
public const byte MessageCode = (byte)'K';
|
||||
|
||||
/// Diverter transition data
|
||||
const int samplesCount = 245;
|
||||
int DiverterTime_ms;
|
||||
byte[] CurveRaw;
|
||||
|
||||
DivTransitionData()
|
||||
{
|
||||
CurveRaw = new byte[samplesCount];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns tru when receive data fit the message frame
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="cumulativeSums">Cumulative sums of received data bytes</param>
|
||||
/// <param name="rcvdBytesCount">Received bytes count</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
/// <returns>true when frame fits data</returns>
|
||||
public static bool FrameFitsData(byte[] rcvdData, int[] cumulativeSums, int rcvdBytesCount, int offset)
|
||||
{
|
||||
if (offset + MessageLen > rcvdBytesCount) return false;
|
||||
|
||||
int checksum = cumulativeSums[offset + MessageLen - 3] - cumulativeSums[offset];
|
||||
|
||||
return rcvdData[offset] == Const.STX &&
|
||||
rcvdData[offset + 1] == 0x01 &&
|
||||
rcvdData[offset + 2] == ((MessageLen - 5) & 0xFF) &&
|
||||
rcvdData[offset + 3] == MessageCode &&
|
||||
rcvdData[offset + MessageLen - 2] == (checksum & 0xFF) &&
|
||||
rcvdData[offset + MessageLen - 1] == ((checksum >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proces received data
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
public static DivTransitionData GetData(byte[] rcvdData, int offset)
|
||||
{
|
||||
var data = new DivTransitionData();
|
||||
data.DiverterTime_ms = Const.DivTimeResolution * rcvdData[offset + 4];
|
||||
for (int i = 0; i < samplesCount; i++)
|
||||
{
|
||||
data.CurveRaw[i] = rcvdData[offset + 6 + i];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class Const
|
||||
{
|
||||
public const byte STX = 0x10;
|
||||
public const int WMsCount = 20; /// water meters count
|
||||
public const int ADCsCount = 16; /// ADCs count: feedback from RV-s and diverters
|
||||
public const int RVsCount = 8; /// 0..7
|
||||
public const int FlowmtrsCount = 7; /// ID=1..7, ID=0 ... flowmeters 1,2,3 parallel
|
||||
public const int DivertersCount = 5; /// 1..5
|
||||
public const int DivTimeResolution = 2; /// [ms]
|
||||
public const double TimeResolution = 0.0002; /// [s]
|
||||
}
|
||||
|
||||
|
||||
public enum StatusP : ulong
|
||||
{
|
||||
/// byte 0
|
||||
FlowmtrNrMask = 0x7, /// bits 0,1,2
|
||||
TestInProgress = 0x8, /// bit 3
|
||||
TestCompleted = 0x10, /// bit 4
|
||||
ReadingCounters = 0x20, /// bit 5
|
||||
WaitingForDiverter = 0x40, /// bit 6
|
||||
TestWithDiverter = 0x80, /// bit 7
|
||||
/// byte 1
|
||||
TestWithRefFlowmtr = 0x100, /// bit 8
|
||||
DirectionOfDiverer = 0x200, /// bit 9
|
||||
SynchroMethod = 0x800, /// bit 11
|
||||
WaterMeterCalib = 0x1000, /// bit 12
|
||||
EmgcyStopActive = 0x2000, /// bit 13
|
||||
GateOn = 0x4000, /// bit 14
|
||||
TimeMeasurementEn = 0x8000, /// bit 15
|
||||
/// byte 2
|
||||
FrequencyMeasured = 0x80000, /// bit 19
|
||||
CoaxRegValveBusy = 0x200000, /// bit 21
|
||||
/// byte 3
|
||||
ADCError = 0x80000000, /// bit 31
|
||||
/// byte 4
|
||||
TimeoutOccured = 0x100000000, /// bit 32 (after 40s without communication)
|
||||
MeretAddresses = 0x200000000, /// bit 33
|
||||
ScopeBufferFull = 0x400000000, /// bit 34
|
||||
/// byte 5
|
||||
/// byte 6
|
||||
Flowmtr1Active = 0x1000000000000, /// bit 48
|
||||
Flowmtr2Active = 0x2000000000000, /// bit 49
|
||||
Flowmtr3Active = 0x4000000000000, /// bit 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class ExtremaData
|
||||
{
|
||||
public const int MessageLen = 253;
|
||||
public const byte MessageCode = (byte)'E';
|
||||
|
||||
// TODO: Implement member variables
|
||||
|
||||
ExtremaData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns tru when receive data fit the message frame
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="cumulativeSums">Cumulative sums of received data bytes</param>
|
||||
/// <param name="rcvdBytesCount">Received bytes count</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
/// <returns>true when frame fits data</returns>
|
||||
public static bool FrameFitsData(byte[] rcvdData, int[] cumulativeSums, int rcvdBytesCount, int offset)
|
||||
{
|
||||
if (offset + MessageLen > rcvdBytesCount) return false;
|
||||
|
||||
int checksum = cumulativeSums[offset + MessageLen - 3] - cumulativeSums[offset];
|
||||
|
||||
return rcvdData[offset] == Const.STX &&
|
||||
rcvdData[offset + 1] == 0x01 &&
|
||||
rcvdData[offset + 2] == ((MessageLen - 5) & 0xFF) &&
|
||||
rcvdData[offset + 3] == MessageCode &&
|
||||
rcvdData[offset + MessageLen - 2] == (checksum & 0xFF) &&
|
||||
rcvdData[offset + MessageLen - 1] == ((checksum >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proces received data
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
public static ExtremaData GetData(byte[] rcvdData, int offset)
|
||||
{
|
||||
var data = new ExtremaData();
|
||||
|
||||
// TODO
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { UniCB.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new UniCB(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new UniCB(cfg); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new UniCBCfg("UniCB", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(UniCBCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class GeneralData
|
||||
{
|
||||
public const int MessageLen = 303;
|
||||
public const byte MessageCode = (byte)' ';
|
||||
|
||||
/// General data
|
||||
public ulong State; /// bytes 5,6,7,8,9,80,81 = 7 bytes = 56 bits
|
||||
public uint Chyby485;
|
||||
public ulong Vystupy;
|
||||
public uint[] StavDA = new uint[2];
|
||||
public double[] ReferenceFreq = new double[4];
|
||||
public int[] EtPulses = new int[Const.WMsCount + 1]; /// EtPulses[0]=total pulses, EtPulses[1..WMsCount] gated et.pulses for respective WM
|
||||
public int EtPulsesK;
|
||||
public int EtPulses2;
|
||||
public int EtPulses3;
|
||||
public int[] WMeterPuls = new int[Const.WMsCount + 1]; /// WMsCount = 20
|
||||
public double[] ImpulseTime = new double[Const.WMsCount + 1]; /// WMsCount = 20
|
||||
public uint[] RegVStatus = new uint[Const.RVsCount + 1 + 1]; /// RVsCount = 8, posledny rValveStatus[9] je prudovy
|
||||
public float[] RegVMoveTime = new float[Const.RVsCount];
|
||||
public int DivTime;
|
||||
public double Ttime; /// s
|
||||
public double TimeRef; /// s
|
||||
public ulong Vstupy;
|
||||
public Int16[] AnalogInput = new Int16[Const.ADCsCount];
|
||||
public int[] TemperatureRaw = new int[8];
|
||||
|
||||
|
||||
public GeneralData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns tru when receive data fit the message frame
|
||||
/// </summary>
|
||||
/// <param name="data">Received data</param>
|
||||
/// <param name="cumulativeSums">Cumulative sums of received data bytes</param>
|
||||
/// <param name="rcvdBytesCount">Received bytes count</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
/// <returns>true when frame fits data</returns>
|
||||
public static bool FrameFitsData(byte[] data, int[] cumulativeSums, int rcvdBytesCount, int offset)
|
||||
{
|
||||
if (offset + MessageLen > rcvdBytesCount) return false;
|
||||
|
||||
int checksum = cumulativeSums[offset + MessageLen - 3] - cumulativeSums[offset];
|
||||
|
||||
return data[offset] == Const.STX &&
|
||||
data[offset + 1] == 0x01 &&
|
||||
data[offset + 2] == ((MessageLen - 5) & 0xFF) &&
|
||||
data[offset + 3] == MessageCode &&
|
||||
data[offset + MessageLen - 2] == (checksum & 0xFF) &&
|
||||
data[offset + MessageLen - 1] == ((checksum >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Auxiliary functions
|
||||
/// </summary>
|
||||
/// <param name="data">Received data</param>
|
||||
/// <param name="offs">Offset to the files</param>
|
||||
/// <returns></returns>
|
||||
Int16 GetInt16(byte[] data, int offs) { return BitConverter.ToInt16(data, offs); }
|
||||
UInt16 GetUInt16(byte[] data, int offs) { return BitConverter.ToUInt16(data, offs); }
|
||||
UInt32 GetUInt24(byte[] data, int offs) { return BitConverter.ToUInt32(data, offs) & 0x00FFFFFF; }
|
||||
UInt32 GetUInt32(byte[] data, int offs) { return BitConverter.ToUInt32(data, offs); }
|
||||
UInt64 GetUInt40(byte[] data, int offs) { return BitConverter.ToUInt64(data, offs) & 0x000000FFFFFFFFFF; }
|
||||
UInt64 GetUInt64(byte[] data, int offs) { return BitConverter.ToUInt64(data, offs); }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Proces received data
|
||||
/// </summary>
|
||||
/// <param name="data">Received data</param>
|
||||
/// <param name="offs">Offset of the message</param>
|
||||
public void UpdateData(byte[] data, int offs)
|
||||
{
|
||||
State = GetUInt40(data, offs + (int)Poz.State) | /// Byte 5,6,7,8,9,80,81
|
||||
((ulong)data[offs + (int)Poz.Stat5] << 40) |
|
||||
((ulong)data[offs + (int)Poz.Stat6] << 48);
|
||||
|
||||
Vystupy = GetUInt64(data, offs + (int)Poz.Vyst); /// Byte 10 .. 17
|
||||
StavDA[1] = GetUInt16(data, offs + (int)Poz.SDA2); /// Byte 18,19
|
||||
Vstupy = GetUInt40(data, offs + (int)Poz.Vst); /// Byte 20,21,22,23,24
|
||||
|
||||
/// A/D converters: Feedback from RV-s and diverters
|
||||
for (int i = 0; i < Const.ADCsCount; i++) /// Byte 25 .. 56
|
||||
{
|
||||
#if DEBUG
|
||||
AnalogInput[Const.ADCsCount - 1 - i] = (short)(11 * (15 - i));
|
||||
#else
|
||||
AnalogInput[Const.ADCsCount - 1 - i] = GetInt16(data, offs + (int)Poz.Analogy + 2 * i);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Groch temperature meters
|
||||
for (int i = 0; i < 8; i++) /// byte 57 .. 72
|
||||
{
|
||||
TemperatureRaw[i] = GetInt16(data, offs + (int)Poz.Groch + 2 * i);
|
||||
}
|
||||
|
||||
EtPulses[0] = Convert.ToInt32(GetUInt24(data, offs + (int)Poz.Et1));/// Byte 73,74,75
|
||||
EtPulsesK = Convert.ToInt32(GetUInt24(data, offs + (int)Poz.EtK)); /// Byte 76,77,78
|
||||
byte spare1 = data[offs + (int)Poz.spare1]; /// byte 79
|
||||
byte spare2 = data[offs + (int)Poz.spare2]; /// byte 82
|
||||
|
||||
for (int i = 0; i < Const.RVsCount; i++) /// Byte 83 .. 90
|
||||
{
|
||||
RegVStatus[i + 1] = ((uint)data[offs + (int)Poz.RVs + i] >> 3) & 7;
|
||||
}
|
||||
/// 4-20 mA reg. valve
|
||||
uint stavRegQ = (uint)((State >> 16) & 0xFF);
|
||||
RegVStatus[Const.RVsCount + 1] = (stavRegQ >> 4) & 2;
|
||||
|
||||
/// This must preceed processing bytes 91 .. 250 as Ttime is used there
|
||||
uint ttimeRaw = GetUInt32(data, offs + (int)Poz.Ttime); /// Byte 251,252,253,254
|
||||
Ttime = Convert.ToDouble(ttimeRaw) * Const.TimeResolution; /// convert to [s]
|
||||
ImpulseTime[0] = Ttime;
|
||||
|
||||
/// Water meters (pulses count, gated test time, gated etalon pulses count)
|
||||
int ix1 = offs + (int)Poz.CT1; /// Byte 91 .. 250
|
||||
int ix2 = offs + (int)Poz.CTR1;
|
||||
for (int wmNr = 1; wmNr <= Const.WMsCount; wmNr++, ix1 += 6, ix2 += 2)
|
||||
{
|
||||
if ((State & (ulong)StatusP.SynchroMethod) != 0)
|
||||
{
|
||||
ushort pulses = GetUInt16(data, ix2);
|
||||
WMeterPuls[wmNr] = Convert.ToInt32(pulses);
|
||||
EtPulses[wmNr] = (pulses == 0) ? 0 : Convert.ToInt32(GetUInt24(data, ix1));
|
||||
ImpulseTime[wmNr] = (pulses == 0) ? 0 : Const.TimeResolution * Convert.ToDouble(GetUInt24(data, ix1 + 3));
|
||||
}
|
||||
else
|
||||
{
|
||||
WMeterPuls[wmNr] = Convert.ToInt32(GetUInt24(data, ix1));
|
||||
EtPulses[wmNr] = EtPulses[0];
|
||||
ImpulseTime[wmNr] = Ttime;
|
||||
}
|
||||
}
|
||||
|
||||
StavDA[0] = GetUInt16(data, offs + (int)Poz.SDA); /// Byte 255,256
|
||||
byte spare3 = data[offs + (int)Poz.spare3]; /// Byte 257
|
||||
|
||||
/// Impulzy perioda (???)
|
||||
uint[] par1 = new uint[3];
|
||||
uint[] par2 = new uint[3];
|
||||
par2[0] = GetUInt16(data, offs + (int)Poz.Per1); /// Byte 258,259
|
||||
par1[0] = GetUInt16(data, offs + (int)Poz.Per1 + 2); /// Byte 260,261
|
||||
par2[1] = GetUInt16(data, offs + (int)Poz.Per2); /// Byte 262.263
|
||||
par1[1] = GetUInt16(data, offs + (int)Poz.Per2 + 2); /// Byte 264,265
|
||||
par2[2] = GetUInt16(data, offs + (int)Poz.Per3); /// Byte 266,267
|
||||
par1[2] = GetUInt16(data, offs + (int)Poz.Per3 + 2); /// Byte 268,269
|
||||
///
|
||||
ReferenceFreq[0] = (par2[0] != 0) ? (5.0f * par1[0] / par2[0]) : 0.0f;
|
||||
ReferenceFreq[1] = ReferenceFreq[2] = ReferenceFreq[3] = 0;
|
||||
///
|
||||
if ((State & (ulong)StatusP.TestWithRefFlowmtr) != 0 && (State & (ulong)StatusP.FlowmtrNrMask) == 0)
|
||||
{
|
||||
/// Measurement with parallel flowmeters
|
||||
if ((State & (ulong)StatusP.Flowmtr1Active) != 0)
|
||||
{
|
||||
ReferenceFreq[1] = ReferenceFreq[0];
|
||||
}
|
||||
|
||||
if ((State & (ulong)StatusP.Flowmtr2Active) != 0)
|
||||
{
|
||||
ReferenceFreq[2] = (par2[1] != 0) ? (5.0f * par1[1] / par2[1]) : 0.0f;
|
||||
}
|
||||
|
||||
if ((State & (ulong)StatusP.Flowmtr3Active) != 0)
|
||||
{
|
||||
ReferenceFreq[3] = (par2[2] != 0) ? (5.0f * par1[2] / par2[2]) : 0.0f;
|
||||
}
|
||||
|
||||
ReferenceFreq[0] = ReferenceFreq[1] + ReferenceFreq[2] + ReferenceFreq[3];
|
||||
}
|
||||
|
||||
DivTime = Const.DivTimeResolution * data[offs + (int)Poz.CasKl]; /// Byte 271
|
||||
byte spare4 = data[offs + (int)Poz.spare4]; /// Byte 272
|
||||
Chyby485 = GetUInt16(data, offs + (int)Poz.Chyb485); /// Byte 273, 274 !!!!!!!!!!!!!!!
|
||||
uint timeRefRaw = GetUInt24(data, offs + (int)Poz.Tim2); /// Byte 274,275,276 !!!!!!!!!!!!!!!
|
||||
TimeRef = Convert.ToDouble(timeRefRaw) / 1000.0; /// convert to [s]
|
||||
|
||||
for (int i = 0; i < Const.RVsCount; i++) /// Byte 278 .. 293
|
||||
{
|
||||
RegVMoveTime[i] = 10 * GetUInt16(data, offs + (int)Poz.CasKoh + 2*i);
|
||||
}
|
||||
|
||||
EtPulses2 = Convert.ToInt32(GetUInt24(data, offs + (int)Poz.ETX2)); /// Byte 294,295,296
|
||||
EtPulses3 = Convert.ToInt32(GetUInt24(data, offs + (int)Poz.ETX3)); /// Byte 297,298.299 !!!!!!!!!!!!!!!
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Byte positions in rcvdData buffer
|
||||
/// </summary>
|
||||
public enum Poz : int
|
||||
{
|
||||
State = 5, /// 5 .. 9
|
||||
Vyst = State + 5, /// 10 .. 17
|
||||
SDA2 = Vyst + 8, /// 18,19
|
||||
Vst = SDA2 + 2, /// 20 .. 24
|
||||
Analogy = Vst + 5, /// 25 .. 56
|
||||
Groch = Analogy + 2 * Const.ADCsCount, /// 57 (16 analog inputs)
|
||||
Et1 = Groch + 16, /// 73,74,75
|
||||
EtK = Et1 + 3, /// 76,77,78
|
||||
spare1 = EtK + 3, /// 79
|
||||
Stat5 = spare1 + 1, /// 80
|
||||
Stat6 = Stat5 + 1, /// 81
|
||||
spare2 = Stat6 + 1, /// 82
|
||||
RVs = spare2 + 1, /// 83
|
||||
CT1 = RVs + 8, /// 91
|
||||
CTR1 = CT1 + 6 * Const.WMsCount, /// 211
|
||||
Ttime = CTR1 + 2 * Const.WMsCount, /// 251
|
||||
SDA = Ttime + 4, /// 255
|
||||
spare3 = SDA + 2, /// 257
|
||||
Per1 = spare3 + 1, /// 258
|
||||
Per2 = Per1 + 4, /// 262
|
||||
Per3 = Per2 + 4, /// 266
|
||||
CasKl = Per3 + 5, /// 271
|
||||
spare4 = CasKl + 1, /// 272
|
||||
Chyb485 = spare4 + 1, /// 273
|
||||
Tim2 = Chyb485 + 1, /// 274
|
||||
CasKoh = Tim2 + 4, /// 278
|
||||
ETX2 = CasKoh + 2 * Const.RVsCount, /// 294
|
||||
ETX3 = ETX2 + 3, /// 297
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Dirichlet.Numerics;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public static class OutputMessage
|
||||
{
|
||||
public const int PayloadLen = 38;
|
||||
public const byte MessageCode = (byte)' ';
|
||||
|
||||
public static byte[] GetMessage(Action action, short config)
|
||||
{
|
||||
byte[] message = new byte[PayloadLen + 5]; /// headed 3 bytes, checksum 2 bytes
|
||||
|
||||
/// Header + message code (4 bytes)
|
||||
message[0] = Const.STX;
|
||||
message[1] = 1; /// Control board addres
|
||||
message[2] = (byte)PayloadLen; /// Payload length
|
||||
message[3] = MessageCode;
|
||||
|
||||
/// Command
|
||||
message[4] = GetCommand(action);
|
||||
message[5] = action.IsStart() ? GetStartParams(action) : action.IsStop() ? GetStopParams(action) : (byte)0;
|
||||
message[6] = (action.DivId <= 0) ? (byte)0 : (byte)(action.DivId - 1);
|
||||
|
||||
int totalPulsesCount = (action.TotalPulsesCount < 0) ? 0 : action.TotalPulsesCount;
|
||||
message[7] = (byte)(totalPulsesCount & 0xFF);
|
||||
message[8] = (byte)((totalPulsesCount >> 8) & 0xFF);
|
||||
message[9] = (byte)((totalPulsesCount >> 16) & 0xFF);
|
||||
|
||||
int massPulsesCount = (action.MassPulsesCount < 0) ? 0 : action.MassPulsesCount;
|
||||
message[10] = (byte)(massPulsesCount & 0xFF);
|
||||
message[11] = (byte)((massPulsesCount >> 8) & 0xFF);
|
||||
message[12] = (byte)((massPulsesCount >> 16) & 0xFF);
|
||||
|
||||
message[13] = 0;
|
||||
|
||||
message[14] = (byte)(config & 0xff);
|
||||
message[15] = (byte)((config >> 8) & 0xff);
|
||||
|
||||
/// Route
|
||||
message[16] = ((action.ActionId & ActionID.ChangeRoute) != 0) ? (byte)1 : (byte)0; /// Route change flag
|
||||
message[17] = (byte)(action.Route & 0xFF);
|
||||
message[18] = (byte)((action.Route >> 8) & 0xFF);
|
||||
message[19] = (byte)((action.Route >> 16) & 0xFF);
|
||||
message[20] = (byte)((action.Route >> 24) & 0xFF);
|
||||
message[21] = (byte)((action.Route >> 32) & 0xFF);
|
||||
message[22] = (byte)((action.Route >> 40) & 0xFF);
|
||||
message[23] = (byte)((action.Route >> 48) & 0xFF);
|
||||
message[24] = (byte)((action.Route >> 56) & 0xFF);
|
||||
|
||||
/// DA2
|
||||
message[25] = 0;
|
||||
message[26] = 0;
|
||||
|
||||
/// Regulation valve
|
||||
message[27] = (action.RegVId < 0) ? (byte)0 : (byte)(action.RegVId | (int)action.RegVMode);
|
||||
message[28] = (byte)(action.RVMovePar1 & 0xFF);
|
||||
message[29] = (byte)((action.RVMovePar1 >> 8) & 0xFF);
|
||||
message[30] = (byte)(action.RVMovePar2 & 0xFF);
|
||||
message[31] = (byte)((action.RVMovePar2 >> 8) & 0xFF);
|
||||
message[32] = action.IsStop() ? (byte)0x20 : action.IsStart() ? (byte)0x42 : (byte)0; /// ZStavReg
|
||||
|
||||
/// DA1
|
||||
message[33] = 0; /// PrudParL
|
||||
message[34] = 0; /// PrudParH
|
||||
|
||||
message[35] = (byte)Math.Max(1, Math.Min(255, action.PID)); /// PIDRV
|
||||
message[36] = (byte)Math.Max(4, Math.Min(255, action.TolerRV)); /// TolerRV (4..20 mA reg.valve only)
|
||||
message[37] = (byte)Math.Max(0, Math.Min(255, action.StabTime)); /// StabRV
|
||||
message[38] = (byte)((action.DivThreshold >> 2) & 0xFF); /// HranAK
|
||||
|
||||
message[39] = 0;
|
||||
message[40] = 0;
|
||||
Debug.Assert(40 == PayloadLen + 2);
|
||||
|
||||
/// Checksum (2 bytes)
|
||||
int checksum = 0;
|
||||
for (int i = 1; i < PayloadLen + 3; i++) checksum += message[i];
|
||||
message[PayloadLen + 3] = (byte)(checksum & 0xFF);
|
||||
message[PayloadLen + 4] = (byte)((checksum >> 8) & 0xFF);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
static byte GetCommand(Action action)
|
||||
{
|
||||
int command = 0;
|
||||
if (action.IsStart()) command |= (int)Command.Start;
|
||||
if (action.IsStop()) command |= (int)Command.Stop;
|
||||
return (byte)command;
|
||||
}
|
||||
|
||||
static byte GetStartParams(Action action)
|
||||
{
|
||||
int param = action.FlowMId & (int)StartParam.EtalonMask;
|
||||
|
||||
if (action.IsDivUsed)
|
||||
param |= (int)StartParam.DiverterStart;
|
||||
|
||||
if (action.IsSyncMethod)
|
||||
param |= (int)StartParam.SynchroMethod;
|
||||
else
|
||||
param |= (int)StartParam.StartStopMethod;
|
||||
|
||||
return (byte)param;
|
||||
}
|
||||
|
||||
static byte GetStopParams(Action action)
|
||||
{
|
||||
int param = 0;
|
||||
return (byte)param;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum Command : byte
|
||||
{
|
||||
RequestData = 0,
|
||||
Start = 1,
|
||||
Stop = 2,
|
||||
GetDiverterTransitionData = 4,
|
||||
GetScopeAnalyzerData = 7,
|
||||
ResetScopeAnalyzer = 8,
|
||||
GetSwitchCounterData = 9,
|
||||
}
|
||||
|
||||
public enum StartParam : byte
|
||||
{
|
||||
EtalonMask = 0x07,
|
||||
DiverterStart = 0x08,
|
||||
SynchroMethod = 0x10,
|
||||
DirectGateStart = 0x20, /// ???
|
||||
StartStopMethod = 0x40,
|
||||
CalibrationMode = 0x80,
|
||||
}
|
||||
|
||||
public enum StopDevs : byte
|
||||
{
|
||||
None = 0,
|
||||
Reference = 0x01, /// bit 0
|
||||
Diverter = 0x02, /// bit 1
|
||||
GatePulse = 0x08, /// bit 3
|
||||
TimeMeasurement = 0x10, /// bit 4
|
||||
BypassDevCoupled2Div = 0x20, /// bit 5
|
||||
RegValveRegulation = 0x80, /// bit 7
|
||||
All = 0xFF,
|
||||
}
|
||||
|
||||
public enum TestMethods
|
||||
{
|
||||
Diverter = 0x01, /// bit 0: 1=Mass method (diverters are used), 0=Volume method
|
||||
FixedStart = 0x02, /// bit 1: 1=fixed start method, 0=flying start method
|
||||
Synchro = 0x04, /// bit 2: 1=Synchro method, 0=Pulse counting
|
||||
MassAndContinue = 0x10, /// bit 4: 1=Method with mass measurement followed by a volume method
|
||||
}
|
||||
|
||||
public enum ValveChgFlag : byte
|
||||
{
|
||||
DoNotChange = 0,
|
||||
Change = 1,
|
||||
SendPressureMeterAddresses = 2,
|
||||
}
|
||||
|
||||
public enum RegValveMode : byte
|
||||
{
|
||||
None = 0,
|
||||
TargetFrequency = 0x10, /// Low and high frequency limits (0..2000Hz,0..2200Hz) are specified
|
||||
TargetPosition = 0x20, /// Low and high position (=DAC value) limits (0..100%) are specified
|
||||
Stop = 0x30, /// Stop regulation
|
||||
PulseWidth = 0x40, /// Pulse width 0.05 .. 2 sec. ... opening and closing (opening=0x40, closing=0xC0)
|
||||
NegPulseWidth = 0x80, /// Pulse width 0.05 .. 2 sec. ... closing (closing=0xC0)
|
||||
}
|
||||
|
||||
public enum RegValveState : byte
|
||||
{
|
||||
Idle = 0,
|
||||
PwOrFreqRegul = 2,
|
||||
DacValueRegul = 3,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class ScopeAnalyzerData
|
||||
{
|
||||
public const int MessageLen = 1033;
|
||||
public const byte MessageCode = (byte)'S';
|
||||
|
||||
/// Scope analyzer data
|
||||
public int KonSc;
|
||||
public int ZacSc;
|
||||
|
||||
ScopeAnalyzerData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns tru when receive data fit the message frame
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="cumulativeSums">Cumulative sums of received data bytes</param>
|
||||
/// <param name="rcvdBytesCount">Received bytes count</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
/// <returns>true when frame fits data</returns>
|
||||
public static bool FrameFitsData(byte[] rcvdData, int[] cumulativeSums, int rcvdBytesCount, int offset)
|
||||
{
|
||||
if (offset + MessageLen > rcvdBytesCount) return false;
|
||||
|
||||
int checksum = cumulativeSums[offset + MessageLen - 3] - cumulativeSums[offset];
|
||||
|
||||
return rcvdData[offset] == Const.STX &&
|
||||
rcvdData[offset + 1] == 0x01 &&
|
||||
rcvdData[offset + 2] == ((MessageLen - 5) & 0xFF) &&
|
||||
rcvdData[offset + 3] == MessageCode &&
|
||||
rcvdData[offset + MessageLen - 2] == (checksum & 0xFF) &&
|
||||
rcvdData[offset + MessageLen - 1] == ((checksum >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proces received data
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
public static ScopeAnalyzerData GetData(byte[] rcvdData, int offset)
|
||||
{
|
||||
var data = new ScopeAnalyzerData();
|
||||
|
||||
data.KonSc = Convert.ToInt32(rcvdData[4]) + 256 * Convert.ToInt32(rcvdData[5]);
|
||||
data.ZacSc = Convert.ToInt32(rcvdData[6]) + 256 * Convert.ToInt32(rcvdData[7]);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class SwitchCountersData
|
||||
{
|
||||
public const int MessageLen = 303;
|
||||
public const byte MessageCode = (byte)'C';
|
||||
|
||||
// TODO: Implement member variables
|
||||
|
||||
SwitchCountersData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns tru when receive data fit the message frame
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="cumulativeSums">Cumulative sums of received data bytes</param>
|
||||
/// <param name="rcvdBytesCount">Received bytes count</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
/// <returns>true when frame fits data</returns>
|
||||
public static bool FrameFitsData(byte[] rcvdData, int[] cumulativeSums, int rcvdBytesCount, int offset)
|
||||
{
|
||||
if (offset + MessageLen > rcvdBytesCount) return false;
|
||||
|
||||
int checksum = cumulativeSums[offset + MessageLen - 3] - cumulativeSums[offset];
|
||||
|
||||
return rcvdData[offset] == Const.STX &&
|
||||
rcvdData[offset + 1] == 0x01 &&
|
||||
rcvdData[offset + 2] == ((MessageLen - 5) & 0xFF) &&
|
||||
rcvdData[offset + 3] == MessageCode &&
|
||||
rcvdData[offset + MessageLen - 2] == (checksum & 0xFF) &&
|
||||
rcvdData[offset + MessageLen - 1] == ((checksum >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Proces received data
|
||||
/// </summary>
|
||||
/// <param name="rcvdData">Received data</param>
|
||||
/// <param name="offset">Offset of the message</param>
|
||||
public static SwitchCountersData GetData(byte[] rcvdData, int offset)
|
||||
{
|
||||
var data = new SwitchCountersData();
|
||||
|
||||
// TODO
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,596 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Common;
|
||||
using Config.Entities;
|
||||
using Dirichlet.Numerics;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using TBF.Rig.Sequences;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
public class UniCB : ComponentBase, IControlBoard, SchematicDrawing.IDrawingItCmpntWithMeasuredVal
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(UniCB));
|
||||
public override string ToString() { return string.Format("CBoard({0})", cbCfg != null ? cbCfg.ToString(1) : string.Empty); }
|
||||
|
||||
/// TBF component configuration and useful wrappers
|
||||
readonly UniCBCfg cbCfg;
|
||||
string comPort { get { return string.Format("COM{0}", cbCfg.ComPortNr); } }
|
||||
short config { get { return (short)((cbCfg.DrainValvesCount << 8) + ((cbCfg.DivertersCount - 1) << 3) + cbCfg.RegValvesCount - 4); } }
|
||||
|
||||
/// IDrawingItCmpnt interface implementation
|
||||
public SchematicDrawing.IDrawingItem DrawingItem { get { return cbCfg as SchematicDrawing.IDrawingItem; } }
|
||||
|
||||
public bool MsrmntAvailable { get { return true; } }
|
||||
public double MeasuredVal { get { return 0; } }
|
||||
|
||||
StringBuilder altString = new StringBuilder();
|
||||
public string AltString
|
||||
{
|
||||
get {
|
||||
altString.Clear();
|
||||
altString.AppendFormat("DI: {0}\n", ToBin40(DigitalInputs));
|
||||
altString.AppendFormat("DO: {0}\n", ToBin40((UInt64)Route));
|
||||
altString.AppendFormat("AD 0:{0:D4} 1:{1:D4} 2:{2:D4} 3:{3:D4} 4:{4:D4} 5:{5:D4}\n",
|
||||
AnalogInput(0), AnalogInput(1), AnalogInput(2), AnalogInput(3), AnalogInput(4), AnalogInput(5));
|
||||
altString.AppendFormat("AD 8:{0:D4} 9:{1:D4} 10:{2:D4} 11:{3:D4}",
|
||||
AnalogInput(8), AnalogInput(9), AnalogInput(10), AnalogInput(11));
|
||||
return altString.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
string ToBin40(UInt64 val)
|
||||
{
|
||||
return string.Format("{0}-{1}-{2}-{3}-{4}", ToBin8((val >> 32) & 0xFF), ToBin8((val >> 24) & 0xFF),
|
||||
ToBin8((val >> 16) & 0xFF), ToBin8((val >> 8) & 0xFF), ToBin8(val & 0xFF));
|
||||
}
|
||||
|
||||
string ToBin8(UInt64 val)
|
||||
{
|
||||
string str = Convert.ToString((byte)val, 2);
|
||||
switch (str.Length)
|
||||
{
|
||||
case 1: return "0000000" + str;
|
||||
case 2: return "000000" + str;
|
||||
case 3: return "00000" + str;
|
||||
case 4: return "0000" + str;
|
||||
case 5: return "000" + str;
|
||||
case 6: return "00" + str;
|
||||
case 7: return "0" + str;
|
||||
default: return str;
|
||||
}
|
||||
}
|
||||
|
||||
/// Uni CB state
|
||||
UInt32 currentOutputs;
|
||||
bool outputsInitialized;
|
||||
DateTime lastOutputsChange;
|
||||
int lastStateMachineTime = 0;
|
||||
|
||||
|
||||
/// Propagated from configurations of other components
|
||||
UInt128 benchModelRoute;
|
||||
UInt128 valvesToInvert; /// Route = valesToInvert ^ RequiredRouteWithoutInvertedVlaves
|
||||
readonly UInt128 routeMask; /// This mask masks out virtual valves, routeMask is set in the constructor
|
||||
|
||||
/// Serial communication
|
||||
SerialPort serialPort; /// Seral port or null: Check serialPort.IsOpen before using the serial port
|
||||
const int BUFFER_SIZE = 4000; /// Size of input buffers
|
||||
byte[] buffer; /// Buffer for data received in one attempt in RunDeviceBefore()
|
||||
byte[] rcvdData; /// Buffer for all recevied but nut processed data. May contain data from several read attempts
|
||||
int[] cumulativeSums;
|
||||
int rcvdBytesCount; /// Count of valid bytes in rcvdData buffer
|
||||
|
||||
/// Message queue
|
||||
Queue<Action> scheduledActionQueue;
|
||||
|
||||
/// Received data
|
||||
public GeneralData Data;
|
||||
DivTransitionData divTransitionData;
|
||||
ScopeAnalyzerData scopeAnalyzerData;
|
||||
SwitchCountersData switchCounterData;
|
||||
|
||||
|
||||
public UInt64 State { get { return Data.State; } } /// Control board state
|
||||
public UInt64 DigitalInputs { get { return Data.Vstupy; } } /// Digital inputs
|
||||
public Int16 AnalogInput(int channel)
|
||||
{
|
||||
if (Data.AnalogInput != null && channel >= 0 && channel < Data.AnalogInput.Length)
|
||||
{
|
||||
return Data.AnalogInput[channel];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Route: 128-bit word representing the current state of all valves and pumps
|
||||
/// </summary>
|
||||
public UInt128 Route { get { return benchModelRoute; } }
|
||||
|
||||
/// Values valid during a test
|
||||
public double RefFrequency { get { return Data.ReferenceFreq[0]; } }
|
||||
|
||||
public double RefFlow
|
||||
{
|
||||
get { return (Devices != null && Devices.FlowMeter != null) ? Devices.FlowMeter.ReadFlow() : 0.0; }
|
||||
}
|
||||
|
||||
/// Last test results
|
||||
public double TestTime { set; get; }
|
||||
public int RefPulses { set; get; }
|
||||
public float ValveOpenCloseTime { set; get; } /// Start valve open or close time in sec
|
||||
|
||||
/// <summary>
|
||||
/// Select devices used for control and measurement
|
||||
/// </summary>
|
||||
/// <param name="outPath"></param>
|
||||
public OutputPath Devices
|
||||
{
|
||||
set { devices = value; }
|
||||
get { return devices; }
|
||||
}
|
||||
|
||||
OutputPath devices;
|
||||
IFlowMeter flowMeter { get { return devices.FlowMeter; } }
|
||||
IRegValve regValve { get { return devices.RegValve; } }
|
||||
IDiverter diverter { get { return devices.Diverter; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for user interfaces (change settings only).
|
||||
/// Initialize(), RunDeviceXY() and StopDevice() methods of the created object will not be called.
|
||||
/// </summary>
|
||||
public UniCB()
|
||||
{
|
||||
devices = new OutputPath(string.Empty, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor invoked when starting the test bench and creating components.
|
||||
/// </summary>
|
||||
public UniCB(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.WriteLine("");
|
||||
Debug.WriteLine("Uni CB enums");
|
||||
Debug.WriteLine("");
|
||||
foreach (var e in Enum.GetValues(typeof(Poz)))
|
||||
{
|
||||
Debug.WriteLine(string.Format("{0} ... {1}", e, ((int)e)));
|
||||
}
|
||||
#endif
|
||||
cbCfg = cfg as UniCBCfg;
|
||||
|
||||
devices = new OutputPath(string.Empty, 0);
|
||||
scheduledActionQueue = new Queue<Action>();
|
||||
|
||||
Data = new GeneralData();
|
||||
divTransitionData = null;
|
||||
scopeAnalyzerData = null;
|
||||
switchCounterData = null;
|
||||
|
||||
serialPort = null;
|
||||
buffer = new byte[BUFFER_SIZE];
|
||||
rcvdData = new byte[BUFFER_SIZE];
|
||||
cumulativeSums = new int[BUFFER_SIZE];
|
||||
rcvdBytesCount = 0;
|
||||
|
||||
routeMask = 0;
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
if (i < cbCfg.VirtValvesRangeLo || i > cbCfg.VirtValvesRangeHi)
|
||||
{
|
||||
routeMask = routeMask | ((UInt128)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
TBF.UiBridge.Bridge.RouteChangeHandler += delegate(object sndr, TBF.UiBridge.RouteChangeArgs args)
|
||||
{
|
||||
UInt128 mask = ((UInt128)1) << args.BitNr;
|
||||
if ((benchModelRoute & mask) == 0)
|
||||
{
|
||||
benchModelRoute |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
benchModelRoute &= (~mask);
|
||||
}
|
||||
};
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify inverted valves
|
||||
/// </summary>
|
||||
/// <param name="valvesToInvert"></param>
|
||||
public void SpecifyInvertedValves(UInt128 valvesToInvert)
|
||||
{
|
||||
this.valvesToInvert = valvesToInvert;
|
||||
this.benchModelRoute = valvesToInvert;
|
||||
}
|
||||
|
||||
#region IDevice interface
|
||||
|
||||
/// <summary>
|
||||
/// Initialize control board device hardware
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (cbCfg.DebugLevel != DebugMode.Normal)
|
||||
{
|
||||
log.FatalFormat("{0} - Device simulated", Name);
|
||||
return;
|
||||
}
|
||||
|
||||
serialPort = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
|
||||
serialPort.DtrEnable = true;
|
||||
serialPort.WriteTimeout = 4000;
|
||||
serialPort.ParityReplace = 0xFF;
|
||||
serialPort.Open();
|
||||
|
||||
log.FatalFormat("{0} - Device successfully initialized", Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reecive and process data from the control board serial port
|
||||
/// </summary>
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if (cbCfg.DebugLevel != DebugMode.Normal || serialPort == null || !serialPort.IsOpen) return;
|
||||
|
||||
/// Read new received bytes and append them to a buffer
|
||||
int bytesCount = serialPort.BytesToRead;
|
||||
if (bytesCount > 0)
|
||||
{
|
||||
bytesCount = serialPort.Read(buffer, 0, Math.Min(bytesCount, BUFFER_SIZE));
|
||||
}
|
||||
for (int i = 0; i < bytesCount && rcvdBytesCount < BUFFER_SIZE; i++, rcvdBytesCount++)
|
||||
{
|
||||
rcvdData[rcvdBytesCount] = buffer[i];
|
||||
}
|
||||
|
||||
/// Calculate cumulative sums (to verify checksums easily)
|
||||
int cumulativeSum = 0;
|
||||
for (int i = 0; i < rcvdBytesCount; i++)
|
||||
{
|
||||
cumulativeSum += rcvdData[i];
|
||||
cumulativeSums[i] = cumulativeSum;
|
||||
}
|
||||
|
||||
/// Try to detect various kinds of data in rcvdData buffer in a loop, start at offset 0
|
||||
int offset = 0;
|
||||
int lastValidOffset = 0; /// Offset of the first byte after the last successfully parsed frame
|
||||
do
|
||||
{
|
||||
bool anyProcessed = false;
|
||||
if (ScopeAnalyzerData.FrameFitsData(rcvdData, cumulativeSums, rcvdBytesCount, offset))
|
||||
{
|
||||
/// Scope analyzer data received
|
||||
scopeAnalyzerData = ScopeAnalyzerData.GetData(rcvdData, offset);
|
||||
string s = Telegram.LogTelegram("Scope analyzer data ", rcvdData, offset, ScopeAnalyzerData.MessageLen);
|
||||
Debug.WriteLine(s);
|
||||
log.Debug(s);
|
||||
offset += ScopeAnalyzerData.MessageLen;
|
||||
lastValidOffset = offset;
|
||||
anyProcessed = true;
|
||||
}
|
||||
else if (GeneralData.FrameFitsData(rcvdData, cumulativeSums, rcvdBytesCount, offset))
|
||||
{
|
||||
/// Regular data received
|
||||
Data.UpdateData(rcvdData, offset);
|
||||
string s = Telegram.LogTelegram("General data ", rcvdData, offset, GeneralData.MessageLen);
|
||||
Debug.WriteLine(s);
|
||||
log.Debug(s);
|
||||
offset += GeneralData.MessageLen;
|
||||
lastValidOffset = offset;
|
||||
anyProcessed = true;
|
||||
}
|
||||
else if (SwitchCountersData.FrameFitsData(rcvdData, cumulativeSums, rcvdBytesCount, offset))
|
||||
{
|
||||
/// Switch counter data received
|
||||
switchCounterData = SwitchCountersData.GetData(rcvdData, offset);
|
||||
string s = Telegram.LogTelegram("Switch counter data ", rcvdData, offset, SwitchCountersData.MessageLen);
|
||||
Debug.WriteLine(s);
|
||||
log.Debug(s);
|
||||
offset += SwitchCountersData.MessageLen;
|
||||
lastValidOffset = offset;
|
||||
anyProcessed = true;
|
||||
}
|
||||
else if (DivTransitionData.FrameFitsData(rcvdData, cumulativeSums, rcvdBytesCount, offset))
|
||||
{
|
||||
/// Diverter transition data received
|
||||
divTransitionData = DivTransitionData.GetData(rcvdData, offset);
|
||||
string s = Telegram.LogTelegram("Diverter transition data ", rcvdData, offset, DivTransitionData.MessageLen);
|
||||
Debug.WriteLine(s);
|
||||
log.Debug(s);
|
||||
offset += DivTransitionData.MessageLen;
|
||||
lastValidOffset = offset;
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
if (!anyProcessed) offset++;
|
||||
}
|
||||
while (offset < rcvdBytesCount);
|
||||
|
||||
/// Remove processed data from the receive buffer
|
||||
for (int i = lastValidOffset; i < rcvdBytesCount; i++)
|
||||
{
|
||||
rcvdData[i - lastValidOffset] = rcvdData[i];
|
||||
}
|
||||
rcvdBytesCount -= lastValidOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send data to the control board serial port
|
||||
/// </summary>
|
||||
public void RunDeviceAfter()
|
||||
{
|
||||
if (cbCfg.DebugLevel != DebugMode.Normal) return;
|
||||
|
||||
/// Make sure the serial port is open
|
||||
if (serialPort == null || !serialPort.IsOpen)
|
||||
{
|
||||
/// Serial port is closed or does not exist => re-open the serial port
|
||||
try
|
||||
{
|
||||
if (serialPort == null)
|
||||
{
|
||||
serialPort = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
|
||||
}
|
||||
serialPort.DtrEnable = true;
|
||||
serialPort.WriteTimeout = 4000;
|
||||
serialPort.ParityReplace = 0xFF;
|
||||
serialPort.Open();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
/// Re-opening serial port failed
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!outputsInitialized || Data.Vystupy != (ulong)benchModelRoute || (StateMachine.Time - lastStateMachineTime) >= 15)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.ChangeRoute((ulong)benchModelRoute));
|
||||
log.InfoFormat("Enqueue( ChangeRoute(route={0:X}) )", benchModelRoute);
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
var combinedAction = Action.FetchNonConflictingActions(scheduledActionQueue);
|
||||
|
||||
byte[] outData = OutputMessage.GetMessage(combinedAction, config);
|
||||
if (outData != null && outData.Length > 0)
|
||||
{
|
||||
serialPort.Write(outData, 0, outData.Length);
|
||||
string s = Telegram.LogTelegram("Sent: ", outData);
|
||||
Debug.WriteLine(s);
|
||||
log.Debug(s);
|
||||
}
|
||||
|
||||
ProcessData.UpdateMeasuredValuesAndSetpoints();
|
||||
TBF.UiBridge.Bridge.OnStateMachineTick(this, new TBF.UiBridge.StateMachineTickEventArgs(Route, ProcessData.MsrmntAvailableFlags,
|
||||
ProcessData.MeasuredValues,
|
||||
ProcessData.AltStrings,
|
||||
ProcessData.Setpoints));
|
||||
}
|
||||
|
||||
public void StopDevice()
|
||||
{
|
||||
if (serialPort != null) serialPort.Close();
|
||||
serialPort = null;
|
||||
}
|
||||
|
||||
public void StopDevice2()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IControlBoard interface
|
||||
|
||||
///
|
||||
/// Interface functions
|
||||
///
|
||||
public void ClearProcessValues() { }
|
||||
|
||||
public double TestTimeWM(int wmNr1)
|
||||
{
|
||||
if (wmNr1 >= 1 && wmNr1 < Data.ImpulseTime.Length)
|
||||
{
|
||||
return Data.ImpulseTime[wmNr1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int RefPulsesWM(int wmNr1)
|
||||
{
|
||||
if (wmNr1 >= 1 && wmNr1 < Data.EtPulses.Length)
|
||||
{
|
||||
return Data.EtPulses[wmNr1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int PulsesWM(int wmNr1)
|
||||
{
|
||||
if (wmNr1 >= 1 && wmNr1 < Data.WMeterPuls.Length)
|
||||
{
|
||||
return Data.WMeterPuls[wmNr1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public UInt128 SetValves(UInt128 valvesToOpen, UInt128 valvesToClose, IList<BuiltIn.ValveEx.Valve> extendedValves)
|
||||
{
|
||||
UInt128 oldRoute = benchModelRoute;
|
||||
benchModelRoute = (((benchModelRoute ^ valvesToInvert) | valvesToOpen) & (~valvesToClose)) ^ valvesToInvert;
|
||||
foreach (var extV in extendedValves) extV.UpdateRoute(ref benchModelRoute);
|
||||
log.DebugFormat("SetValves(x,x), new route = {0}", Utils.RouteToStr(benchModelRoute));
|
||||
UInt128 retVal = oldRoute ^ benchModelRoute;
|
||||
|
||||
log.DebugFormat("{0}.SetValves({1}, {2}) returns {3}", Name, valvesToOpen.ToString("X"), valvesToClose.ToString("X"), retVal.ToString("X"));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///
|
||||
/// Operations
|
||||
///
|
||||
public IOperation SetFlowOp(double flowLimLo, double flowLimHi, TBF.Boxes.DoubleBox measuredFlow, int timeout)
|
||||
{
|
||||
return Devices.RegValve.SetFlowOp(Devices.FlowMeter,flowLimLo, flowLimHi, measuredFlow, timeout);
|
||||
}
|
||||
|
||||
public IOperation StopFlowRegulationOp()
|
||||
{
|
||||
//scheduledActionQueue.Enqueue(Action.Stop());
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a test, Events: MeasurementStarted
|
||||
/// </summary>
|
||||
/// <param name="iParam">Int32 parameter 1</param>
|
||||
/// <param name="dParam1">Double parameter 1 (alternative lower flow limit)</param>
|
||||
/// <param name="dParam2">Double parameter 2 (alternative upper flow limit)</param>
|
||||
/// <returns>Operation</returns>
|
||||
public IOperation StartTestOp(Test test, int iParam = 0, double dParam1 = 0, double dParam2 = 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IOperation ReadDiverterTransitionOp(bool isStart, Sequences.Statistics plotter, int batchNr, string testName, int repetition)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns operation with events: Event.MeasurementCompleted or Event.None
|
||||
/// </summary>
|
||||
/// <returns>Operation</returns>
|
||||
public IOperation QueryMeasurementEndOp()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IOperation StopPreviousOp()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IValveControl interface
|
||||
|
||||
/// <summary>
|
||||
/// Open/close one valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <param name="valveToOpen">Valve to be opened</param>
|
||||
/// <param name="valveToClose">Valve to be closed</param>
|
||||
/// <returns>Newly created operation instance reference casted to IOperaton</returns>
|
||||
public IOperation SetValvesOp(IValve valveOpen, IValve valveClose)
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, valveOpen, valveClose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open/close multiple valves.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <param name="valvesToOpen">A list of valves to be opened</param>
|
||||
/// <param name="valvesToClose">A list of valves to be closed</param>
|
||||
/// <returns>Newly created operation instance reference casted to IOperaton</returns>
|
||||
public IOperation SetValvesOp(IList<IValve> valvesOpen, IList<IValve> valvesClose)
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, valvesOpen, valvesClose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open start/stop valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation OpenStartValveOp()
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, true, devices);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close start/stop valve.
|
||||
/// Events: ValvesSet, ValvesBusy, Error
|
||||
/// </summary>
|
||||
/// <returns>Created operation</returns>
|
||||
public IOperation CloseStartValveOp()
|
||||
{
|
||||
return new BuiltIn.SetValvesOp(this, false, devices);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void MeasureFlow(int flowMeterId)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.MeasureFlow(flowMeterId));
|
||||
log.InfoFormat("Enqueue( MeasureFlow(fm={0}) )", flowMeterId);
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
public void SetFlow(int flowMeterId, int regVId, double freqLo, double freqHi)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.SetFlow(flowMeterId, regVId, freqLo, freqHi, Convert.ToInt32(Math.Round(Devices.PidCoef)), 0, 200));
|
||||
log.InfoFormat("Enqueue( SetFlow(fm={0}, rv={1}, fLo={2}, fHi={3}, pid={4}) )", flowMeterId, regVId, freqLo, freqHi, Convert.ToInt32(Math.Round(Devices.PidCoef)));
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform incremental movement of a regulation valve
|
||||
/// </summary>
|
||||
/// <param name="rvId">Reg. valve ID</param>
|
||||
/// <param name="time">Time in seconds, positive value opens the reg. valve</param>
|
||||
public void RegVlvIncrMove(int regVId, double time)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.RegVlvIncrMove(regVId, time));
|
||||
log.InfoFormat("Enqueue( RegVlvIncrMove(rv={0}, time={1}) )", regVId, time);
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move a regulation valve to specfied position
|
||||
/// </summary>
|
||||
/// <param name="rvId">Reg. valve ID</param>
|
||||
/// <param name="position">Reg. valve position (0 .. 1.0)</param>
|
||||
public void RegVlvMoveToPos(int regVId, double positionLo, double positionHi = -1)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.RegVlvMoveToPos(regVId, positionLo, positionHi));
|
||||
log.InfoFormat("Enqueue( RegVlvMoveToPos(rv={0}, positionLo={1}, positionHi={2}) )", regVId, positionLo, positionHi);
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
public void DiverterToTank(int divNr1)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.SwitchDiverter(divNr1, true));
|
||||
log.InfoFormat("Enqueue( SwitchDiverter(div={0}, true) )", divNr1);
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
public void DiverterToSink(int divNr1)
|
||||
{
|
||||
scheduledActionQueue.Enqueue(Action.SwitchDiverter(divNr1, false));
|
||||
log.InfoFormat("Enqueue( SwitchDiverter(div={0}, false) )", divNr1);
|
||||
foreach (var a in scheduledActionQueue) log.DebugFormat(" {0}", a);
|
||||
}
|
||||
|
||||
public void ReadDiverterTransition(int divNr1)
|
||||
{
|
||||
/// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds backup and security options - serializable configuration.
|
||||
/// </summary>
|
||||
public class UniCBCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider, IDrawingItemWithMeasuredVal
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(UniCBCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int ComPortNr;
|
||||
public int DivertersCount;
|
||||
public int DrainValvesCount;
|
||||
public int RegValvesCount;
|
||||
public int VirtValvesRangeLo;
|
||||
public int VirtValvesRangeHi;
|
||||
|
||||
/// Schematic drawing info
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
public int MsrdX { get; set; }
|
||||
public int MsrdY { get; set; }
|
||||
public Orient MsrdOrient { get; set; }
|
||||
public Config.Unit MsrdUnit { get; set; }
|
||||
public string MsrdFormat { get; set; }
|
||||
public double MsrdValLimLo { get; set; }
|
||||
public double MsrdValLimHi { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
[XmlIgnore]
|
||||
public IList<GEdge> EdgesToSet { get; set; }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
UniCBCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
EdgesToSet = new List<GEdge>();
|
||||
}
|
||||
|
||||
public UniCBCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.UniCB;
|
||||
Sz = Sz.L;
|
||||
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
ComPortNr = 1;
|
||||
VirtValvesRangeLo = 90;
|
||||
VirtValvesRangeHi = 99;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Serial port number",
|
||||
"Diverters count (1..5)",
|
||||
"Drain valves count (0..8)",
|
||||
"Regulation valves count (4..8)",
|
||||
"Virtual valves range LO [bit#]",
|
||||
"Virtual valves range HI [bit#]",
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
|
||||
public ICollection<string> ParamValues(int i)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return string.Format("{0}: COM{1}, VirtValvesRngLO={2}, VirtValvesRngeHI={3}", Name, ComPortNr, VirtValvesRangeLo, VirtValvesRangeHi);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: return ComPortNr.ToString();
|
||||
case 1: return DivertersCount.ToString();
|
||||
case 2: return DrainValvesCount.ToString();
|
||||
case 3: return RegValvesCount.ToString();
|
||||
case 4: return VirtValvesRangeLo.ToString();
|
||||
case 5: return VirtValvesRangeHi.ToString();
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: ComPortNr = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 1: DivertersCount = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 2: DrainValvesCount = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 3: RegValvesCount = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 4: VirtValvesRangeLo = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 5: VirtValvesRangeHi = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
int n;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (int.TryParse(strValue, out n) && (n >= 1)) return true;
|
||||
break;
|
||||
case 1:
|
||||
if (int.TryParse(strValue, out n) && (n >= 1) && n <= 5) return true;
|
||||
break;
|
||||
case 2:
|
||||
if (int.TryParse(strValue, out n) && (n >= 0) && n <= 8) return true;
|
||||
break;
|
||||
case 3:
|
||||
if (int.TryParse(strValue, out n) && (n >= 4) && n <= 8) return true;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
if (int.TryParse(strValue, out n) && (n >= 0) && n <= 127) return true;
|
||||
break;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(UniCBCfg prms)
|
||||
{
|
||||
prms.ComPortNr = ComPortNr;
|
||||
prms.DivertersCount = DivertersCount;
|
||||
prms.DrainValvesCount = DrainValvesCount;
|
||||
prms.RegValvesCount = RegValvesCount;
|
||||
prms.VirtValvesRangeLo = VirtValvesRangeLo;
|
||||
prms.VirtValvesRangeHi = VirtValvesRangeHi;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
var pars = new UniCBCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TBF.Rig.ControlBoard.Uni
|
||||
{
|
||||
class ValveMoveMsg
|
||||
{
|
||||
public int PayloadLen { get { return 38; } }
|
||||
public byte MessageCode { get { return 0x20; } }
|
||||
|
||||
Command cmd;
|
||||
int regValveNr;
|
||||
|
||||
public ValveMoveMsg(Command cmd, int regValveNr)
|
||||
{
|
||||
this.cmd = cmd;
|
||||
this.regValveNr = regValveNr;
|
||||
}
|
||||
|
||||
public byte[] GetMessage()
|
||||
{
|
||||
byte[] message = new byte[PayloadLen + 5]; /// headed 3 bytes, checksum 2 bytes
|
||||
|
||||
/// Header (3 bytes)
|
||||
message[0] = Const.STX;
|
||||
message[1] = 1; /// Control board addres
|
||||
message[2] = (byte)PayloadLen; /// Payload length
|
||||
|
||||
/// Command
|
||||
message[3] = MessageCode;
|
||||
message[4] = (byte)cmd;
|
||||
|
||||
/// ...
|
||||
|
||||
message[40] = 0;
|
||||
Debug.Assert(40 == PayloadLen + 2);
|
||||
|
||||
/// Checksum (2 bytes)
|
||||
int checksum = 0;
|
||||
for (int i = 1; i < PayloadLen + 3; i++) checksum += message[i];
|
||||
message[PayloadLen + 3] = (byte)(checksum & 0xFF);
|
||||
message[PayloadLen + 4] = (byte)((checksum >> 8) & 0xFF);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("ValveMoveMsg : {0}", cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using Common;
|
||||
using Config.Entities;
|
||||
using Dirichlet.Numerics;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.ControlBoard;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Danfoss.VLT2800
|
||||
{
|
||||
/// <summary>
|
||||
/// See page 20 of MG10S202 Operational Instructions Modbus RTU
|
||||
/// </summary>
|
||||
public enum CW : ushort
|
||||
{
|
||||
PresetRefLsb = (1 << 0),
|
||||
PresetRefMsb = (1 << 1),
|
||||
Not_DcBraking = (1 << 2),
|
||||
Not_CoastingStop = (1 << 3),
|
||||
Not_QuickStop = (1 << 4),
|
||||
Not_FreezeFreq = (1 << 5),
|
||||
Start_NotRampStop = (1 << 6),
|
||||
Reset = (1 << 7),
|
||||
Jog = (1 << 8),
|
||||
Ramp2_NotRamp1 = (1 << 9),
|
||||
DataValid = (1 << 10),
|
||||
Relay01Activ = (1 << 11),
|
||||
DOut46Activ = (1 << 12),
|
||||
SelectSetupLsb = (1 << 13),
|
||||
SelectSetupMsb = (1 << 14),
|
||||
Reversing = (1 << 15),
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See page 22 of MG10S202 Operational Instructions Modbus RTU
|
||||
/// </summary>
|
||||
public enum SW : ushort
|
||||
{
|
||||
ControlReady = (1 << 0),
|
||||
DriveReady = (1 << 1),
|
||||
CoastingStop = (1 << 2),
|
||||
Trip = (1 << 3),
|
||||
TripLock = (1 << 6),
|
||||
Warning = (1 << 7),
|
||||
SpeedEqRef = (1 << 8),
|
||||
RemoteCtrl = (1 << 9),
|
||||
FreqLimitOK = (1 << 10),
|
||||
MotorRunning = (1 << 11),
|
||||
VoltageWarn = (1 << 13),
|
||||
CurrentLimit = (1 << 14),
|
||||
ThermalWarn = (1 << 15),
|
||||
}
|
||||
|
||||
public enum Function : byte
|
||||
{
|
||||
ReadCoilStatus = 0x01,
|
||||
ForceSingleCoil = 0x05,
|
||||
ForceMultipleCoils = 0x0F,
|
||||
ReadHoldingRegisters = 0x03,
|
||||
PresetSingleRegister = 0x06,
|
||||
PresetMultipleRegisters = 0x10,
|
||||
}
|
||||
|
||||
|
||||
public class Pump : ComponentBase, IDevice, IOperation, GenericDevices.IPumpFM, GenericDevices.IValve, IDrawingItCmpntWithSetpoint
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Pump));
|
||||
public override string ToString() { return string.Format("Pump-Danfoss-VLT2800({0})", Cfg.ToString(1)); }
|
||||
|
||||
private readonly PumpCfg pumpCfg;
|
||||
public IDrawingItem DrawingItem { get { return pumpCfg as IDrawingItem; } }
|
||||
|
||||
public int Delay { get { return pumpCfg.Delay; } }
|
||||
public ValveCategory Category { get { return ValveCategory.Feeding; } } /// Pump category is Feeding
|
||||
public GenericDevices.IValve CoupledTo { get { return null; } }
|
||||
public bool InvertCouple { get { return false; } }
|
||||
public int LagOpening { get { return 0; } }
|
||||
public int LagClosing { get { return 0; } }
|
||||
|
||||
/// <summary>
|
||||
/// Pump power in [%] in range 0 .. 100.0f
|
||||
/// </summary>
|
||||
private double power;
|
||||
public double Power
|
||||
{
|
||||
get { return power; }
|
||||
}
|
||||
///
|
||||
public double SetpointVal
|
||||
{
|
||||
get { return power; }
|
||||
set
|
||||
{
|
||||
power = value;
|
||||
if (power != 0) TurnOn(power);
|
||||
}
|
||||
}
|
||||
///
|
||||
public void IncreaseSetpoint()
|
||||
{
|
||||
power += 0.05;
|
||||
if (power > 100.0) power = 100.0;
|
||||
TurnOn(power);
|
||||
}
|
||||
///
|
||||
public void DecreaseSetpoint()
|
||||
{
|
||||
power -= 0.05;
|
||||
if (power <= 0)
|
||||
{
|
||||
power = 0;
|
||||
TurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOn(power);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readonly IControlBoard controlBoard;
|
||||
readonly int bitNr; /// 0 .. 63
|
||||
|
||||
public readonly UInt128 Mask; /// derived from bitPosition in the constructor
|
||||
|
||||
public bool State
|
||||
{
|
||||
get { return (controlBoard.Route & Mask) != 0; }
|
||||
}
|
||||
|
||||
/// Private fields
|
||||
SerialPort serialPort;
|
||||
bool dataToSendReady;
|
||||
byte[] dataToSend;
|
||||
StringBuilder responseBuilder;
|
||||
|
||||
|
||||
public Pump()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ambient temperature / humidity / pressure meter 'Greco' connected via serial interface (RS232)
|
||||
/// Connection settings: 19200 Bd 8-bits No-parity 1-stop-bit Flow control: none or hardware.
|
||||
/// </summary>
|
||||
public Pump(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
pumpCfg = cfg as PumpCfg;
|
||||
|
||||
controlBoard = TbfComponents.FindComponent("CB", components) as IControlBoard; /// TODO: replace "CB"
|
||||
if (controlBoard == null) throw new Exception("Cannot find " + Name + " parent");
|
||||
|
||||
bitNr = pumpCfg.BitNr;
|
||||
Mask = (((UInt128)1) << bitNr);
|
||||
#if MUNICH
|
||||
Mask |= (((UInt128)1) << (bitNr + 1));
|
||||
#endif
|
||||
TBF.UiBridge.Bridge.SetpointChangeHandler += delegate(object sndr, TBF.UiBridge.SetpointChangeArgs args)
|
||||
{
|
||||
if (args.Name == Name)
|
||||
{
|
||||
if (args.Increase)
|
||||
{
|
||||
IncreaseSetpoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
DecreaseSetpoint();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (pumpCfg.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string comPortName = "COM" + pumpCfg.ComPortNr.ToString();
|
||||
serialPort = new SerialPort(comPortName, pumpCfg.BaudRate, pumpCfg.Parity, pumpCfg.DataBits, pumpCfg.StopBits);
|
||||
serialPort.Handshake = Handshake.None;
|
||||
serialPort.Open();
|
||||
responseBuilder = new StringBuilder(40);
|
||||
|
||||
log.FatalFormat("Successfully initialized device {0}", ToString());
|
||||
}
|
||||
|
||||
/// <summary>Run this device</summary>
|
||||
public void RunDeviceBefore()
|
||||
{
|
||||
if (pumpCfg.DebugLevel == DebugMode.Simulate) return;
|
||||
|
||||
responseBuilder.Append(serialPort.ReadExisting());
|
||||
|
||||
/// Check if the response is complete
|
||||
if (responseBuilder.Length >= 8)
|
||||
{
|
||||
string response = responseBuilder.ToString();
|
||||
responseBuilder.Clear();
|
||||
|
||||
log.Info(Telegram.LogTelegram("Received ", response));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares data to be sent in RunDeviceAfter() function
|
||||
/// </summary>
|
||||
bool SendData(byte[] data)
|
||||
{
|
||||
if (dataToSendReady) return false;
|
||||
dataToSend = data;
|
||||
dataToSendReady = true;
|
||||
|
||||
log.Info(Telegram.LogTelegram("Sending ", data));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Run this device</summary>
|
||||
public void RunDeviceAfter()
|
||||
{
|
||||
if (dataToSendReady)
|
||||
{
|
||||
if (pumpCfg.DebugLevel != DebugMode.Simulate)
|
||||
{
|
||||
serialPort.Write(dataToSend, 0, dataToSend.Length);
|
||||
}
|
||||
dataToSendReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stop this device</summary>
|
||||
public void StopDevice()
|
||||
{
|
||||
if (serialPort != null) serialPort.Close();
|
||||
}
|
||||
|
||||
public void StopDevice2() { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Turn the pmp on using Modbus commad, use the variable frequency
|
||||
/// </summary>
|
||||
/// <param name="powerArg">Frequency in percent (-200.0 .. 200.0)</param>
|
||||
public void TurnOn(double powerArg)
|
||||
{
|
||||
log.DebugFormat("{0}.TurnOn({1})", Name, powerArg);
|
||||
|
||||
this.power = powerArg;
|
||||
|
||||
//UInt16 controlWord = 0x047C;
|
||||
UInt16 controlWord = (UInt16)(CW.Not_DcBraking |
|
||||
CW.Not_CoastingStop |
|
||||
CW.Not_QuickStop |
|
||||
CW.Not_FreezeFreq |
|
||||
CW.Start_NotRampStop |
|
||||
CW.DataValid);
|
||||
|
||||
UInt16 serialComReference = (UInt16)(Int16)((float)0x4000 * powerArg / 100.0f + 0.5f);
|
||||
|
||||
byte[] msg;
|
||||
if (pumpCfg.Protocol == PumpProtocol.Modbus)
|
||||
{
|
||||
msg = new byte[13];
|
||||
msg[0] = (byte)pumpCfg.BusAddress;
|
||||
msg[1] = (byte)Function.ForceMultipleCoils;
|
||||
msg[2] = 0; /// Data Hi
|
||||
msg[3] = 0; /// Data Lo
|
||||
msg[4] = 0; /// Nr. of coils Hi
|
||||
msg[5] = 0x20; /// Nr. of coils Lo
|
||||
msg[6] = 4; /// Byte count
|
||||
msg[7] = (byte)(controlWord & 0xFF); /// Control Word Lo
|
||||
msg[8] = (byte)(controlWord >> 8); /// Control Word Hi
|
||||
msg[9] = (byte)(serialComReference & 0xFF); /// Serial Com Reference Lo
|
||||
msg[10] = (byte)(serialComReference >> 8); /// Serial Com Reference Hi
|
||||
Telegram.UpdateTelegramCRC(msg);
|
||||
}
|
||||
else /// if (pumpCfg.Protocol == PumpProtocol.FC)
|
||||
{
|
||||
msg = new byte[8];
|
||||
msg[0] = 0x02; /// STX
|
||||
msg[1] = 6; /// lenght (6 bytes following this one)
|
||||
msg[2] = (byte)pumpCfg.BusAddress;
|
||||
msg[3] = (byte)(controlWord >> 8); /// Control Word Hi
|
||||
msg[4] = (byte)(controlWord & 0xFF); /// Control Word Lo
|
||||
msg[5] = (byte)(serialComReference >> 8); /// Serial Com Reference Hi
|
||||
msg[6] = (byte)(serialComReference & 0xFF); /// Serial Com Reference Lo
|
||||
Telegram.UpdateTelegramChecksum(msg);
|
||||
}
|
||||
SendData(msg);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Turn the pmp off using Modbus command
|
||||
/// </summary>
|
||||
public void TurnOff()
|
||||
{
|
||||
log.DebugFormat("{0}.TurnOff()", Name);
|
||||
|
||||
this.power = 0;
|
||||
|
||||
UInt16 controlWord = (UInt16)(CW.Not_DcBraking |
|
||||
CW.Not_CoastingStop |
|
||||
CW.Not_QuickStop |
|
||||
CW.Not_FreezeFreq |
|
||||
//CW.Start_NotRampStop |
|
||||
CW.DataValid);
|
||||
|
||||
UInt16 serialComReference = 0;
|
||||
|
||||
byte[] msg;
|
||||
if (pumpCfg.Protocol == PumpProtocol.Modbus)
|
||||
{
|
||||
msg = new byte[13];
|
||||
msg[0] = (byte)pumpCfg.BusAddress;
|
||||
msg[1] = (byte)Function.ForceMultipleCoils;
|
||||
msg[2] = 0; /// Data Hi
|
||||
msg[3] = 0; /// Data Lo
|
||||
msg[4] = 0; /// Nr. of coils Hi
|
||||
msg[5] = 0x20; /// Nr. of coils Lo
|
||||
msg[6] = 4; /// Byte count
|
||||
msg[7] = (byte)(controlWord & 0xFF); /// Control Word Lo
|
||||
msg[8] = (byte)(controlWord >> 8); /// Control Word Hi
|
||||
msg[9] = (byte)(serialComReference & 0xFF); /// Serial Com Reference Lo
|
||||
msg[10] = (byte)(serialComReference >> 8); /// Serial Com Reference Hi
|
||||
Telegram.UpdateTelegramCRC(msg);
|
||||
}
|
||||
else /// if (pumpCfg.Protocol == PumpProtocol.FC)
|
||||
{
|
||||
msg = new byte[8];
|
||||
msg[0] = 0x02; /// STX
|
||||
msg[1] = 6; /// lenght (6 bytes following this one)
|
||||
msg[2] = (byte)pumpCfg.BusAddress;
|
||||
msg[3] = (byte)(controlWord >> 8); /// Control Word Hi
|
||||
msg[4] = (byte)(controlWord & 0xFF); /// Control Word Lo
|
||||
msg[5] = (byte)(serialComReference >> 8); /// Serial Com Reference Hi
|
||||
msg[6] = (byte)(serialComReference & 0xFF); /// Serial Com Reference Lo
|
||||
Telegram.UpdateTelegramChecksum(msg);
|
||||
}
|
||||
SendData(msg);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The currently running operation.
|
||||
/// </summary>
|
||||
public enum CurrentOp
|
||||
{
|
||||
None,
|
||||
TurnOn,
|
||||
TurnOff,
|
||||
}
|
||||
///
|
||||
CurrentOp currentOp;
|
||||
|
||||
double powerForOp;
|
||||
|
||||
/// <summary>
|
||||
/// Turn the pump frequency inverter on.
|
||||
/// </summary>
|
||||
public IOperation TurnOnOp(double powerArg)
|
||||
{
|
||||
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
|
||||
currentOp = CurrentOp.TurnOn;
|
||||
powerForOp = powerArg;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn the pump frequency inverter on.
|
||||
/// </summary>
|
||||
public IOperation TurnOffOp()
|
||||
{
|
||||
if (currentOp != CurrentOp.None) throw new Exception("Sequence error");
|
||||
currentOp = CurrentOp.TurnOff;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Start the operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
switch (currentOp)
|
||||
{
|
||||
case CurrentOp.TurnOn:
|
||||
TurnOn(powerForOp);
|
||||
return;
|
||||
case CurrentOp.TurnOff:
|
||||
default:
|
||||
TurnOff();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Run the operation</summary>
|
||||
public Event Run()
|
||||
{
|
||||
return Event.TurnPumpOnOffDone;
|
||||
}
|
||||
|
||||
/// <summary>Stop the operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
currentOp = CurrentOp.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Xml.Serialization;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Danfoss.VLT2800
|
||||
{
|
||||
public class PumpCfg : ComponentCfgBase, Generic.IComponentCfg, IRouteBasedDrawingItem, IDrawingItemWithSetpoint
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(PumpCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new PumpCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int BitNr { get; set; }
|
||||
public bool Inverted { get; set; } /// When true the pump function is inverted: 0 = on, 1 = off
|
||||
public int Delay; /// Delay of the pump function in [s] (affects the duration of transition sequence steps)
|
||||
public PumpProtocol Protocol; /// Modbus or FC with Siemens address
|
||||
public int BusAddress; /// Modbus or FC address in range 1..247 (Modbus) or 1..31 (FC with Siemens address)
|
||||
public int ComPortNr;
|
||||
public int BaudRate;
|
||||
public Parity Parity;
|
||||
public int DataBits;
|
||||
public StopBits StopBits;
|
||||
|
||||
/// Schematic drawing info
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
public int SetpX { get; set; }
|
||||
public int SetpY { get; set; }
|
||||
public Orient SetpOrient { get; set; }
|
||||
public string SetpFormat { get; set; }
|
||||
public Config.Unit SetpUnit { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
[XmlIgnore]
|
||||
public IList<GEdge> EdgesToSet { get; set; }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
PumpCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
EdgesToSet = new List<GEdge>();
|
||||
}
|
||||
|
||||
public PumpCfg(IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.PumpFM;
|
||||
Sz = Sz.M;
|
||||
SetpFormat = "{0:F0} %";
|
||||
SetpUnit = Config.Unit.Pct;
|
||||
|
||||
Name = "Pump-Danfoss";
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
Delay = 1;
|
||||
ComPortNr = 3;
|
||||
|
||||
/// Default protocol settings (the same as Danfoss VLT2800 factory settings)
|
||||
Protocol = PumpProtocol.FC;
|
||||
BusAddress = 1;
|
||||
BaudRate = 9600;
|
||||
DataBits = 8;
|
||||
Parity = System.IO.Ports.Parity.Even; /// 'Parity.None' is the default value for Protocol = PumpProtocol.Modbus
|
||||
StopBits = System.IO.Ports.StopBits.One;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, Delay={1}s, Protocol={2}, BusAddress={3}, Com{4}, {5}Bd, {6}-bits, parity={7}, stopBits={8}",
|
||||
Name, Delay, Protocol, BusAddress, ComPortNr, BaudRate, DataBits, Parity, StopBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.IO.Ports;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Danfoss.VLT2800
|
||||
{
|
||||
public partial class PumpCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
public bool ShowMore { get { return false; } }
|
||||
|
||||
PumpCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as PumpCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public PumpCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
protocolComboBox.Items.Add(PumpProtocol.Modbus.ToString());
|
||||
protocolComboBox.Items.Add(PumpProtocol.FC.ToString());
|
||||
|
||||
parityComboBox.Items.Add(Parity.None.ToString());
|
||||
parityComboBox.Items.Add(Parity.Even.ToString());
|
||||
parityComboBox.Items.Add(Parity.Odd.ToString());
|
||||
|
||||
stopBitsComboBox.Items.Add(StopBits.None.ToString());
|
||||
stopBitsComboBox.Items.Add(StopBits.One.ToString());
|
||||
stopBitsComboBox.Items.Add(StopBits.OnePointFive.ToString());
|
||||
stopBitsComboBox.Items.Add(StopBits.Two.ToString());
|
||||
}
|
||||
|
||||
int GetParityIx(Parity par)
|
||||
{
|
||||
if (par == Parity.None) return 0;
|
||||
if (par == Parity.Even) return 0;
|
||||
if (par == Parity.Odd) return 0;
|
||||
return -1;
|
||||
}
|
||||
Parity GetParity(string str)
|
||||
{
|
||||
if (str.Equals(Parity.None.ToString())) return Parity.None;
|
||||
if (str.Equals(Parity.Even.ToString())) return Parity.Even;
|
||||
if (str.Equals(Parity.Odd.ToString())) return Parity.Odd;
|
||||
return (Parity)(-1);
|
||||
}
|
||||
|
||||
int GetStopBitsIx(StopBits sb)
|
||||
{
|
||||
if (sb == StopBits.None) return 0;
|
||||
if (sb == StopBits.One) return 1;
|
||||
if (sb == StopBits.OnePointFive) return 2;
|
||||
if (sb == StopBits.Two) return 3;
|
||||
return -1;
|
||||
}
|
||||
StopBits GetStopBits(string str)
|
||||
{
|
||||
if (str.Equals(StopBits.None.ToString())) return StopBits.None;
|
||||
if (str.Equals(StopBits.One.ToString())) return StopBits.One;
|
||||
if (str.Equals(StopBits.OnePointFive.ToString())) return StopBits.OnePointFive;
|
||||
if (str.Equals(StopBits.Two.ToString())) return StopBits.Two;
|
||||
return (StopBits)(-1);
|
||||
}
|
||||
|
||||
int GetHandshakeIx(Handshake par)
|
||||
{
|
||||
if (par == Handshake.None) return 0;
|
||||
if (par == Handshake.RequestToSend) return 0;
|
||||
if (par == Handshake.XOnXOff) return 0;
|
||||
return -1;
|
||||
}
|
||||
Handshake GetHandshake(string str)
|
||||
{
|
||||
if (str.Equals(Handshake.None.ToString())) return Handshake.None;
|
||||
if (str.Equals(Handshake.RequestToSend.ToString())) return Handshake.RequestToSend;
|
||||
if (str.Equals(Handshake.XOnXOff.ToString())) return Handshake.XOnXOff;
|
||||
return (Handshake)(-1);
|
||||
}
|
||||
|
||||
private void AbbientCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
for (Config.Unit units = 0; units < global::Config.Unit.Count; units++)
|
||||
{
|
||||
if (global::Config.Units.IsQuantity(units, global::Config.Quantity.Error))
|
||||
{
|
||||
unitsComboBox.Items.Add(units.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
delayTextBox.Text = config.Delay.ToString();
|
||||
bitPositionTextBox.Text = config.BitNr.ToString();
|
||||
protocolComboBox.Text = config.Protocol.ToString();
|
||||
busAddressTextBox.Text = config.BusAddress.ToString();
|
||||
comPortNrTextBox.Text = config.ComPortNr.ToString();
|
||||
baudRateTextBox.Text = config.BaudRate.ToString();
|
||||
parityComboBox.Text = config.Parity.ToString();
|
||||
dataBitsTextBox.Text = config.DataBits.ToString();
|
||||
stopBitsComboBox.Text = config.StopBits.ToString();
|
||||
formatTextBox.Text = config.SetpFormat;
|
||||
unitsComboBox.Text = config.SetpUnit.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
delayTextBox.Enabled = true;
|
||||
bitPositionTextBox.Enabled = true;
|
||||
protocolComboBox.Enabled = true;
|
||||
busAddressTextBox.Enabled = true;
|
||||
comPortNrTextBox.Enabled = true;
|
||||
baudRateTextBox.Enabled = true;
|
||||
parityComboBox.Enabled = true;
|
||||
dataBitsTextBox.Enabled = true;
|
||||
stopBitsComboBox.Enabled = true;
|
||||
formatTextBox.Enabled = true;
|
||||
unitsComboBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
|
||||
config.Name = nameTextBox.Text;
|
||||
config.Delay = int.Parse(delayTextBox.Text);
|
||||
config.BitNr = int.Parse(bitPositionTextBox.Text);
|
||||
config.Protocol = protocolComboBox.Text.Equals(PumpProtocol.Modbus.ToString()) ? PumpProtocol.Modbus : PumpProtocol.FC;
|
||||
config.BusAddress = int.Parse(busAddressTextBox.Text);
|
||||
config.ComPortNr = int.Parse(comPortNrTextBox.Text);
|
||||
config.BaudRate = int.Parse(baudRateTextBox.Text);
|
||||
config.Parity = GetParity(parityComboBox.SelectedItem.ToString());
|
||||
config.DataBits = int.Parse(dataBitsTextBox.Text);
|
||||
config.StopBits = GetStopBits(stopBitsComboBox.SelectedItem.ToString());
|
||||
|
||||
config.SetpFormat = formatTextBox.Text;
|
||||
config.SetpUnit = global::Config.Unit.None;
|
||||
for (Config.Unit units = 0; units < global::Config.Unit.Count; units++)
|
||||
{
|
||||
if (unitsComboBox.Text == units.ToString())
|
||||
{
|
||||
config.SetpUnit = units;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!int.TryParse(delayTextBox.Text, out dummy) || dummy < 0 || dummy > 300)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Delay' is not valid";
|
||||
}
|
||||
|
||||
if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy >= 128)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Bit Position' should be between 0 and 127";
|
||||
}
|
||||
|
||||
if (!protocolComboBox.Items.Contains(protocolComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Protocol' should Modbus or FC";
|
||||
}
|
||||
|
||||
if (!int.TryParse(busAddressTextBox.Text, out dummy) || dummy < 1 || dummy > 247)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Bus Address' should be in range 1..247";
|
||||
}
|
||||
|
||||
if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Serial Port Number' is not valid";
|
||||
}
|
||||
|
||||
if (!int.TryParse(baudRateTextBox.Text, out dummy) || dummy < 150 || dummy > 115200)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Baud Rate' is not valid";
|
||||
}
|
||||
|
||||
if (!int.TryParse(dataBitsTextBox.Text, out dummy) || dummy < 7 || dummy > 8)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Data Bits' is not valid";
|
||||
}
|
||||
|
||||
if (!unitsComboBox.Items.Contains(unitsComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Units'";
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
||||
///
|
||||
namespace TBF.Rig.Danfoss.VLT2800
|
||||
{
|
||||
partial class PumpCfgCtrl
|
||||
{
|
||||
/// <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.comPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.baudRateLabel = new System.Windows.Forms.Label();
|
||||
this.baudRateTextBox = new System.Windows.Forms.TextBox();
|
||||
this.partityLabel = new System.Windows.Forms.Label();
|
||||
this.dataBitsLabel = new System.Windows.Forms.Label();
|
||||
this.dataBitsTextBox = new System.Windows.Forms.TextBox();
|
||||
this.stopBitsLabel = new System.Windows.Forms.Label();
|
||||
this.busAddressLabel = 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.parityComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.stopBitsComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.busAddressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.delayTextBox = new System.Windows.Forms.TextBox();
|
||||
this.delayLabel = new System.Windows.Forms.Label();
|
||||
this.protocolLabel = new System.Windows.Forms.Label();
|
||||
this.protocolComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.bitPositionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.bitPositionLabel = new System.Windows.Forms.Label();
|
||||
this.unitsComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.unitsLabel = new System.Windows.Forms.Label();
|
||||
this.formatTextBox = new System.Windows.Forms.TextBox();
|
||||
this.formatLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// comPortNrTextBox
|
||||
//
|
||||
this.comPortNrTextBox.Enabled = false;
|
||||
this.comPortNrTextBox.Location = new System.Drawing.Point(140, 129);
|
||||
this.comPortNrTextBox.Name = "comPortNrTextBox";
|
||||
this.comPortNrTextBox.Size = new System.Drawing.Size(34, 20);
|
||||
this.comPortNrTextBox.TabIndex = 6;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(29, 132);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(98, 13);
|
||||
this.label1.TabIndex = 5;
|
||||
this.label1.Text = "Serial Port Number:";
|
||||
//
|
||||
// baudRateLabel
|
||||
//
|
||||
this.baudRateLabel.AutoSize = true;
|
||||
this.baudRateLabel.Location = new System.Drawing.Point(29, 153);
|
||||
this.baudRateLabel.Name = "baudRateLabel";
|
||||
this.baudRateLabel.Size = new System.Drawing.Size(58, 13);
|
||||
this.baudRateLabel.TabIndex = 7;
|
||||
this.baudRateLabel.Text = "Baud Rate";
|
||||
//
|
||||
// baudRateTextBox
|
||||
//
|
||||
this.baudRateTextBox.Enabled = false;
|
||||
this.baudRateTextBox.Location = new System.Drawing.Point(140, 150);
|
||||
this.baudRateTextBox.Name = "baudRateTextBox";
|
||||
this.baudRateTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.baudRateTextBox.TabIndex = 8;
|
||||
//
|
||||
// partityLabel
|
||||
//
|
||||
this.partityLabel.AutoSize = true;
|
||||
this.partityLabel.Location = new System.Drawing.Point(29, 174);
|
||||
this.partityLabel.Name = "partityLabel";
|
||||
this.partityLabel.Size = new System.Drawing.Size(33, 13);
|
||||
this.partityLabel.TabIndex = 9;
|
||||
this.partityLabel.Text = "Parity";
|
||||
//
|
||||
// dataBitsLabel
|
||||
//
|
||||
this.dataBitsLabel.AutoSize = true;
|
||||
this.dataBitsLabel.Location = new System.Drawing.Point(29, 196);
|
||||
this.dataBitsLabel.Name = "dataBitsLabel";
|
||||
this.dataBitsLabel.Size = new System.Drawing.Size(50, 13);
|
||||
this.dataBitsLabel.TabIndex = 11;
|
||||
this.dataBitsLabel.Text = "Data Bits";
|
||||
//
|
||||
// dataBitsTextBox
|
||||
//
|
||||
this.dataBitsTextBox.Enabled = false;
|
||||
this.dataBitsTextBox.Location = new System.Drawing.Point(140, 193);
|
||||
this.dataBitsTextBox.Name = "dataBitsTextBox";
|
||||
this.dataBitsTextBox.Size = new System.Drawing.Size(34, 20);
|
||||
this.dataBitsTextBox.TabIndex = 12;
|
||||
//
|
||||
// stopBitsLabel
|
||||
//
|
||||
this.stopBitsLabel.AutoSize = true;
|
||||
this.stopBitsLabel.Location = new System.Drawing.Point(29, 217);
|
||||
this.stopBitsLabel.Name = "stopBitsLabel";
|
||||
this.stopBitsLabel.Size = new System.Drawing.Size(49, 13);
|
||||
this.stopBitsLabel.TabIndex = 13;
|
||||
this.stopBitsLabel.Text = "Stop Bits";
|
||||
//
|
||||
// busAddressLabel
|
||||
//
|
||||
this.busAddressLabel.AutoSize = true;
|
||||
this.busAddressLabel.Location = new System.Drawing.Point(29, 110);
|
||||
this.busAddressLabel.Name = "busAddressLabel";
|
||||
this.busAddressLabel.Size = new System.Drawing.Size(66, 13);
|
||||
this.busAddressLabel.TabIndex = 3;
|
||||
this.busAddressLabel.Text = "Bus Address";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(140, 23);
|
||||
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(30, 26);
|
||||
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, 5);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComonentName";
|
||||
//
|
||||
// parityComboBox
|
||||
//
|
||||
this.parityComboBox.Enabled = false;
|
||||
this.parityComboBox.FormattingEnabled = true;
|
||||
this.parityComboBox.Location = new System.Drawing.Point(140, 171);
|
||||
this.parityComboBox.Name = "parityComboBox";
|
||||
this.parityComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.parityComboBox.TabIndex = 10;
|
||||
//
|
||||
// stopBitsComboBox
|
||||
//
|
||||
this.stopBitsComboBox.Enabled = false;
|
||||
this.stopBitsComboBox.FormattingEnabled = true;
|
||||
this.stopBitsComboBox.Location = new System.Drawing.Point(140, 214);
|
||||
this.stopBitsComboBox.Name = "stopBitsComboBox";
|
||||
this.stopBitsComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.stopBitsComboBox.TabIndex = 14;
|
||||
//
|
||||
// busAddressTextBox
|
||||
//
|
||||
this.busAddressTextBox.Enabled = false;
|
||||
this.busAddressTextBox.Location = new System.Drawing.Point(140, 108);
|
||||
this.busAddressTextBox.Name = "busAddressTextBox";
|
||||
this.busAddressTextBox.Size = new System.Drawing.Size(34, 20);
|
||||
this.busAddressTextBox.TabIndex = 4;
|
||||
//
|
||||
// delayTextBox
|
||||
//
|
||||
this.delayTextBox.Enabled = false;
|
||||
this.delayTextBox.Location = new System.Drawing.Point(140, 44);
|
||||
this.delayTextBox.Name = "delayTextBox";
|
||||
this.delayTextBox.Size = new System.Drawing.Size(34, 20);
|
||||
this.delayTextBox.TabIndex = 16;
|
||||
//
|
||||
// delayLabel
|
||||
//
|
||||
this.delayLabel.AutoSize = true;
|
||||
this.delayLabel.Location = new System.Drawing.Point(29, 46);
|
||||
this.delayLabel.Name = "delayLabel";
|
||||
this.delayLabel.Size = new System.Drawing.Size(45, 13);
|
||||
this.delayLabel.TabIndex = 15;
|
||||
this.delayLabel.Text = "Delay[s]";
|
||||
//
|
||||
// protocolLabel
|
||||
//
|
||||
this.protocolLabel.AutoSize = true;
|
||||
this.protocolLabel.Location = new System.Drawing.Point(29, 89);
|
||||
this.protocolLabel.Name = "protocolLabel";
|
||||
this.protocolLabel.Size = new System.Drawing.Size(46, 13);
|
||||
this.protocolLabel.TabIndex = 17;
|
||||
this.protocolLabel.Text = "Protocol";
|
||||
//
|
||||
// protocolComboBox
|
||||
//
|
||||
this.protocolComboBox.Enabled = false;
|
||||
this.protocolComboBox.FormattingEnabled = true;
|
||||
this.protocolComboBox.Location = new System.Drawing.Point(140, 86);
|
||||
this.protocolComboBox.Name = "protocolComboBox";
|
||||
this.protocolComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.protocolComboBox.TabIndex = 18;
|
||||
//
|
||||
// bitPositionTextBox
|
||||
//
|
||||
this.bitPositionTextBox.Enabled = false;
|
||||
this.bitPositionTextBox.Location = new System.Drawing.Point(140, 65);
|
||||
this.bitPositionTextBox.Name = "bitPositionTextBox";
|
||||
this.bitPositionTextBox.Size = new System.Drawing.Size(34, 20);
|
||||
this.bitPositionTextBox.TabIndex = 20;
|
||||
//
|
||||
// bitPositionLabel
|
||||
//
|
||||
this.bitPositionLabel.AutoSize = true;
|
||||
this.bitPositionLabel.Location = new System.Drawing.Point(30, 68);
|
||||
this.bitPositionLabel.Name = "bitPositionLabel";
|
||||
this.bitPositionLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.bitPositionLabel.TabIndex = 19;
|
||||
this.bitPositionLabel.Text = "Valve Bit Position";
|
||||
//
|
||||
// unitsComboBox
|
||||
//
|
||||
this.unitsComboBox.Enabled = false;
|
||||
this.unitsComboBox.FormattingEnabled = true;
|
||||
this.unitsComboBox.Location = new System.Drawing.Point(140, 257);
|
||||
this.unitsComboBox.Name = "unitsComboBox";
|
||||
this.unitsComboBox.Size = new System.Drawing.Size(80, 21);
|
||||
this.unitsComboBox.TabIndex = 32;
|
||||
//
|
||||
// unitsLabel
|
||||
//
|
||||
this.unitsLabel.AutoSize = true;
|
||||
this.unitsLabel.Location = new System.Drawing.Point(29, 260);
|
||||
this.unitsLabel.Name = "unitsLabel";
|
||||
this.unitsLabel.Size = new System.Drawing.Size(71, 13);
|
||||
this.unitsLabel.TabIndex = 31;
|
||||
this.unitsLabel.Text = "Setpoint units";
|
||||
//
|
||||
// formatTextBox
|
||||
//
|
||||
this.formatTextBox.Enabled = false;
|
||||
this.formatTextBox.Location = new System.Drawing.Point(140, 236);
|
||||
this.formatTextBox.Name = "formatTextBox";
|
||||
this.formatTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.formatTextBox.TabIndex = 30;
|
||||
//
|
||||
// formatLabel
|
||||
//
|
||||
this.formatLabel.AutoSize = true;
|
||||
this.formatLabel.Location = new System.Drawing.Point(29, 239);
|
||||
this.formatLabel.Name = "formatLabel";
|
||||
this.formatLabel.Size = new System.Drawing.Size(78, 13);
|
||||
this.formatLabel.TabIndex = 29;
|
||||
this.formatLabel.Text = "Setpoint format";
|
||||
//
|
||||
// PumpCfgCtrl
|
||||
//
|
||||
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.unitsComboBox);
|
||||
this.Controls.Add(this.unitsLabel);
|
||||
this.Controls.Add(this.formatTextBox);
|
||||
this.Controls.Add(this.formatLabel);
|
||||
this.Controls.Add(this.bitPositionTextBox);
|
||||
this.Controls.Add(this.bitPositionLabel);
|
||||
this.Controls.Add(this.protocolComboBox);
|
||||
this.Controls.Add(this.protocolLabel);
|
||||
this.Controls.Add(this.delayTextBox);
|
||||
this.Controls.Add(this.delayLabel);
|
||||
this.Controls.Add(this.busAddressTextBox);
|
||||
this.Controls.Add(this.stopBitsComboBox);
|
||||
this.Controls.Add(this.parityComboBox);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Controls.Add(this.busAddressLabel);
|
||||
this.Controls.Add(this.stopBitsLabel);
|
||||
this.Controls.Add(this.dataBitsTextBox);
|
||||
this.Controls.Add(this.dataBitsLabel);
|
||||
this.Controls.Add(this.partityLabel);
|
||||
this.Controls.Add(this.baudRateTextBox);
|
||||
this.Controls.Add(this.baudRateLabel);
|
||||
this.Controls.Add(this.comPortNrTextBox);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Name = "PumpCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(400, 300);
|
||||
this.Load += new System.EventHandler(this.AbbientCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox comPortNrTextBox;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label baudRateLabel;
|
||||
private System.Windows.Forms.TextBox baudRateTextBox;
|
||||
private System.Windows.Forms.Label partityLabel;
|
||||
private System.Windows.Forms.Label dataBitsLabel;
|
||||
private System.Windows.Forms.TextBox dataBitsTextBox;
|
||||
private System.Windows.Forms.Label stopBitsLabel;
|
||||
private System.Windows.Forms.Label busAddressLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.ComboBox parityComboBox;
|
||||
private System.Windows.Forms.ComboBox stopBitsComboBox;
|
||||
private System.Windows.Forms.TextBox busAddressTextBox;
|
||||
private System.Windows.Forms.TextBox delayTextBox;
|
||||
private System.Windows.Forms.Label delayLabel;
|
||||
private System.Windows.Forms.Label protocolLabel;
|
||||
private System.Windows.Forms.ComboBox protocolComboBox;
|
||||
private System.Windows.Forms.TextBox bitPositionTextBox;
|
||||
private System.Windows.Forms.Label bitPositionLabel;
|
||||
private System.Windows.Forms.ComboBox unitsComboBox;
|
||||
private System.Windows.Forms.Label unitsLabel;
|
||||
private System.Windows.Forms.TextBox formatTextBox;
|
||||
private System.Windows.Forms.Label formatLabel;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2013-2016 Sensus Metering Systems
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Danfoss.VLT2800
|
||||
{
|
||||
public class PumpFactory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "Pump-Danfoss-VLT2800"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Pump.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Pump(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Pump(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new PumpCfg(this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(PumpCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using log4net;
|
||||
|
||||
namespace TBF.Rig.DataContainer.BackupAndSecurityOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds backup and security options.
|
||||
/// </summary>
|
||||
public class Component : ComponentBase
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
|
||||
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
|
||||
|
||||
readonly ComponentCfg myCfg;
|
||||
|
||||
public int MinPasswdLength { get { return myCfg.MinPasswdLength; } }
|
||||
public int PasswdExpirationPeriodDays { get { return myCfg.PasswdExpirationPeriodDays; } }
|
||||
|
||||
public Component()
|
||||
{
|
||||
}
|
||||
|
||||
public Component(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
myCfg = cfg as ComponentCfg;
|
||||
|
||||
Users.GlobalData.MinPasswdLength = myCfg.MinPasswdLength;
|
||||
Users.GlobalData.PasswdExpirationPeriodDays = myCfg.PasswdExpirationPeriodDays;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.BackupAndSecurityOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds backup and security options - serializable configuration.
|
||||
/// </summary>
|
||||
public class ComponentCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ComponentCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int MinPasswdLength;
|
||||
public int PasswdExpirationPeriodDays; /// 0 = validity is not limited
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ComponentCfg() {}
|
||||
|
||||
public ComponentCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Factory = factory;
|
||||
Name = name;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
MinPasswdLength = 6;
|
||||
PasswdExpirationPeriodDays = 0;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Minimum password length (characters)",
|
||||
"Password expiration period (days)",
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
public ICollection<string> ParamValues(int i) { return null; }
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return string.Format("{0}: Min. password length = {1} characters, Password expiration period = {2} days", Name, MinPasswdLength, PasswdExpirationPeriodDays);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: return MinPasswdLength.ToString();
|
||||
case 1: return PasswdExpirationPeriodDays.ToString();;
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: MinPasswdLength = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 1: PasswdExpirationPeriodDays = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
int idummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
/// Positive integers and zero are allowed
|
||||
if (int.TryParse(strValue, out idummy) && (idummy >= 0)) return true;
|
||||
break;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(ComponentCfg prms)
|
||||
{
|
||||
prms.MinPasswdLength = this.MinPasswdLength;
|
||||
prms.PasswdExpirationPeriodDays = this.PasswdExpirationPeriodDays;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
ComponentCfg pars = new ComponentCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.BackupAndSecurityOptions
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Component.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Component(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Component(cfg); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ComponentCfg(GetType().Namespace.Substring(22), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ComponentCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
///
|
||||
/// Copyright (c) 2018-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using TBF.Rig;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.BenchInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds information identifying the test bench.
|
||||
/// </summary>
|
||||
public class Component : ComponentBase, GenericDevices.IBenchInfo
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
|
||||
public override string ToString() { return string.Format("BenchInfo({0})", Cfg.ToString(1)); }
|
||||
|
||||
readonly ComponentCfg myCfg;
|
||||
|
||||
public string TestBenchName { get { return myCfg.TestBenchName; } }
|
||||
public int TestBenchId { get { return myCfg.TestBenchId; } }
|
||||
public string Address1 { get { return myCfg.Address1; } }
|
||||
public string Address2 { get { return myCfg.Address2; } }
|
||||
public string Address3 { get { return myCfg.Address3; } }
|
||||
public string Address4 { get { return myCfg.Address4; } }
|
||||
public string Address5 { get { return myCfg.Address5; } }
|
||||
public RemoteDBUse RemoteDBUse { get { return myCfg.RemoteDBUse; } }
|
||||
|
||||
public Component()
|
||||
{
|
||||
}
|
||||
|
||||
public Component(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
myCfg = cfg as ComponentCfg;
|
||||
Events.DB.SetBenchName(myCfg.TestBenchName);
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.BenchInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds information identifying the test bench - serializable configuration.
|
||||
/// </summary>
|
||||
public class ComponentCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ComponentCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public string TestBenchName;
|
||||
public int TestBenchId;
|
||||
public string Address1;
|
||||
public string Address2;
|
||||
public string Address3;
|
||||
public string Address4;
|
||||
public string Address5;
|
||||
public string ApprovalId;
|
||||
public string ApprovalDate;
|
||||
public string ApprovedBy;
|
||||
public RemoteDBUse RemoteDBUse;
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ComponentCfg() {}
|
||||
|
||||
public ComponentCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
TestBenchName = "1";
|
||||
TestBenchId = 1;
|
||||
|
||||
Address1 = string.Empty;
|
||||
Address2 = string.Empty;
|
||||
Address3 = string.Empty;
|
||||
Address4 = string.Empty;
|
||||
Address5 = string.Empty;
|
||||
|
||||
ApprovalId = string.Empty;
|
||||
ApprovalDate = string.Empty;
|
||||
ApprovedBy = string.Empty;
|
||||
|
||||
RemoteDBUse = RemoteDBUse.LocalDBOnly;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Test bench name",
|
||||
"Test bench ID",
|
||||
"Address 1",
|
||||
"Address 2",
|
||||
"Address 3",
|
||||
"Address 4",
|
||||
"Address 5",
|
||||
"Approval",
|
||||
"Approval date",
|
||||
"Approved by",
|
||||
"Remote DB use",
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
|
||||
public ICollection<string> ParamValues(int i)
|
||||
{
|
||||
if (i == 10)
|
||||
{
|
||||
return new string[] { RemoteDBUse.LocalDBOnly.ToString(),
|
||||
RemoteDBUse.RemoteDBOnly.ToString(),
|
||||
RemoteDBUse.BothDBsLocalFirst.ToString(),
|
||||
RemoteDBUse.BothDBsRemoteFirst.ToString() };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return string.Format("{0}: Bench name={1}, Bench Id={2}, Procedures={3}", Name, TestBenchName, TestBenchId, RemoteDBUse.ToDescription());
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: return TestBenchName;
|
||||
case 1: return TestBenchId.ToString();
|
||||
case 2: return Address1;
|
||||
case 3: return Address2;
|
||||
case 4: return Address3;
|
||||
case 5: return Address4;
|
||||
case 6: return Address5;
|
||||
case 7: return ApprovalId;
|
||||
case 8: return ApprovalDate;
|
||||
case 9: return ApprovedBy;
|
||||
case 10: return RemoteDBUse.ToDescription();
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: TestBenchName = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 1: TestBenchId = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 2: Address1 = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 3: Address2 = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 4: Address3 = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 5: Address4 = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 6: Address5 = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 7: ApprovalId = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 8: ApprovalDate = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
case 9: ApprovedBy = strValue; return CfgUpdateFlags.RestartRqrd;
|
||||
|
||||
case 10:
|
||||
for (RemoteDBUse rdbu = 0; rdbu < RemoteDBUse.Count; rdbu++)
|
||||
{
|
||||
if (strValue == rdbu.ToDescription())
|
||||
{
|
||||
if (RemoteDBUse != rdbu)
|
||||
{
|
||||
RemoteDBUse = rdbu;
|
||||
return CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
return CfgUpdateFlags.Error;
|
||||
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
int idummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
return true;
|
||||
case 1:
|
||||
if (int.TryParse(strValue, out idummy) && (idummy >= 0)) return true;
|
||||
break;
|
||||
case 10:
|
||||
for (RemoteDBUse rdbu = 0; rdbu < RemoteDBUse.Count; rdbu++)
|
||||
{
|
||||
if (strValue == rdbu.ToDescription()) return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(ComponentCfg prms)
|
||||
{
|
||||
prms.TestBenchName = this.TestBenchName;
|
||||
prms.TestBenchId = this.TestBenchId;
|
||||
prms.Address1 = this.Address1;
|
||||
prms.Address2 = this.Address2;
|
||||
prms.Address3 = this.Address3;
|
||||
prms.Address4 = this.Address4;
|
||||
prms.Address5 = this.Address5;
|
||||
prms.ApprovalId = this.ApprovalId;
|
||||
prms.ApprovalDate = this.ApprovalDate;
|
||||
prms.ApprovedBy = this.ApprovedBy;
|
||||
prms.RemoteDBUse = this.RemoteDBUse;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
ComponentCfg pars = new ComponentCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2018 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.BenchInfo
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Component.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Component(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Component(cfg); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ComponentCfg(GetType().Namespace.Substring(22), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ComponentCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
///
|
||||
/// Copyright (c) 2019-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.DataContainer.Buoyancy
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds measured (true) buoyancy value.
|
||||
/// </summary>
|
||||
public class Component : ComponentBase, GenericDevices.IHasCalendarEvents
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
|
||||
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
|
||||
|
||||
readonly ComponentCfg myCfg;
|
||||
|
||||
public double Buoyancy { get { return myCfg.Buoyancy; } }
|
||||
|
||||
public Component()
|
||||
{
|
||||
}
|
||||
|
||||
public Component(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
myCfg = cfg as ComponentCfg;
|
||||
|
||||
/// This is to use data in formulas
|
||||
Config.Data.Buoyancy = Buoyancy;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public IList<Config.CalendarEvent.ICalendarEvent> GetCalendarEvents()
|
||||
{
|
||||
DateTime calibrationDue = myCfg.CalibValidDate;
|
||||
IList<Config.CalendarEvent.ICalendarEvent> calendarEvents = new List<Config.CalendarEvent.ICalendarEvent>();
|
||||
|
||||
if (calibrationDue > TBF.UI.Constants.MinDate)
|
||||
{
|
||||
/// Calibration due date calendar event
|
||||
calendarEvents.Add(new TBF.UI.Calendar.CalibrationDueDateEvent(calibrationDue.Date, Name,
|
||||
string.Format(Strings.Calibration_due_date_is_0,
|
||||
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat))));
|
||||
if (DateTime.Now.Date <= calibrationDue.AddDays(-7))
|
||||
{
|
||||
/// Weekly reminders (last 5 weeks)
|
||||
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.Date.AddDays(-35), Name,
|
||||
string.Format(Strings.Calibration_due_date_is_0,
|
||||
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
|
||||
false));
|
||||
}
|
||||
if (DateTime.Now.Date <= calibrationDue.Date)
|
||||
{
|
||||
/// Daily reminders (last 5 days)
|
||||
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.AddDays(-5), Name,
|
||||
string.Format(Strings.Calibration_due_date_is_0,
|
||||
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
|
||||
true));
|
||||
}
|
||||
}
|
||||
return calendarEvents;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
///
|
||||
/// Copyright (c) 2019-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.Buoyancy
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds backup and security options - serializable configuration.
|
||||
/// </summary>
|
||||
public class ComponentCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider, TBF.Rig.GenericDevices.ICalibInfoCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ComponentCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public double Buoyancy;
|
||||
|
||||
/// Calibration info serialized parameters displayed in Metrology tab page
|
||||
public string CalibCertificateNr { get; set; }
|
||||
public DateTime CalibDate { get; set; }
|
||||
public DateTime CalibValidDate { get; set; }
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ComponentCfg() {}
|
||||
|
||||
public ComponentCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
Buoyancy = 1.00103;
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Buoyancy",
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
public ICollection<string> ParamValues(int i) { return null; }
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return string.Format("{0}: Buoyancy = {1}", Name, Buoyancy);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: return Buoyancy.ToString();
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: Buoyancy = Utils.ParseUDouble(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
double dummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
/// Real number between 0.8 and 1.2 expected
|
||||
if (Utils.TryParseUDouble(strValue, out dummy) && (dummy >= 0.8) && (dummy <= 1.2)) return true;
|
||||
break;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(ComponentCfg prms)
|
||||
{
|
||||
prms.Buoyancy = this.Buoyancy;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
ComponentCfg pars = new ComponentCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2019 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.Buoyancy
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return GetType().Namespace.Substring(8); } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { Component.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new Component(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Component(cfg); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new ComponentCfg(GetType().Namespace.Substring(22), this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(ComponentCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
///
|
||||
/// Copyright (c) 2019-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Resources;
|
||||
|
||||
namespace TBF.Rig.DataContainer.Density
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds measured (true) density value.
|
||||
/// </summary>
|
||||
public class Component : ComponentBase, GenericDevices.IHasCalendarEvents
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(Component));
|
||||
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(1)); }
|
||||
|
||||
readonly ComponentCfg myCfg;
|
||||
|
||||
public double SampleDensity { get { return myCfg.SampleDensity; } }
|
||||
public double SampleTemp { get { return myCfg.SampleTemp; } }
|
||||
|
||||
public Component()
|
||||
{
|
||||
}
|
||||
|
||||
public Component(Generic.IComponentCfg cfg)
|
||||
: base(cfg)
|
||||
{
|
||||
myCfg = cfg as ComponentCfg;
|
||||
|
||||
/// This is to use data in formulas
|
||||
Config.Data.SampleDensity = SampleDensity;
|
||||
Config.Data.SampleTemp = SampleTemp;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
public IList<Config.CalendarEvent.ICalendarEvent> GetCalendarEvents()
|
||||
{
|
||||
DateTime calibrationDue = myCfg.CalibValidDate;
|
||||
IList<Config.CalendarEvent.ICalendarEvent> calendarEvents = new List<Config.CalendarEvent.ICalendarEvent>();
|
||||
|
||||
if (calibrationDue > TBF.UI.Constants.MinDate)
|
||||
{
|
||||
/// Calibration due date calendar event
|
||||
calendarEvents.Add(new TBF.UI.Calendar.CalibrationDueDateEvent(calibrationDue.Date, Name,
|
||||
string.Format(Strings.Calibration_due_date_is_0,
|
||||
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat))));
|
||||
if (DateTime.Now.Date <= calibrationDue.AddDays(-7))
|
||||
{
|
||||
/// Weekly reminders (last 5 weeks)
|
||||
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.Date.AddDays(-35), Name,
|
||||
string.Format(Strings.Calibration_due_date_is_0,
|
||||
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
|
||||
false));
|
||||
}
|
||||
if (DateTime.Now.Date <= calibrationDue.Date)
|
||||
{
|
||||
/// Daily reminders (last 5 days)
|
||||
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.AddDays(-5), Name,
|
||||
string.Format(Strings.Calibration_due_date_is_0,
|
||||
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
|
||||
true));
|
||||
}
|
||||
}
|
||||
return calendarEvents;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
///
|
||||
/// Copyright (c) 2019-2020 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.DataContainer.Density
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds water density - serializable configuration.
|
||||
/// </summary>
|
||||
public class ComponentCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider, TBF.Rig.GenericDevices.ICalibInfoCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(ComponentCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public double SampleDensity;
|
||||
public double SampleTemp;
|
||||
|
||||
/// Calibration info serialized parameters displayed in Metrology tab page
|
||||
public string CalibCertificateNr { get; set; }
|
||||
public DateTime CalibDate { get; set; }
|
||||
public DateTime CalibValidDate { get; set; }
|
||||
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
ComponentCfg() {}
|
||||
|
||||
public ComponentCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
InitializeAll();
|
||||
}
|
||||
|
||||
public string ComponentName { get { return Name; } }
|
||||
|
||||
public void InitializeAll()
|
||||
{
|
||||
SampleDensity = 998.2008; /// kg/m3
|
||||
SampleTemp = 20.0; /// °C
|
||||
}
|
||||
|
||||
string[] paramNames = new string[]
|
||||
{
|
||||
"Sample density [kg/m3]",
|
||||
"Sample temperature [°C]",
|
||||
};
|
||||
public string ParamName(int i) { return paramNames[i]; }
|
||||
public int ParamsCount() { return paramNames.Length; }
|
||||
public ICollection<string> ParamValues(int i) { return null; }
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return string.Format("{0}: Sample density = {1} kg/m3 measured at temperature {2} °C", Name, SampleDensity, SampleTemp);
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: return SampleDensity.ToString();
|
||||
case 1: return SampleTemp.ToString();
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateParam(int i, string strValue)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: SampleDensity = Utils.ParseUDouble(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
case 1: SampleTemp = Utils.ParseUDouble(strValue); return CfgUpdateFlags.RestartRqrd;
|
||||
default: return CfgUpdateFlags.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ValidateParam(int i, string strValue, out string message)
|
||||
{
|
||||
message = string.Empty;
|
||||
double dummy;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
/// Real number between 800 and 1200 kg/m3 expected
|
||||
if (Utils.TryParseUDouble(strValue, out dummy) && (dummy >= 800) && (dummy <= 1200)) return true;
|
||||
break;
|
||||
case 1:
|
||||
/// Real number above 0 expected
|
||||
if (Utils.TryParseUDouble(strValue, out dummy) && (dummy >= 0)) return true;
|
||||
break;
|
||||
default:
|
||||
message = "Invalid index";
|
||||
return false;
|
||||
}
|
||||
|
||||
message = ParamName(i) + " is invalid";
|
||||
return false;
|
||||
}
|
||||
|
||||
void CopyContentTo(ComponentCfg prms)
|
||||
{
|
||||
prms.SampleDensity = this.SampleDensity;
|
||||
prms.SampleTemp = this.SampleTemp;
|
||||
}
|
||||
|
||||
public Config.Entities.IParamsProvider Clone()
|
||||
{
|
||||
ComponentCfg pars = new ComponentCfg();
|
||||
CopyContentTo(pars);
|
||||
return pars;
|
||||
}
|
||||
|
||||
public bool UpdateEmbeddedDbEntity()
|
||||
{
|
||||
return true; /// =OK, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user