common/CordonelPreadjustmentUi/ZeroFlowGenesisMeter.cs

417 lines
16 KiB
C#
Raw Permalink Normal View History

2026-04-23 15:50:07 +00:00
using CordonelPreadjustmentUi.Const;
using CordonelPreadjustmentUi.Helper;
using Logic.ProductionToProductMapper.Cordonel;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using Logic.ProductionToProductMapper.Cordonel;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using Xylem.Common.Hardware.Interfaces.Protocols.ProtocolCore.EventArguments;
using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments;
using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Ui.CordonelPreadjustmentUi.Helper.Extensions;
namespace CordonelPreadjustmentUi
{
public class ZeroFlowGenesisMeter : GenesisMeter
{
#region Data logging
private bool logZeroFlow = false;
public bool logAmpTest = false;
#endregion
private CultureInfo GlobalCulture { get; set; }
public Byte Gp30LastByte { get; set; }
private Byte[] GP30LastRegister { get; set; }
public void SetGP30LastRegister(Byte[] data)
{
GP30LastRegister = data;
}
private Byte GP30LastPayloadLsb { get; set; }
public Byte GP30LastCommand { get; set; }
private Byte GP30RXPayload { get; set; }
private Boolean GP30RequestStarted { get; set; }
private Boolean GP30RequestFailed { get; set; }
private Boolean GP30RequestGotAnswer { get; set; }
private Byte Privilege { get; set; }
private Byte FirstHitLevelUpPath0 { get; set; }
private Byte FirstHitLevelUpPath1 { get; set; }
private Byte FirstHitLevelUpPath2 { get; set; }
private Byte FirstHitLevelDownPath0 { get; set; }
private Byte FirstHitLevelDownPath1 { get; set; }
private Byte FirstHitLevelDownPath2 { get; set; }
private Byte PercentPath0 { get; set; }
private Byte PercentPath1 { get; set; }
private Byte PercentPath2 { get; set; }
public Byte Subreason { get; set; }
private Byte Starthit { get; set; }
private Byte StoreCalibration { get; set; }
private Byte Amplitude { get; set; }
private Byte Samplerate { get; set; }
private UInt16 CalibrationFactorPath0 { get; set; }
private UInt16 CalibrationFactorPath1 { get; set; }
private UInt16 CalibrationFactorPath2 { get; set; }
private Int32 ZeroOffsetPath0 { get; set; }
private Int32 ZeroOffsetPath1 { get; set; }
private Int32 ZeroOffsetPath2 { get; set; }
private Byte LedMode { get; set; }
private Byte UpdatePeriode { get; set; }
private Byte FirstHitShift { get; set; }
private UInt32 ToFTempCalibrate { get; set; }
private Int32 ToFTempOffsetPath0 { get; set; }
private Int32 ToFTempOffsetPath1 { get; set; }
private Int32 ToFTempOffsetPath2 { get; set; }
public Int32 MeterNumber { get; set; }
private Byte MeterSize { get; set; }
public bool CalculationIndicatorZeroFlowTest { get; private set; }
public bool LoggingIndicatorZeroFlowTest { get; private set; }
public long ZeroflowOffsetTestNumberOfLines { get; private set; }
public Boolean LogOnEnable;
public Boolean AmplitudeEnable;
public Boolean ZeroFlowOffsetEnable;
public Boolean TempCalEnable;
public Boolean CompletionEnable;
public Boolean LoginFailed;
public Boolean PreparationFailed;
public Boolean AmplitudeFailed;
public Boolean ZeroFlowOffsetFailed;
public Boolean TempCalFailed;
public Boolean CompletionFailed;
public Boolean Ok;
public Boolean EmptyPipeCheckEnable;
public Boolean EmptyPipeCheckFailed;
public Boolean MeterSelected;
public CalibrationResult calibrationResult = new CalibrationResult();
public ConcurrentQueue<CalibrationRecord> CurrentRecords = new ConcurrentQueue<CalibrationRecord>();
public ZeroFlowGenesisMeter(int Slot, int PathsCount = 3, bool ignorCurruptdata = true) : base()
{
base.SetupFromConfigFile(Slot, ignorCurruptdata);
//base.EnableAutoLogon();
Setup(PathsCount);
//on zeroflow every param has to be stored
Configuration.UseRegisterWatchService = true;
Configuration.RegisterWatchServiceUrl = Xylem.Common.CommonCore.Configuration.ServiceUrls.RegisterWatchServiceUrl();
}
public ZeroFlowGenesisMeter(int Slot, int PathsCount, PortConfig request, PortConfig streaming, bool ignoreCurrptData) : base()
{
base.SetupGenesisMeter(Slot, request, streaming, ignoreCurrptData);
// base.EnableAutoLogon();
Setup(PathsCount);
//overide register watch service
//on zeroflow every param has to be stored
Configuration.UseRegisterWatchService = true;
}
private void Setup(int PathsCount)
{
base.LogRawData(true);
this.GP30LastRegister = new Byte[2] { 0, 0 };
this.GP30LastPayloadLsb = 0;
this.GP30LastCommand = 0;
this.GP30RXPayload = 0;
this.GP30RequestStarted = false;
this.GP30RequestFailed = false;
this.GP30RequestGotAnswer = false;
this.FirstHitLevelUpPath0 = 0;
this.FirstHitLevelUpPath1 = 0;
this.FirstHitLevelUpPath2 = 0;
this.FirstHitLevelDownPath0 = 0;
this.FirstHitLevelDownPath1 = 0;
this.FirstHitLevelDownPath2 = 0;
this.Starthit = 0;
this.Amplitude = 0;
this.Samplerate = 0;
this.CalibrationFactorPath0 = 0;
this.CalibrationFactorPath1 = 0;
this.CalibrationFactorPath2 = 0;
this.ZeroOffsetPath0 = 0;
this.ZeroOffsetPath1 = 0;
this.ZeroOffsetPath2 = 0;
this.LedMode = 0;
this.MeterNumber = Slot;
this.GlobalCulture = CultureInfo.CreateSpecificCulture("en-US");
this.Gp30LastByte = 0;
linesRecived = new MultiPathDataLogContainer<Int64>(PathsCount);
listOfTotalTimeOfFlightSPerPath = new ActivityCheckMultiPathDataLogContainer<List<Double>>(PathsCount);
listOfTotalTimeOfFlightSPerPath.Update(null, new List<Double>());
BadDataCounterZeroFlowTest = new MultiPathDataLogContainer<Int64>(PathsCount);
LineCounterZeroFlowTest = new MultiPathDataLogContainer<Int64>(PathsCount);
AmplitudeValuesUp = new MultiPathDataLogContainer<List<double>>(PathsCount);
AmplitudeValuesDown = new MultiPathDataLogContainer<List<double>>(PathsCount);
DeltaTimeOfFlightAverage = new MultiPathDataLogContainer<List<double>>(PathsCount);
Decoded = new MultiPathDataLogContainer<CalibrationRecord>(PathsCount);
}
public Boolean CheckStreamingPort()
{
if (!StreamingPort.IsOpen())
{
base.StreamingPort.Open();
}
return StreamingPort.IsOpen();
}
public Boolean CheckRequestPort()
{
if (!RequestPort.IsOpen())
{
base.RequestPort.Open();
}
return RequestPort.IsOpen();
}
public void StartRecordData(int zeroflowOffsetTestNumberOfLines = 0)
{
CurrentRecords.Clear();
StreamingProtocol.OnRecordIsDecoded += StreamingProtocol_OnRecordIsDecoded; ;
SyncStreamingBuffer(SyncMarkRecord.DecodeEveryPackage);
ZeroflowOffsetTestNumberOfLines = zeroflowOffsetTestNumberOfLines;
}
private List<string> logContent = new List<String>();
public ActivityCheckMultiPathDataLogContainer<List<double>> listOfTotalTimeOfFlightSPerPath;
private MultiPathDataLogContainer<Int64> linesRecived;
private MultiPathDataLogContainer<Int64> BadDataCounterZeroFlowTest;
private MultiPathDataLogContainer<Int64> LineCounterZeroFlowTest;
private MultiPathDataLogContainer<List<double>> AmplitudeValuesUp;
private MultiPathDataLogContainer<List<double>> AmplitudeValuesDown;
private MultiPathDataLogContainer<List<double>> DeltaTimeOfFlightAverage;
private MultiPathDataLogContainer<CalibrationRecord> Decoded;
internal void DataLog(string text)
{
logContent.Add(text);
//todo nlog!
}
private void StreamingProtocol_OnRecordIsDecoded(object sender, BaseDataEventArgs e)
{
try
{
if (e is CalibDataEventArgs)
{
var decodedDate = (CalibDataEventArgs)e;
var data = decodedDate.CalibChl;
if (Slot == 10 && data.Channel == 2)
{
String time = DateTime.Now.ToString(Formats.RawDataDateTimeLogString);
DataLog($"{time} {decodedDate.RawData}\n");
}
CurrentRecords.Enqueue(data);
//todo make new imesturementrecord according to units need by zeroflow app
var TotalTimeOfFlightS = data.TotalTimeOfFlightS * 1000000;
Double temp = data.DeltaTimeOfFlightS;
//data.DeltaTimeOfFlightS = data.DeltaTimeOfFlightS * (1.0 / 0x4000000000); // 2^38;
data.AmplitudeUpV = data.AmplitudeUpV * 1000.0;
data.AmplitudeDownV = data.AmplitudeDownV * 1000.0;
#region Logging (Zero flow test)
if (logZeroFlow || logAmpTest)
{
String time = DateTime.Now.ToString(Formats.RawDataDateTimeLogString);
DataLog($"{time} {decodedDate.RawData}\n");
}
#endregion
#region Add to list h-protocol
UInt16 Path = (UInt16)(decodedDate.CalibChl.Channel - 1);
//todo check if isValid == crc Ok
if (decodedDate.CalibChl.IsValid)
{
#region Activity check for empty pipe test
linesRecived.Update(Path, linesRecived.Get(Path) + 1);
#endregion
#region Data for amplitude test
if (logAmpTest)
{
DataLog($"Add {TotalTimeOfFlightS} for chnl {Path}\n");
var tmp = listOfTotalTimeOfFlightSPerPath.Get(Path).ToList();
tmp.Add(TotalTimeOfFlightS);
listOfTotalTimeOfFlightSPerPath.Update(Path, tmp);
}
#endregion
#region Data for zero flow test
var meterDone = true;
for (int i = 0; i < LineCounterZeroFlowTest.GetPathCount(); i++)
{
if (LineCounterZeroFlowTest.Get(i) < ZeroflowOffsetTestNumberOfLines)
{
meterDone = false;
}
}
if (meterDone)
{
CalculationIndicatorZeroFlowTest = false;
LoggingIndicatorZeroFlowTest = false;
}
if (CalculationIndicatorZeroFlowTest)
{
#region Bad data check
if (decodedDate.CalibChl.Validation == DataErrorCodes.NoError)
{
AmplitudeValuesUp.Get(Path).Add(decodedDate.CalibChl.AmplitudeUpV);
AmplitudeValuesDown.Get(Path).Add(decodedDate.CalibChl.AmplitudeDownV);
DeltaTimeOfFlightAverage.Get(Path).Add(decodedDate.CalibChl.DeltaTimeOfFlightS);
LineCounterZeroFlowTest.Update(Path, LineCounterZeroFlowTest.Get(Path) + 1);
}
else
{
BadDataCounterZeroFlowTest.Update(Path, BadDataCounterZeroFlowTest.Get(Path) + 1);
}
#endregion
}
#endregion
}
#endregion
#region Copy to global object
Decoded.Update(Path, data);
#endregion
}
}
catch (Exception ex)
{
DataLog($"Exception occur {e}\n");
}
}
public void StopRecordData()
{
StreamingProtocol.OnRecordIsDecoded -= StreamingProtocol_OnRecordIsDecoded;
SyncStreamingBuffer(SyncMarkRecord.SkipDecoding);
}
internal void Flush()
{
if (StreamingPort == null)
{
throw new ApplicationException("Synchronization not possible due to undefined streaming port");
}
SyncStreamingBuffer(SyncMarkRecord.FlushBuffer);
}
public new Boolean WriteRegisterUnsafe<T>(string reg, T value)
{
var RetrysLeft = 8;
while (RetrysLeft >= 0)
{
try
{
var result = base.WriteRegister(reg, value, true, false);
if (result)
{
return result;
}
Thread.Sleep(1500);
}
catch (Exception e)
{
base.WriteLog($"Can not WriteRegisterUnsafe retry left: {RetrysLeft}, message: {e.Message}");
}
RetrysLeft = RetrysLeft - 1;
}
return false;
}
public new Boolean WriteRegisterSafe<T>(string reg, T value)
{
var RetrysLeft = 8;
while (RetrysLeft >= 0)
{
try
{
var result = base.WriteRegister(reg, value, true, true);
if (result)
{
return result;
}
Thread.Sleep(1500);
}
catch (Exception e)
{
base.WriteLog($"Can not WriteRegisterUnsafe retry left: {RetrysLeft}, message: {e.Message}");
}
RetrysLeft = RetrysLeft - 1;
}
return false;
}
public new Byte[] ReadRegister(string reg)
{
var RetrysLeft = 8;
Exception lastEx = null;
while (RetrysLeft >= 0)
{
try
{
return base.ReadRegister(reg);
}
catch (Exception e)
{
lastEx = e;
base.WriteLog($"Can not WriteRegisterUnsafe retry left: {RetrysLeft}, message: {e.Message}");
}
Thread.Sleep(1500);
RetrysLeft = RetrysLeft - 1;
}
if (lastEx == null)
{
throw new ApplicationException("something went totally wrong on ReadRegister. no Exception found");
}
throw new ApplicationException($"something went wrong on ReadRegister.Message{lastEx.Message}");
}
}
}