324 lines
13 KiB
C#
324 lines
13 KiB
C#
using ByteArrayStyle;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Xylem.Common.CommonCore.Consts;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig.Const;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
|
using Xylem.Common.Metrology.Measurements;
|
|
using Xylem.Common.Metrology.Measurements.Consts;
|
|
|
|
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
|
{
|
|
public partial class GenesisMeter
|
|
{
|
|
/// <summary>
|
|
/// List of ongoing measurements, base- and calibration-measurements
|
|
/// </summary>
|
|
private List<IMeasurement> _listOfIMeasurement = new List<IMeasurement>();
|
|
|
|
/// <summary>
|
|
/// All channels required to process
|
|
/// </summary>
|
|
public Boolean AllChannelsRequired = true;
|
|
|
|
/// <summary>
|
|
/// Quality watch mode can be used to decode intermediate records and check
|
|
/// for actual quality of the measurements.
|
|
/// </summary>
|
|
public Boolean QualityWatchMode;
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
/// <summary>
|
|
/// Perpetration of Measurement
|
|
/// SampleRate 10 and Led mode Test
|
|
/// </summary>
|
|
public void InitMeasurement()
|
|
{
|
|
Logger.Info($"Slot:{Slot} - Init measurement");
|
|
PreMeasurement();
|
|
}
|
|
|
|
private void PreMeasurement()
|
|
{
|
|
if (!SkipPreparationForTestBench)
|
|
{
|
|
//SkipPreparationForTestBench = true;
|
|
//TODO set display unit
|
|
//TODO calculated overflow volume for display
|
|
WriteRegister<Byte>(Register.Genesisflow.SampleRate, 0x08, checkRegister: true);
|
|
WriteRegister(Register.Genesisflow.LedMode, (Byte)LedMode.FlowTestAndCalibData, checkRegister: true);
|
|
WriteRegister("GENESISFLOW_SealDisplay", 0, true, true);
|
|
|
|
try
|
|
{
|
|
var displayState = ReadRegister(Register.Genesisflow.TriggerIdle);
|
|
if (displayState == null)
|
|
{
|
|
displayState = ReadRegister(Register.Genesisflow.TriggerIdle);
|
|
if (displayState == null)
|
|
{
|
|
Logger.Info($"Slot:{Slot} - Not able to read display state");
|
|
return;
|
|
}
|
|
}
|
|
var displayStateString = ByteStyler.ToString(displayState);
|
|
|
|
|
|
if (displayStateString.Substring(0, 2) != "FF" || displayStateString.Substring(0, 5) == "FF-55")
|
|
{
|
|
WriteRegister(Register.Genesisflow.TriggerIdle, 0, true, true);
|
|
displayState = ReadRegister(Register.Genesisflow.TriggerIdle);
|
|
displayStateString = ByteStyler.ToString(displayState);
|
|
if (displayStateString != "00-00-00-00")
|
|
{
|
|
WriteRegister(Register.Genesisflow.TriggerActive, 1);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WriteLog($"meter not active because display code has an error on code:{displayStateString}");
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// ignored
|
|
}
|
|
|
|
|
|
WriteRegister("GENESISFLOW_DisplayPow10", (new Byte[] { 0x00, 0x00, 0x00, 0xFA }).Reverse().ToArray());
|
|
//WriteRegister(Register.Genesisflow.StoreCalibration, 1);
|
|
//WriteRegister(Register.Genesisflow.StoreConfiguration, 1);
|
|
|
|
try
|
|
{
|
|
if (GetRegistersDic().Any(a => a.Key.RegisterName == "GENESISFLOW_DelayedLedOff"))
|
|
{
|
|
WriteRegister("GENESISFLOW_DelayedLedOff", 60 * 60 * 2, false);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
WriteLog($"wait for measurement is starting");
|
|
}
|
|
ProcessStatus = ProcessState.WaitForMeasurement;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void StartMeasurement()
|
|
{
|
|
_listOfIMeasurement = new List<IMeasurement>
|
|
{
|
|
new BaseMeasurement(Slot, typeof(FlowTestRecord), IntermediateUpdateTimeS)
|
|
};
|
|
|
|
//add channels for calibration measurement
|
|
for (var i = 1; i <= MeterConfig.CalibChannels; i++)
|
|
{
|
|
_listOfIMeasurement.Add(new CalibrationMeasurement(Slot, typeof(CalibrationRecord), IntermediateUpdateTimeS, i));
|
|
}
|
|
|
|
foreach (var measurement in _listOfIMeasurement)
|
|
{
|
|
measurement.OnActionStateHasChanged += Measurement_ActionStateHasChanged;
|
|
}
|
|
|
|
Logger.Info($"Slot:{Slot} - Start measurement");
|
|
|
|
ProcessStatus = ProcessState.MeasurementIsActive;
|
|
_listOfIMeasurement.ForEach(m => m.MeasurementState = MeasurementStates.IsWaitingForStartData);
|
|
SyncStreamingBuffer(SyncMarkRecord.SyncStart);
|
|
}
|
|
|
|
|
|
/// <inheritdoc />
|
|
public void StopMeasurement()
|
|
{
|
|
Logger.Info($"Slot:{Slot} - Stop measurement");
|
|
ProcessStatus = ProcessState.MeasurementIsDone;
|
|
_listOfIMeasurement.ForEach(m => m.MeasurementState = MeasurementStates.IsWaitingForEndData);
|
|
SyncStreamingBuffer(SyncMarkRecord.SyncEnd);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Testing the flow direction
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Boolean CheckChannelFlowDirection()
|
|
{
|
|
Boolean? dirPositive = null;
|
|
foreach (var cali in _listOfIMeasurement.Where(m => m.GetType() == typeof(CalibrationRecord)))
|
|
{
|
|
var result = cali.GetIntermediateMeasurementResult();
|
|
var channelDirPositive = result.DutVolumeCm > 0.0;
|
|
|
|
if (!dirPositive.HasValue)
|
|
{
|
|
dirPositive = channelDirPositive;
|
|
}
|
|
if (dirPositive != channelDirPositive)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
/// <summary>
|
|
/// the first measurement is ALWAYS a FlowTestRecord due to the underlying<see cref="GetAllMeasurementResults"/> routine logic.
|
|
/// </summary>
|
|
public MeasurementResults GetMainMeasurementResult(Double? refVolume, Double? refTimeS, Boolean intermediateMeasurement = false, MeasurementDirection dir = MeasurementDirection.TakeBoth)
|
|
{
|
|
if (!intermediateMeasurement && GetMeasurementState(0) != MeasurementStates.IsCompleted)
|
|
{
|
|
throw new ApplicationException("Measurement is not completed");
|
|
}
|
|
return GetAllMeasurementResults(refVolume, refTimeS, intermediateMeasurement, 0).First();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The first measurement is ALWAYS a FlowTestRecord.
|
|
/// </summary>
|
|
public List<MeasurementResults> GetAllMeasurementResults(Double? refVolume, Double? refTimeS, Boolean intermediateMeasurement = false, Int32? channel = null, MeasurementDirection dir = MeasurementDirection.TakeBoth)
|
|
{
|
|
//
|
|
if (!intermediateMeasurement && GetMeasurementState(channel) != MeasurementStates.IsCompleted)
|
|
{
|
|
throw new ApplicationException("Measurement is not completed");
|
|
}
|
|
var mainMeasurement = _listOfIMeasurement.FirstOrDefault(m => m.GetType() == typeof(FlowTestRecord));
|
|
|
|
if (mainMeasurement == null)
|
|
{
|
|
throw new ApplicationException("Can not find an ongoing measurement");
|
|
}
|
|
mainMeasurement.FlowDirectionforCalculatingVol = dir;
|
|
var results = new List<MeasurementResults>();
|
|
var mainResult = intermediateMeasurement
|
|
? mainMeasurement.GetIntermediateMeasurementResult(refVolume, refTimeS)
|
|
: mainMeasurement.GetFinalMeasurementResult(refVolume, refTimeS);
|
|
results.Add(mainResult);
|
|
Logger.Info($"Slot:{Slot}, Channel:{mainMeasurement.GetChannel()} - MeasuredTime({mainResult.DutTimeS}s), " +
|
|
$"MeasuredVolume({mainResult.DutVolumeCm}Qm)");
|
|
|
|
foreach (var otherMeasurement in _listOfIMeasurement.Where(m => m.GetType() != typeof(FlowTestRecord)))
|
|
{
|
|
try
|
|
{
|
|
var otherResults = intermediateMeasurement
|
|
? otherMeasurement.GetIntermediateMeasurementResult(refVolume, refTimeS)
|
|
: otherMeasurement.GetFinalMeasurementResult(refVolume, refTimeS);
|
|
Logger.Info($"Slot:{Slot}, Channel:{otherMeasurement.GetChannel()} - ChannelTime({otherResults.DutTimeS}s), " +
|
|
$"ChannelVolume({otherResults.DutVolumeCm}Qm)");
|
|
results.Add(otherResults);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Warn($"Slot:{Slot}, No Results for channel:{otherMeasurement.GetChannel()} Ex: {ex.Message}");
|
|
if (channel == null)
|
|
{
|
|
throw new ApplicationException($"Can not read result from channel:{otherMeasurement.GetChannel() } Ex: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
private void AddData(IMeasurementRecord newRecord)
|
|
{
|
|
|
|
foreach (var measurement in _listOfIMeasurement)
|
|
{
|
|
if (measurement.GetType() != newRecord.GetType())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (measurement.GetChannel() == newRecord.GetChannel())
|
|
{
|
|
measurement.AddData(newRecord);
|
|
}
|
|
}
|
|
|
|
// when every measurement has state IsRunning or every measurement has state IsCompleted, the streaming buffer set to skip decoding
|
|
if (_listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsRunning)
|
|
|| _listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsCompleted))
|
|
{
|
|
SyncStreamingBuffer(QualityWatchMode
|
|
? SyncMarkRecord.DecodeIntermediateQuality
|
|
: SyncMarkRecord.SkipDecoding);
|
|
}
|
|
|
|
}
|
|
|
|
private void Measurement_ActionStateHasChanged(Object sender, EventArgs e)
|
|
{
|
|
SyncStreamingBuffer(SyncMarkRecord.DecodeIntermediate);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public MeasurementStates GetMeasurementState(Int32? onlyChannelNr = null)
|
|
{
|
|
Logger.Trace($"Slot:{Slot} - Get measurement state");
|
|
if (!_listOfIMeasurement.Any())
|
|
{
|
|
return MeasurementStates.NotStarted;
|
|
}
|
|
|
|
if (onlyChannelNr.HasValue)
|
|
{
|
|
var measurement = _listOfIMeasurement.First(f => f.GetChannel() == onlyChannelNr.Value);
|
|
return measurement.GetMeasurementState();
|
|
}
|
|
return _listOfIMeasurement.Min(m => m.MeasurementState);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Boolean RequestIntermediateMeasurementState(Int32? onlyChannelNr = null)
|
|
{
|
|
Logger.Trace($"Slot:{Slot} - Get measurement state");
|
|
if (!_listOfIMeasurement.Any())
|
|
{
|
|
return false;
|
|
}
|
|
Boolean? ret = null;
|
|
foreach (var item in _listOfIMeasurement)
|
|
{
|
|
if (!onlyChannelNr.HasValue || item.GetChannel() == onlyChannelNr.Value)
|
|
{
|
|
var measurement = _listOfIMeasurement.First(f => onlyChannelNr != null && f.GetChannel() == onlyChannelNr.Value);
|
|
if ((measurement.MeasurementState == MeasurementStates.IsRunning
|
|
|| measurement.MeasurementState == MeasurementStates.IsWaitingForIntermediateData))
|
|
{
|
|
measurement.RequestIntermediateRecord();
|
|
if (!ret.HasValue)
|
|
{
|
|
ret = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = false;
|
|
}
|
|
}
|
|
}
|
|
return ret.HasValue ? ret.Value : false;
|
|
}
|
|
}
|
|
}
|