ControlBoard.Uni component added.
This commit is contained in:
@@ -71,7 +71,8 @@ namespace TBF.BenchControl.ControlBoard.Legacy
|
|||||||
ErrorPressMeter2 = 0x2000000000000,
|
ErrorPressMeter2 = 0x2000000000000,
|
||||||
ErrorPressMeter3 = 0x4000000000000,
|
ErrorPressMeter3 = 0x4000000000000,
|
||||||
ErrorPressMeter4 = 0x8000000000000,
|
ErrorPressMeter4 = 0x8000000000000,
|
||||||
}
|
EndurCycleRunning = 0x200000000000000, /// bit 57
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public enum StopDevs
|
public enum StopDevs
|
||||||
|
|||||||
@@ -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<IOutputMessage> 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
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Select devices used for control and measurement
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outPath"></param>
|
||||||
|
public OutputPath Devices { set; get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for user interfaces (change settings only).
|
||||||
|
/// Initialize(), RunDeviceXY() and StopDevice() methods of the created object will not be called.
|
||||||
|
/// </summary>
|
||||||
|
public CBoard()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor invoked when starting the test bench and creating components.
|
||||||
|
/// </summary>
|
||||||
|
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<IOutputMessage>();
|
||||||
|
|
||||||
|
serialPort = null;
|
||||||
|
buffer = new byte[BUFFER_SIZE];
|
||||||
|
rcvdData = new byte[BUFFER_SIZE];
|
||||||
|
cumulativeSums = new int[BUFFER_SIZE];
|
||||||
|
rcvdBytesCount = 0;
|
||||||
|
|
||||||
|
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 (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reecive and process data from the control board serial port
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send data to the control board serial port
|
||||||
|
/// </summary>
|
||||||
|
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<BuiltIn.ValveEx.Valve> extendedValves) { return 0; }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Operations
|
||||||
|
///
|
||||||
|
public IOperation SetFlowOp(double flowLimLo, double flowLimHi, TBF.Boxes.DoubleBox measuredFlow, int timeout)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOperation StopFlowRegulationOp()
|
||||||
|
{
|
||||||
|
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 valveToOpen, IValve valveToClose)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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> valvesToOpen, IList<IValve> valvesToClose)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open start/stop valve.
|
||||||
|
/// Events: ValvesSet, ValvesBusy, Error
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Created operation</returns>
|
||||||
|
public IOperation OpenStartValveOp()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close start/stop valve.
|
||||||
|
/// Events: ValvesSet, ValvesBusy, Error
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Created operation</returns>
|
||||||
|
public IOperation CloseStartValveOp()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds backup and security options - serializable configuration.
|
||||||
|
/// </summary>
|
||||||
|
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<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 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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,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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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.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<IComponent> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
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); }
|
||||||
|
|
||||||
|
|
||||||
|
/// <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)
|
||||||
|
{
|
||||||
|
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 !!!!!!!!!!!!!!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Byte positions in rcvdData buffer
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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.BenchControl.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,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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,9 +21,8 @@ namespace TBF.BenchControl
|
|||||||
Factories.Add(new DataContainers.Buoyancy.ComponentFactory());
|
Factories.Add(new DataContainers.Buoyancy.ComponentFactory());
|
||||||
Factories.Add(new DataContainers.Density.ComponentFactory());
|
Factories.Add(new DataContainers.Density.ComponentFactory());
|
||||||
Factories.Add(new DataContainers.Evaporation.Factory());
|
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.Papouch.CBoardFactory());
|
||||||
|
Factories.Add(new ControlBoard.Uni.Factory());
|
||||||
Factories.Add(new Elde.CoverTest.Factory());
|
Factories.Add(new Elde.CoverTest.Factory());
|
||||||
Factories.Add(new DataEntry.Combined.EntryFormFactory());
|
Factories.Add(new DataEntry.Combined.EntryFormFactory());
|
||||||
Factories.Add(new DataEntry.HeatMeters6.Factory());
|
Factories.Add(new DataEntry.HeatMeters6.Factory());
|
||||||
|
|||||||
+15
-9
@@ -247,6 +247,18 @@
|
|||||||
<DependentUpon>CBoardCfgCtrl.cs</DependentUpon>
|
<DependentUpon>CBoardCfgCtrl.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="BenchControl\ControlBoard\Papouch\CBoardFactory.cs" />
|
<Compile Include="BenchControl\ControlBoard\Papouch\CBoardFactory.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\CBoard.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\CBoardCfg.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\CommandMsg.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\DivTransitionData.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\Enums.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\ExtremaData.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\Factory.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\IOutputMessage.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\GeneralData.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\ScopeAnalyzerData.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\SwitchCountersData.cs" />
|
||||||
|
<Compile Include="BenchControl\ControlBoard\Uni\ValveMoveMsg.cs" />
|
||||||
<Compile Include="BenchControl\DataContainers\BackupAndSecurityOptions\Component.cs" />
|
<Compile Include="BenchControl\DataContainers\BackupAndSecurityOptions\Component.cs" />
|
||||||
<Compile Include="BenchControl\DataContainers\BackupAndSecurityOptions\ComponentCfg.cs" />
|
<Compile Include="BenchControl\DataContainers\BackupAndSecurityOptions\ComponentCfg.cs" />
|
||||||
<Compile Include="BenchControl\DataContainers\BackupAndSecurityOptions\ComponentFactory.cs" />
|
<Compile Include="BenchControl\DataContainers\BackupAndSecurityOptions\ComponentFactory.cs" />
|
||||||
@@ -2288,12 +2300,8 @@
|
|||||||
<DependentUpon>EventToolTipCtrl.cs</DependentUpon>
|
<DependentUpon>EventToolTipCtrl.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="UI\Calendar\HolidayEvent.cs" />
|
<Compile Include="UI\Calendar\HolidayEvent.cs" />
|
||||||
<Compile Include="UI\Calendar\NavigateLeftButtonCtrl.cs">
|
<Compile Include="UI\Calendar\NavigateLeftButtonCtrl.cs" />
|
||||||
<SubType>UserControl</SubType>
|
<Compile Include="UI\Calendar\NavigateRightButtonCtrl.cs" />
|
||||||
</Compile>
|
|
||||||
<Compile Include="UI\Calendar\NavigateRightButtonCtrl.cs">
|
|
||||||
<SubType>UserControl</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="UI\Calendar\RectangleComparer.cs" />
|
<Compile Include="UI\Calendar\RectangleComparer.cs" />
|
||||||
<Compile Include="UI\Calendar\ScrollPanelCtrl.cs">
|
<Compile Include="UI\Calendar\ScrollPanelCtrl.cs">
|
||||||
<SubType>UserControl</SubType>
|
<SubType>UserControl</SubType>
|
||||||
@@ -2301,9 +2309,7 @@
|
|||||||
<Compile Include="UI\Calendar\ScrollPanelCtrl.Designer.cs">
|
<Compile Include="UI\Calendar\ScrollPanelCtrl.Designer.cs">
|
||||||
<DependentUpon>ScrollPanelCtrl.cs</DependentUpon>
|
<DependentUpon>ScrollPanelCtrl.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="UI\Calendar\TodayButtonCtrl.cs">
|
<Compile Include="UI\Calendar\TodayButtonCtrl.cs" />
|
||||||
<SubType>UserControl</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="UI\Camera\CameraPictureCtrl.cs">
|
<Compile Include="UI\Camera\CameraPictureCtrl.cs">
|
||||||
<SubType>UserControl</SubType>
|
<SubType>UserControl</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
Reference in New Issue
Block a user