From 71ae636410c609d2c660e026cad7f18a46cee4e2 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Fri, 19 Feb 2021 09:05:37 +0100 Subject: [PATCH] ControlBoard.Uni component added. --- .../ControlBoard/Legacy/Common.cs | 3 +- TBF/BenchControl/ControlBoard/Uni/CBoard.cs | 403 ++++++++++++++++++ .../ControlBoard/Uni/CBoardCfg.cs | 136 ++++++ .../ControlBoard/Uni/CommandMsg.cs | 104 +++++ .../ControlBoard/Uni/DivTransitionData.cs | 59 +++ TBF/BenchControl/ControlBoard/Uni/Enums.cs | 92 ++++ .../ControlBoard/Uni/ExtremaData.cs | 53 +++ TBF/BenchControl/ControlBoard/Uni/Factory.cs | 27 ++ .../ControlBoard/Uni/GeneralData.cs | 244 +++++++++++ .../ControlBoard/Uni/IOutputMessage.cs | 12 + .../ControlBoard/Uni/ScopeAnalyzerData.cs | 57 +++ .../ControlBoard/Uni/SwitchCountersData.cs | 53 +++ .../ControlBoard/Uni/ValveMoveMsg.cs | 55 +++ TBF/BenchControl/TbfComponents.cs | 3 +- TBF/TBF.csproj | 24 +- 15 files changed, 1313 insertions(+), 12 deletions(-) create mode 100644 TBF/BenchControl/ControlBoard/Uni/CBoard.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/CBoardCfg.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/CommandMsg.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/DivTransitionData.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/Enums.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/ExtremaData.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/Factory.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/GeneralData.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/IOutputMessage.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/ScopeAnalyzerData.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/SwitchCountersData.cs create mode 100644 TBF/BenchControl/ControlBoard/Uni/ValveMoveMsg.cs diff --git a/TBF/BenchControl/ControlBoard/Legacy/Common.cs b/TBF/BenchControl/ControlBoard/Legacy/Common.cs index f421c59ab..4a7b1313c 100644 --- a/TBF/BenchControl/ControlBoard/Legacy/Common.cs +++ b/TBF/BenchControl/ControlBoard/Legacy/Common.cs @@ -71,7 +71,8 @@ namespace TBF.BenchControl.ControlBoard.Legacy ErrorPressMeter2 = 0x2000000000000, ErrorPressMeter3 = 0x4000000000000, ErrorPressMeter4 = 0x8000000000000, - } + EndurCycleRunning = 0x200000000000000, /// bit 57 + } #endif public enum StopDevs diff --git a/TBF/BenchControl/ControlBoard/Uni/CBoard.cs b/TBF/BenchControl/ControlBoard/Uni/CBoard.cs new file mode 100644 index 000000000..d92f9f661 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/CBoard.cs @@ -0,0 +1,403 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO.Ports; +using log4net; +using Common; +using Config.Entities; +using Dirichlet.Numerics; +using TBF.BenchControl.GenericDevices; + +namespace TBF.BenchControl.ControlBoard.Uni +{ + public class CBoard : ComponentBase, IControlBoard + { + private static readonly ILog log = LogManager.GetLogger(typeof(CBoard)); + public override string ToString() { return string.Format("CBoard({0})", cBoardCfg != null ? cBoardCfg.ToString(1) : string.Empty); } + + /// TBF component configuration + readonly CBoardCfg cBoardCfg; + int comPortNr { get { return cBoardCfg.ComPortNr; } } + int virtValvesRngLo { get { return cBoardCfg.VirtValvesRangeLo; } } + int virtValvesRngHi { get { return cBoardCfg.VirtValvesRangeHi; } } + + /// Propagated from configurations of other components + UInt128 valvesToInvert; + + /// 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 msgQueue; + + /// Received data + GeneralData generalData; + DivTransitionData divTransitionData; + ScopeAnalyzerData scopeAnalyzerData; + SwitchCountersData switchCounterData; + + + UInt128 benchModelRoute; + public UInt128 Route { set; get; } /// State of valves, test bench route + /// + public UInt64 DigitalInputs { set; get; } /// Inputs + + /// Values valid during a test + public double RefFrequency { set; get; } + public double RefFlow { set; get; } + + /// 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 + + /// + /// Select devices used for control and measurement + /// + /// + public OutputPath Devices { set; get; } + + + /// + /// Constructor for user interfaces (change settings only). + /// Initialize(), RunDeviceXY() and StopDevice() methods of the created object will not be called. + /// + public CBoard() + { + } + + /// + /// Constructor invoked when starting the test bench and creating components. + /// + public CBoard(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 + cBoardCfg = cfg as CBoardCfg; + + generalData = new GeneralData(); + divTransitionData = null; + scopeAnalyzerData = null; + switchCounterData = null; + + msgQueue = new Queue(); + + serialPort = null; + buffer = new byte[BUFFER_SIZE]; + rcvdData = new byte[BUFFER_SIZE]; + cumulativeSums = new int[BUFFER_SIZE]; + rcvdBytesCount = 0; + + log.Warn(this.ToString()); + } + + /// + /// Specify inverted valves + /// + /// + public void SpecifyInvertedValves(UInt128 valvesToInvert) + { + this.valvesToInvert = valvesToInvert; + this.benchModelRoute = valvesToInvert; + } + + #region IDevice interface + + /// + /// Initialize control board device hardware + /// + public void Initialize() + { + if (cBoardCfg.DebugLevel != DebugMode.Normal) + { + log.FatalFormat("{0} - Device simulated", Name); + return; + } + + serialPort = new SerialPort(string.Format("COM{0}", comPortNr), 9600, Parity.None, 8, StopBits.One); + serialPort.DtrEnable = true; + serialPort.WriteTimeout = 4000; + serialPort.ParityReplace = 0xFF; + serialPort.Open(); + + log.FatalFormat("{0} - Device successfully initialized", Name); + } + + /// + /// Reecive and process data from the control board serial port + /// + public void RunDeviceBefore() + { + if (cBoardCfg.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 + generalData.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; + } + + /// + /// Send data to the control board serial port + /// + public void RunDeviceAfter() + { + if (cBoardCfg.DebugLevel != DebugMode.Normal) return; + + 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(string.Format("COM{0}", comPortNr), 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 (msgQueue.Count > 0) + { + /// There is a message in the message queue => write it to the serial port + var message = msgQueue.Dequeue(); + byte[] outData = message.GetMessage(); + serialPort.Write(outData, 0, outData.Length); + + string s1 = message.ToString(); + string s2 = Telegram.LogTelegram("Message ", outData); + Debug.WriteLine(s1); + Debug.WriteLine(s2); + log.Debug(s1); + log.Debug(s2); + } + } + + public void StopDevice() + { + if (serialPort != null) serialPort.Close(); + serialPort = null; + } + + public void StopDevice2() + { + } + + #endregion + + public void SendCommand(Command cmd, int etalonNr, int regValveNr, int divNr, ulong totalPulsesCount, ulong massPuleseCount, UInt128 route) + { + msgQueue.Enqueue(new CommandMsg(cmd, etalonNr, regValveNr, divNr, totalPulsesCount, massPuleseCount, route)); + } + + public void ValveMove(Command cmd, int etalonNr, int regValveNr, int divNr, ulong totalPulsesCount, ulong massPuleseCount, UInt128 route) + { + msgQueue.Enqueue(new CommandMsg(cmd, etalonNr, regValveNr, divNr, totalPulsesCount, massPuleseCount, route)); + } + + #region IControlBoard interface + + /// + /// Interface functions + /// + public void UpdateUI(string sParam, int iParam, double value) { } + public void ClearProcessValues() { } + public double TestTimeWM(int wmNr1) { return 0; } + public int RefPulsesWM(int wmNr1) { return 0; } + public int PulsesWM(int wmNr1) { return 0; } + public UInt128 SetValves(UInt128 valvesToOpen, UInt128 valvesToClose, IList extendedValves) { return 0; } + + /// + /// Operations + /// + public IOperation SetFlowOp(double flowLimLo, double flowLimHi, TBF.Boxes.DoubleBox measuredFlow, int timeout) + { + return null; + } + + public IOperation StopFlowRegulationOp() + { + return null; + } + + /// + /// Start a test, Events: MeasurementStarted + /// + /// Int32 parameter 1 + /// Double parameter 1 (alternative lower flow limit) + /// Double parameter 2 (alternative upper flow limit) + /// Operation + 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; + } + + /// + /// Returns operation with events: Event.MeasurementCompleted or Event.None + /// + /// Operation + public IOperation QueryMeasurementEndOp() + { + return null; + } + + public IOperation StopPreviousOp() + { + return null; + } + + #endregion + + #region IValveControl interface + + /// + /// Open/close one valve. + /// Events: ValvesSet, ValvesBusy, Error + /// + /// Valve to be opened + /// Valve to be closed + /// Newly created operation instance reference casted to IOperaton + public IOperation SetValvesOp(IValve valveToOpen, IValve valveToClose) + { + return null; + } + + /// + /// Open/close multiple valves. + /// Events: ValvesSet, ValvesBusy, Error + /// + /// A list of valves to be opened + /// A list of valves to be closed + /// Newly created operation instance reference casted to IOperaton + public IOperation SetValvesOp(IList valvesToOpen, IList valvesToClose) + { + return null; + } + + /// + /// Open start/stop valve. + /// Events: ValvesSet, ValvesBusy, Error + /// + /// Created operation + public IOperation OpenStartValveOp() + { + return null; + } + + /// + /// Close start/stop valve. + /// Events: ValvesSet, ValvesBusy, Error + /// + /// Created operation + public IOperation CloseStartValveOp() + { + return null; + } + + #endregion + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/CBoardCfg.cs b/TBF/BenchControl/ControlBoard/Uni/CBoardCfg.cs new file mode 100644 index 000000000..14b74e4cc --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/CBoardCfg.cs @@ -0,0 +1,136 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using Config.Entities; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ControlBoard.Uni +{ + /// + /// Holds backup and security options - serializable configuration. + /// + public class CBoardCfg : ComponentCfgBase, Generic.IComponentCfg, Config.Entities.IParamsProvider + { + public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(CBoardCfg) })[0]; + public override XmlSerializer GetSerializer() { return Serializer; } + + public IComponentCfgCtrl GetControl() { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); } + + /// + /// Serialized parameters + /// + public int ComPortNr; + public int VirtValvesRangeLo; + public int VirtValvesRangeHi; + + + /// Private parameterless constructor invoked by all other (public) constructors + CBoardCfg() { } + + public CBoardCfg(string name, IComponentFactory factory) + : this() + { + Name = name; + Factory = factory; + ParentName = string.Empty; + InitializeAll(); + } + + public string ComponentName { get { return Name; } } + + public void InitializeAll() + { + ComPortNr = 1; + VirtValvesRangeLo = 50; + VirtValvesRangeHi = 59; + } + + string[] paramNames = new string[] + { + "Serial port number", + "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 IList 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 VirtValvesRangeLo.ToString(); + case 2: 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: VirtValvesRangeLo = int.Parse(strValue); return CfgUpdateFlags.RestartRqrd; + case 2: 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 dummy; + + switch (i) + { + case 0: + /// Real number between 800 and 1200 kg/m3 expected + if (int.TryParse(strValue, out dummy) && (dummy >= 1) && (dummy <= 1000)) return true; + break; + case 1: + case 2: + /// Real number above 0 expected + if (int.TryParse(strValue, out dummy) && (dummy >= 0) && dummy <= 127) return true; + break; + default: + message = "Invalid index"; + return false; + } + + message = ParamName(i) + " is invalid"; + return false; + } + + void CopyContentTo(CBoardCfg prms) + { + prms.ComPortNr = this.ComPortNr; + prms.VirtValvesRangeLo = this.VirtValvesRangeLo; + prms.VirtValvesRangeHi = this.VirtValvesRangeHi; + } + + public Config.Entities.IParamsProvider Clone() + { + var pars = new CBoardCfg(); + CopyContentTo(pars); + return pars; + } + + public bool UpdateEmbeddedDbEntity() + { + return true; /// =OK, do nothing + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/CommandMsg.cs b/TBF/BenchControl/ControlBoard/Uni/CommandMsg.cs new file mode 100644 index 000000000..38f9fde54 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/CommandMsg.cs @@ -0,0 +1,104 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System; +using System.Diagnostics; +using Dirichlet.Numerics; + +namespace TBF.BenchControl.ControlBoard.Uni +{ + public class CommandMsg : IOutputMessage + { + public int PayloadLen { get { return 38; } } + public byte MessageCode { get { return (byte)' '; } } + + readonly Command cmd; + readonly int etalonNr; + readonly int regValveNr; + readonly int divNr; + readonly ulong totalPulsesCount; + readonly ulong massPuleseCount; + readonly UInt128 route; + + public CommandMsg(Command cmd, int etalonNr, int regValveNr, int divNr, ulong totalPulsesCount, ulong massPuleseCount, UInt128 route) + { + this.cmd = cmd; + this.etalonNr = etalonNr; + this.regValveNr = regValveNr; + this.divNr = divNr; + this.totalPulsesCount = totalPulsesCount; + this.massPuleseCount = massPuleseCount; + this.route = route; + } + + 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[5] = GetCmdParameter(message[4]); + //message[6] = (byte)(pulsesCount & 0xFF); + //message[7] = (byte)((pulsesCount >> 8) & 0xFF); + //message[8] = (byte)((pulsesCount >> 16) & 0xFF); + //message[9] = 0; + + ///// Valves + //message[10] = (byte)GetValveChgFlag(); + //message[11] = (byte)(route & 0xFF); + //message[12] = (byte)((route >> 8) & 0xFF); + //message[13] = (byte)((route >> 16) & 0xFF); + //message[14] = (byte)((route >> 24) & 0xFF); + //message[15] = (byte)((route >> 32) & 0xFF); + //message[16] = (byte)((route >> 40) & 0xFF); + //message[17] = (byte)((route >> 48) & 0xFF); + //message[18] = (byte)((route >> 56) & 0xFF); + //message[19] = 0; + + ///// Frequency converter parameters + //message[20] = 0; + //message[21] = 0; + //message[22] = 0; + //message[23] = 0; + //message[24] = 0; + //message[25] = 0; + //message[26] = 0; + //message[27] = 0; + //message[28] = 0; + //message[29] = 0; + + //message[30] = (byte)(regValveNrTextBox.Visible ? int.Parse(regValveNrTextBox.Text) : 0); + //message[31] = (byte)GetRegValveMode(); + message[32] = 0; /// reg. v. position + message[33] = 0; /// reg. v. frequency + message[34] = 0; /// reg. v. time ticks + message[35] = 0; /// analog v. regul + message[36] = 0; /// analog v. regul + message[37] = 0; /// analog v. regul + message[38] = 0; /// analog v. regul + message[39] = 0; /// analog v. regul + + 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("CommandMessage : {0}", cmd); + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/DivTransitionData.cs b/TBF/BenchControl/ControlBoard/Uni/DivTransitionData.cs new file mode 100644 index 000000000..4e218e1c6 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/DivTransitionData.cs @@ -0,0 +1,59 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +namespace TBF.BenchControl.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]; + } + + /// + /// Returns tru when receive data fit the message frame + /// + /// Received data + /// Cumulative sums of received data bytes + /// Received bytes count + /// Offset of the message + /// true when frame fits data + 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); + } + + /// + /// Proces received data + /// + /// Received data + /// Offset of the message + 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; + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/Enums.cs b/TBF/BenchControl/ControlBoard/Uni/Enums.cs new file mode 100644 index 000000000..b41e31f80 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/Enums.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBF.BenchControl.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 + FlowmtrIdMask = 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 + } + + public enum Command : byte + { + RequestData = 0, + Start = 1, + Stop = 2, + GetDiverterTransitionData = 4, + GetScopeAnalyzerData = 7, + ResetScopeAnalyzer = 8, + GetSwitchCounterData = 9, + } + + public enum StartParam : byte + { + EtalonMask = 7, + DiverterStart = 8, + SynchroMethod = 16, + DirectGateStart = 32, /// ??? + StartStopMethod = 64, + CalibrationMode = 128, + } + + public enum StopParam : byte + { + StopEtalon = 1, + StopDiverter = 2, + StopDirectGate = 8, + StopTimer = 16, + StartStopMethod = 32, + } + + public enum ValveChgFlag : byte + { + DoNotChange = 0, + Change = 1, + SendPressureMeterAddresses = 2, + } + + public enum RegValveMode : byte + { + Mode0 = 0, + Mode1 = 1, + Mode2 = 2, + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/ExtremaData.cs b/TBF/BenchControl/ControlBoard/Uni/ExtremaData.cs new file mode 100644 index 000000000..38a952fd3 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/ExtremaData.cs @@ -0,0 +1,53 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +namespace TBF.BenchControl.ControlBoard.Uni +{ + public class ExtremaData + { + public const int MessageLen = 253; + public const byte MessageCode = (byte)'E'; + + // TODO: Implement member variables + + ExtremaData() + { + } + + /// + /// Returns tru when receive data fit the message frame + /// + /// Received data + /// Cumulative sums of received data bytes + /// Received bytes count + /// Offset of the message + /// true when frame fits data + 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); + } + + /// + /// Proces received data + /// + /// Received data + /// Offset of the message + public static ExtremaData GetData(byte[] rcvdData, int offset) + { + var data = new ExtremaData(); + + // TODO + + return data; + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/Factory.cs b/TBF/BenchControl/ControlBoard/Uni/Factory.cs new file mode 100644 index 000000000..08b327dae --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/Factory.cs @@ -0,0 +1,27 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System.Collections.Generic; +using TBF.BenchControl.Generic; + +namespace TBF.BenchControl.ControlBoard.Uni +{ + public class Factory : IComponentFactory + { + public string ClassName { get { return this.GetType().Namespace.Substring(17); } } + public override string ToString() { return ClassName; } + + public void ResetStaticProperties() { CBoard.ResetStaticProperties(); } + + public IComponent DummyComponent() { return new CBoard(); } + + public IComponent GetComponent(IComponentCfg cfg, IList components) { return new CBoard(cfg); } + + public IComponentCfg DefaultConfig() { return new CBoardCfg(this.GetType().Namespace.Substring(32), this); } + + public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component) + { + return ComponentCfgBase.CreateFromDbEntity(CBoardCfg.Serializer, component, this); + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/GeneralData.cs b/TBF/BenchControl/ControlBoard/Uni/GeneralData.cs new file mode 100644 index 000000000..d6d25f17e --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/GeneralData.cs @@ -0,0 +1,244 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System; +namespace TBF.BenchControl.ControlBoard.Uni +{ + public class GeneralData + { + public const int MessageLen = 303; + public const byte MessageCode = (byte)' '; + + /// General data + public byte UnusedCode; /// ???, byte 4 + public ulong Status; /// byte 5..9 + public uint Status4; /// byte 9 + public uint Status5; + public uint Status6; /// Parallel flow meters mask: bit0=0x01=Et1, bit1=0x02=Et2, bit2=0x04=Et3 + public uint Chyby485; + public bool PosliKohut; + public int TolerRV; + public float[] ZCasPohybu = new float[2]; + public ulong Kohuty = 0; + public ulong KohutyH = 0; + public ulong Vystupy; + public uint DajFilt; + public uint[] KFilter = new uint[8]; + public uint[] Parametre = new uint[5]; + public uint NastavRV; + public uint StabRV; + public uint[] StavDA = new uint[2]; + public float ZStavDA2; + public float[] referenceFreq = new float[4]; + public uint[] etPulses = new uint[Const.WMsCount + 1]; /// WMsCount = 20 + public uint etPulsesK; + public uint EtPulses2; + public uint EtPulses3; + public uint[] wMeterPuls = new uint[Const.WMsCount + 1]; /// WMsCount = 20 + public double[] ImpulseTime = new double[Const.WMsCount + 1]; /// WMsCount = 20 + public uint[] wMeterReference = new uint[Const.WMsCount + 1]; /// WMsCount = 20 + public uint[] rValveStatus = new uint[Const.RVsCount + 1 + 1]; /// RVsCount = 8, posledny rValveStatus[9] je prudovy + public float[] ValveMoveTime = new float[Const.RVsCount]; + public ulong rRoute; + public ulong rRouteH; + public int[] divTime = new int[3]; + public double Ttime; /// s + public double TimeRef; /// s + public uint[] beginSt = new uint[Const.WMsCount + 1]; /// WMsCount = 20 + public float referenceFlow; + public float[] RValvePosition = new float[Const.RVsCount + 1 + 1]; /// RVsCount = 8 + public ulong Vstupy; + public int[] AnalogyRaw = new int[Const.ADCsCount]; + public int[] TemperatureRaw = new int[8]; + public float[] ReferenceVolume = new float[2]; + + + public GeneralData() + { + } + + /// + /// Returns tru when receive data fit the message frame + /// + /// Received data + /// Cumulative sums of received data bytes + /// Received bytes count + /// Offset of the message + /// true when frame fits data + 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); + } + + + /// + /// Auxiliary functions + /// + /// Received data + /// Offset to the files + /// + short GetInt16(byte[] data, int offs) { return BitConverter.ToInt16(data, offs); } + ushort GetUInt16(byte[] data, int offs) { return BitConverter.ToUInt16(data, offs); } + uint GetUInt24(byte[] data, int offs) { return BitConverter.ToUInt32(data, offs) & 0x00FFFFFF; } + uint GetUInt32(byte[] data, int offs) { return BitConverter.ToUInt32(data, offs); } + ulong GetUInt40(byte[] data, int offs) { return BitConverter.ToUInt64(data, offs) & 0x000000FFFFFFFFFF; } + ulong GetUInt64(byte[] data, int offs) { return BitConverter.ToUInt64(data, offs); } + + + /// + /// Proces received data + /// + /// Received data + /// Offset of the message + public void UpdateData(byte[] data, int offs) + { + UnusedCode = data[offs + (int)Poz.Start]; /// Byte 4 + Status = GetUInt40(data, offs + (int)Poz.Status); /// Byte 5,6,7,8,9 + Status4 = data[offs + (int)Poz.Status + 4]; /// Byte 9 (duplicated) + 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 + { + AnalogyRaw[i] = GetInt16(data, offs + (int)Poz.Analogy + 2 * i); + } + + /// 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] = GetUInt24(data, offs + (int)Poz.Et1); /// Byte 73,74,75 + etPulsesK = GetUInt24(data, offs + (int)Poz.EtK); /// Byte 76,77,78 + + /// TODO /// byte 79 + + Status5 = data[offs + (int)Poz.Stat5]; /// Byte 80 + Status6 = data[offs + (int)Poz.Stat6]; /// Byte 81 + + /// TODO /// byte 82 + + for (int i = 0; i < Const.RVsCount; i++) /// Byte 83 .. 90 + { + rValveStatus[i + 1] = ((uint)data[offs + (int)Poz.RVs + i] >> 3) & 7; + } + /// 4-20 mA reg. valve + uint stavRegQ = (uint)((Status >> 16) & 0xFF); + rValveStatus[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 ((Status & (ulong)StatusP.SynchroMethod) != 0) + { + ushort pulses = GetUInt16(data, ix2); + wMeterPuls[wmNr] = pulses; + etPulses[wmNr] = (pulses == 0) ? 0 : GetUInt24(data, ix1); + ImpulseTime[wmNr] = (pulses == 0) ? 0 : GetUInt24(data, ix1 + 3) * Const.TimeResolution; + } + else + { + wMeterPuls[wmNr] = GetUInt24(data, ix1); + etPulses[wmNr] = etPulses[0]; + ImpulseTime[wmNr] = Ttime; + } + } + + StavDA[0] = GetUInt16(data, offs + (int)Poz.SDA); /// Byte 255,256 + byte spare1 = data[offs + (int)Poz.spare1]; /// 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 ((Status & (ulong)StatusP.TestWithRefFlowmtr) != 0 && (Status & (ulong)StatusP.FlowmtrIdMask) == 0) + { + /// Measurement with parallel flowmeters + if ((Status6 & 0x01) != 0) + referenceFreq[1] = referenceFreq[0]; + if ((Status6 & 0x02) != 0) + referenceFreq[2] = (par2[1] != 0) ? (5.0f * par1[1] / par2[1]) : 0.0f; + if ((Status6 & 0x04) != 0) + referenceFreq[3] = (par2[2] != 0) ? (5.0f * par1[2] / par2[2]) : 0.0f; + + referenceFreq[0] = referenceFreq[1] + referenceFreq[2] + referenceFreq[3]; + } + + divTime[0] = Const.DivTimeResolution * data[offs + (int)Poz.CasKl]; /// Byte 271 + byte spare2 = data[offs + (int)Poz.spare2]; /// 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 + { + ValveMoveTime[i] = 10 * GetUInt16(data, offs + (int)Poz.CasKoh + 2*i); + } + + EtPulses2 = GetUInt24(data, offs + (int)Poz.ETX2); /// Byte 294,295,296 + EtPulses3 = GetUInt24(data, offs + (int)Poz.ETX3); /// Byte 297,298.299 !!!!!!!!!!!!!!! + } + } + + /// + /// Byte positions in rcvdData buffer + /// + public enum Poz : int + { + Start = 4, + Status = Start + 1, /// 5 .. 9 + Vyst = Status + 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 + Stat5 = EtK + 4, /// 80 + Stat6 = Stat5 + 1, /// 81 + RVs = Stat6 + 2, /// 83 + CT1 = RVs + 8, /// 91 + CTR1 = CT1 + 6 * Const.WMsCount, /// 211 + Ttime = CTR1 + 2 * Const.WMsCount, /// 251 + SDA = Ttime + 4, /// 255 + spare1 = SDA + 2, /// 257 + Per1 = spare1 + 1, /// 258 + Per2 = Per1 + 4, /// 262 + Per3 = Per2 + 4, /// 266 + CasKl = Per3 + 5, /// 271 + spare2 = CasKl + 1, /// 272 + Chyb485 = spare2 + 1, /// 273 + Tim2 = Chyb485 + 1, /// 274 + CasKoh = Tim2 + 4, /// 278 + ETX2 = CasKoh + 2 * Const.RVsCount, /// 294 + ETX3 = ETX2 + 3, /// 297 + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/IOutputMessage.cs b/TBF/BenchControl/ControlBoard/Uni/IOutputMessage.cs new file mode 100644 index 000000000..64963d684 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/IOutputMessage.cs @@ -0,0 +1,12 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +namespace TBF.BenchControl.ControlBoard.Uni +{ + public interface IOutputMessage + { + int PayloadLen { get; } + byte MessageCode { get; } + byte[] GetMessage(); + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/ScopeAnalyzerData.cs b/TBF/BenchControl/ControlBoard/Uni/ScopeAnalyzerData.cs new file mode 100644 index 000000000..5504094bc --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/ScopeAnalyzerData.cs @@ -0,0 +1,57 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System; +namespace TBF.BenchControl.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() + { + } + + /// + /// Returns tru when receive data fit the message frame + /// + /// Received data + /// Cumulative sums of received data bytes + /// Received bytes count + /// Offset of the message + /// true when frame fits data + 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); + } + + /// + /// Proces received data + /// + /// Received data + /// Offset of the message + 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; + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/SwitchCountersData.cs b/TBF/BenchControl/ControlBoard/Uni/SwitchCountersData.cs new file mode 100644 index 000000000..dd69762c7 --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/SwitchCountersData.cs @@ -0,0 +1,53 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +namespace TBF.BenchControl.ControlBoard.Uni +{ + public class SwitchCountersData + { + public const int MessageLen = 303; + public const byte MessageCode = (byte)'C'; + + // TODO: Implement member variables + + SwitchCountersData() + { + } + + /// + /// Returns tru when receive data fit the message frame + /// + /// Received data + /// Cumulative sums of received data bytes + /// Received bytes count + /// Offset of the message + /// true when frame fits data + 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); + } + + /// + /// Proces received data + /// + /// Received data + /// Offset of the message + public static SwitchCountersData GetData(byte[] rcvdData, int offset) + { + var data = new SwitchCountersData(); + + // TODO + + return data; + } + } +} diff --git a/TBF/BenchControl/ControlBoard/Uni/ValveMoveMsg.cs b/TBF/BenchControl/ControlBoard/Uni/ValveMoveMsg.cs new file mode 100644 index 000000000..a50787f7f --- /dev/null +++ b/TBF/BenchControl/ControlBoard/Uni/ValveMoveMsg.cs @@ -0,0 +1,55 @@ +/// +/// Copyright (c) 2021 Sensus Slovensko a.s. +/// +using System; +using System.Diagnostics; + +namespace TBF.BenchControl.ControlBoard.Uni +{ + class ValveMoveMsg : IOutputMessage + { + 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); + } + } +} diff --git a/TBF/BenchControl/TbfComponents.cs b/TBF/BenchControl/TbfComponents.cs index 9f5a27c3b..b667fb201 100644 --- a/TBF/BenchControl/TbfComponents.cs +++ b/TBF/BenchControl/TbfComponents.cs @@ -21,9 +21,8 @@ namespace TBF.BenchControl Factories.Add(new DataContainers.Buoyancy.ComponentFactory()); Factories.Add(new DataContainers.Density.ComponentFactory()); Factories.Add(new DataContainers.Evaporation.Factory()); - Factories.Add(new ControlBoard.Legacy.ControlBoardFactory()); - Factories.Add(new ControlBoard.New.CBoardFactory()); Factories.Add(new ControlBoard.Papouch.CBoardFactory()); + Factories.Add(new ControlBoard.Uni.Factory()); Factories.Add(new Elde.CoverTest.Factory()); Factories.Add(new DataEntry.Combined.EntryFormFactory()); Factories.Add(new DataEntry.HeatMeters6.Factory()); diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index d21494b77..9556939c1 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -247,6 +247,18 @@ CBoardCfgCtrl.cs + + + + + + + + + + + + @@ -2288,12 +2300,8 @@ EventToolTipCtrl.cs - - UserControl - - - UserControl - + + UserControl @@ -2301,9 +2309,7 @@ ScrollPanelCtrl.cs - - UserControl - + UserControl