905 lines
32 KiB
C#
905 lines
32 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
|
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
|
|
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
|
|
using Xylem.Common.Utils.ProcessExec;
|
|
using Xylem.Common.Utils.ProcessExec.EventArguments;
|
|
|
|
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|
{
|
|
/// <summary>
|
|
/// Meter lookup table for metrology update procedure
|
|
/// </summary>
|
|
public class MeterLutUpdate : IProcessState
|
|
{
|
|
#region Variables
|
|
|
|
/// <summary>
|
|
/// Port scan result event for message dispatcher to caller
|
|
/// </summary>
|
|
public event EventHandler<ProcessExecEventArgs> OnProcessUpdate;
|
|
|
|
//error mask for unsuccessfully written LUT CRC
|
|
private const UInt32 LutCrcErrorMask = 0x8000000;
|
|
|
|
/// <summary>
|
|
/// Threshold for power correction EMEA version
|
|
/// </summary>
|
|
public const UInt32 EmeaFwThresholdForLutFile= 0x1200;
|
|
/// <summary>
|
|
/// Threshold for power correction NA version
|
|
/// </summary>
|
|
public const UInt32 NaFwThresholdForLutFile = 0x2000;
|
|
|
|
//trigger update retries
|
|
private const Int32 RegisterWriteRetries = 0;
|
|
|
|
//update reties for files
|
|
private const Int32 FileWriteRetries = 1;
|
|
|
|
//retry of entire update procedure
|
|
private const Int32 UpdateProcedureRetries = 1;
|
|
|
|
//threshold to increase the file write timing
|
|
private const Int32 IncreaseTimeoutUpdateProcedureRetries = 4;
|
|
|
|
private Int32 _updateProcedureRetryCtr;
|
|
|
|
private IGenesisMeter _genesisMeter;
|
|
private MeterFile _meterFile;
|
|
|
|
// Text for caller to inform about actual process being carried out
|
|
private String _actualOperation;
|
|
private LutUpdateState _lutUpdateState;
|
|
private LutUpdateState _lutBackupUpdateState;
|
|
|
|
// Look up table file
|
|
public MeterLutFile LutFile;
|
|
|
|
// list of names of installed meter files on drive 1
|
|
private List<String> _meterFilesDrive1;
|
|
|
|
// number of operations for over all access
|
|
private const Int32 NumberOfOperations = 11;
|
|
private Int32 _operationCtr;
|
|
|
|
|
|
// error message for display of error reason
|
|
public String ErrorMessage;
|
|
|
|
// manual stop of update process
|
|
private Boolean _stopUpdateProcess;
|
|
|
|
|
|
/// <summary>
|
|
/// Register subset needed to adjust for update performance content before update
|
|
/// </summary>
|
|
private readonly Dictionary<String, Byte[]> _registersBeforeUpdate = new Dictionary<String, Byte[]>();
|
|
|
|
/// <summary>
|
|
/// Register to restore after update
|
|
/// </summary>
|
|
private Dictionary<String, Byte[]> _registersAfterUpdate = new Dictionary<String, Byte[]>();
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
/// <summary>
|
|
/// Process update event
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
/// <remarks date="2020-Dec-10" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public virtual void ProcessUpdate_Event(Object sender, ProcessExecEventArgs e)
|
|
{
|
|
//// copy text from overall messages to actual, because this is from sub-routine
|
|
//OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(_overallOperation,
|
|
// OverallProcessCtrPercent, _actualOperation, e.OverallProcessPercent));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Information
|
|
|
|
/// <summary>
|
|
/// Process counter in percent
|
|
/// </summary>
|
|
/// <remarks date="2022-Mar-03" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Double OverallProcessCtrPercent => 100.0 * _operationCtr / NumberOfOperations;
|
|
|
|
/// <summary>
|
|
/// Single file process counter in percent
|
|
/// </summary>
|
|
/// <remarks date="2019-Jun-24" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Double SingleFileProcessCtrPercent => _meterFile?.ProcessCtrPercent ?? 0;
|
|
|
|
#endregion
|
|
|
|
#region CtorAssignment
|
|
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <param name="genesisMeter"></param>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public MeterLutUpdate(IGenesisMeter genesisMeter)
|
|
{
|
|
if (genesisMeter == null)
|
|
return;
|
|
AssignGenesis(genesisMeter);
|
|
|
|
if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "GENESISFLOW" && f.IsInstalled))
|
|
{
|
|
_registersBeforeUpdate.Add(Register.Genesisflow.LedMode, new[] { (Byte)LedMode.Off });
|
|
_registersBeforeUpdate.Add(Register.Genesisflow.SampleRate, new Byte[] { 1 });
|
|
}
|
|
if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "METROLOGYASST" && f.IsInstalled))
|
|
_registersBeforeUpdate.Add(Register.Metrologyasst.PulseMode, new Byte[] { 0 });
|
|
//deny access if NA product, because this does not have the radio app installed
|
|
if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "SENSUSRADIO" && f.IsInstalled))
|
|
_registersBeforeUpdate.Add(Register.Sensusradio.WakeupInterval, new Byte[] { 6 });
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assign new genesis
|
|
/// </summary>
|
|
/// <param name="genesisMeter"></param>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public void AssignGenesis(IGenesisMeter genesisMeter)
|
|
{
|
|
_genesisMeter = genesisMeter;
|
|
_actualOperation = "";
|
|
_lutUpdateState = LutUpdateState.Idle;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
if (_meterFile == null)
|
|
return;
|
|
_meterFile.OnProcessUpdate -= ProcessUpdate_Event;
|
|
_meterFile = null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ProcessInformation
|
|
|
|
/// <summary>
|
|
/// Returns the actual file in process for update
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2019-Jun-20" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public String GetActualOperation()
|
|
{
|
|
return _actualOperation;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the LUT Update state
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public String GetLutUpdateStateOperation()
|
|
{
|
|
// search text assigned to current state
|
|
var text = LutUpdateStateInfo.GetTextFromState(_lutUpdateState);
|
|
if (_lutUpdateState == LutUpdateState.Idle)
|
|
{
|
|
return text;
|
|
}
|
|
|
|
text += _updateProcedureRetryCtr > 0 ? $"Retry {_updateProcedureRetryCtr}" : "";
|
|
return text;
|
|
}
|
|
#endregion
|
|
|
|
#region Actions
|
|
|
|
/// <summary>
|
|
/// Try to re-establish the file system, therefor logout to close all open files
|
|
/// and login again.
|
|
/// </summary>
|
|
/// <remarks date="2019-Jun-21" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2019-Jun-28" author="Thomas Wiedebusch">
|
|
/// - Enable auto-logon added
|
|
/// </remarks>
|
|
/// <remarks date="2019-Jul-03" author="Thomas Wiedebusch">
|
|
/// - Removed auto-logon
|
|
/// </remarks>
|
|
public void ReestablishMeterFileSystem()
|
|
{
|
|
_genesisMeter?.Logout();
|
|
_genesisMeter?.ReLogin();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stop the update process
|
|
/// </summary>
|
|
public Boolean StopUpdateProcess
|
|
{
|
|
get => _stopUpdateProcess;
|
|
set
|
|
{
|
|
_stopUpdateProcess = value;
|
|
if (_meterFile != null)
|
|
{
|
|
_meterFile.StopProcess = value;
|
|
}
|
|
|
|
_lutUpdateState = LutUpdateState.UpdateFailed;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update meter lookup table
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean UpdateMeterLut()
|
|
{
|
|
if (!UpdatePreparation())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
_operationCtr = 0;
|
|
_actualOperation = "";
|
|
ErrorMessage = "";
|
|
_lutUpdateState = LutUpdateState.StartInitial;
|
|
_lutBackupUpdateState = LutUpdateState.Idle;
|
|
while (_lutUpdateState != LutUpdateState.Idle && !StopUpdateProcess)
|
|
{
|
|
LutUpdateStateMachine();
|
|
}
|
|
|
|
return ExitPreparation(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upload lookup table file and compare with the loaded from file system
|
|
/// </summary>
|
|
/// <remarks date="2019-Jun-29" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean VerifyLutFile()
|
|
{
|
|
if (!UpdatePreparation())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ExitPreparation(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset lookup table update process and all lists and counters
|
|
/// </summary>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public void ResetAll()
|
|
{
|
|
LutFile = null;
|
|
//remove the update stop action
|
|
StopUpdateProcess = false;
|
|
|
|
//reset all counters
|
|
_updateProcedureRetryCtr = 0;
|
|
|
|
//set state machine for automatic FW update
|
|
_lutUpdateState = LutUpdateState.Idle;
|
|
_lutBackupUpdateState = LutUpdateState.Idle;
|
|
_actualOperation = "";
|
|
_operationCtr = 0;
|
|
|
|
//logout/login/auto-login
|
|
ReestablishMeterFileSystem();
|
|
_genesisMeter?.Logout();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common update preparation and check
|
|
/// </summary>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean UpdatePreparation()
|
|
{
|
|
_actualOperation = "Update preparation";
|
|
_lutUpdateState = LutUpdateState.Idle;
|
|
|
|
_meterFile = new MeterFile(_genesisMeter);
|
|
if (_meterFile != null)
|
|
_meterFile.OnProcessUpdate += ProcessUpdate_Event;
|
|
_genesisMeter?.ReLogin();
|
|
_genesisMeter?.SetProcessState(DisplayCodes.FwUpdateActive, webRequest: false);
|
|
|
|
if (_genesisMeter == null || !_genesisMeter.IsLoggedOn)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//set default timeout for file write operation
|
|
_meterFile.SetDefaultFileWriteTimeout();
|
|
|
|
//switch LED off set sample rate to 1 -> 1Hz to slow down CPU load
|
|
_registersAfterUpdate = new Dictionary<String, Byte[]>();
|
|
foreach (var item in _registersBeforeUpdate)
|
|
{
|
|
var writeBackValue = _genesisMeter.ReadRegister(item.Key);
|
|
_registersAfterUpdate.Add(item.Key, writeBackValue);
|
|
_genesisMeter.WriteRegister(item.Key, item.Value);
|
|
|
|
}
|
|
//remove the update stop action
|
|
StopUpdateProcess = false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Common exit routine
|
|
/// </summary>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean ExitPreparation(Boolean returnValue)
|
|
{
|
|
if (_meterFile != null)
|
|
_meterFile.OnProcessUpdate -= ProcessUpdate_Event;
|
|
_meterFile = null;
|
|
ReestablishMeterFileSystem();
|
|
|
|
foreach (var item in _registersAfterUpdate)
|
|
{
|
|
_genesisMeter.WriteRegister(item.Key, item.Value);
|
|
}
|
|
|
|
_genesisMeter?.Logout();
|
|
if (!StopUpdateProcess)
|
|
{
|
|
return returnValue;
|
|
}
|
|
|
|
_actualOperation = "";
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region StateMachine
|
|
|
|
/// <summary>
|
|
/// State machine for metrology lookup table update process
|
|
/// </summary>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
|
/// - Introduced lock for repeated execution of state machine
|
|
/// </remarks>
|
|
/// <remarks date="2023-Jan-16" author="Thomas Wiedebusch">
|
|
/// - Started state machine with download of new mettbl.
|
|
/// </remarks>
|
|
private void LutUpdateStateMachine()
|
|
{
|
|
if (_lutBackupUpdateState == _lutUpdateState)
|
|
{
|
|
Thread.Sleep(1);
|
|
}
|
|
else
|
|
{
|
|
// remind backup state to avoid repeated execution and side effects
|
|
_lutBackupUpdateState = _lutUpdateState;
|
|
switch (_lutUpdateState)
|
|
{
|
|
case LutUpdateState.Idle:
|
|
break;
|
|
|
|
case LutUpdateState.StartInitial:
|
|
_updateProcedureRetryCtr = 0;
|
|
_lutUpdateState = LutUpdateState.DownloadLutFile;
|
|
break;
|
|
|
|
case LutUpdateState.EraseLutFile:
|
|
_lutUpdateState = EraseLutFiles() ? LutUpdateState.DownloadLutFile : LutUpdateState.StepFailed;
|
|
break;
|
|
|
|
case LutUpdateState.DownloadLutFile:
|
|
_lutUpdateState = DownloadLutFiles() ? LutUpdateState.UploadLutFile : LutUpdateState.StepFailed;
|
|
break;
|
|
|
|
case LutUpdateState.UploadLutFile:
|
|
_lutUpdateState = UploadAndCompareLutFiles() ? LutUpdateState.FinalizeLutDownload : LutUpdateState.StepFailed;
|
|
break;
|
|
|
|
case LutUpdateState.FinalizeLutDownload:
|
|
_lutUpdateState =
|
|
FinalizeLutDownload() ? LutUpdateState.Idle : LutUpdateState.StepFailed;
|
|
break;
|
|
|
|
case LutUpdateState.CompareLutFile:
|
|
break;
|
|
|
|
case LutUpdateState.StepFailed:
|
|
_lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
|
|
? LutUpdateState.RepeatLutUpdate
|
|
: LutUpdateState.UpdateFailed;
|
|
break;
|
|
|
|
case LutUpdateState.RepeatLutUpdate:
|
|
_lutUpdateState = LutUpdateState.DownloadLutFile;
|
|
if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries)
|
|
{
|
|
_meterFile?.SetExtremeFileWriteTimeout();
|
|
}
|
|
|
|
break;
|
|
|
|
case LutUpdateState.UpdateFailed:
|
|
StopUpdateProcess = true;
|
|
_lutUpdateState = LutUpdateState.Idle;
|
|
break;
|
|
|
|
case LutUpdateState.LutUpdateStateListDelimiter:
|
|
_lutUpdateState = LutUpdateState.Idle;
|
|
break;
|
|
|
|
default:
|
|
_lutUpdateState = LutUpdateState.Idle;
|
|
break;
|
|
}
|
|
}// lock for identical state
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region LutFile
|
|
/// <summary>
|
|
/// Check the content of the metrology lookup table file
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-25" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2023-Nov-13" author="Thomas Wiedebusch">
|
|
/// - LUT file validation exported to <see cref="MeterLutFile.ValidateLutFormat"/>
|
|
/// </remarks>
|
|
private Boolean ValidateLutFile()
|
|
{
|
|
// Take the file content to validate the format based
|
|
var lutFileFormatValid = LutFile.ValidateLutFormat();
|
|
if (LutFile.CrcError)
|
|
{
|
|
ErrorMessage = "CRC mismatch!";
|
|
return false;
|
|
}
|
|
|
|
// check if LUT file contains data
|
|
if (LutFile?.BinData == null || LutFile.BinData.Count != LutFile.SizeLutFile)
|
|
{
|
|
ErrorMessage = "File size mismatch!";
|
|
return false;
|
|
}
|
|
|
|
return lutFileFormatValid;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Download the CRC, the meter size and store calibration as preparation for the lookup table
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2023-Jan-19" author="Thomas Wiedebusch">
|
|
/// - Used genesis meter lut crc, region and meter size read back procedure.
|
|
/// </remarks>
|
|
private Boolean FinalizeLutDownload()
|
|
{
|
|
var returnValue = true;
|
|
|
|
var retryCtr = 0;
|
|
if (LutFile == null || _genesisMeter == null || _meterFile == null)
|
|
return false;
|
|
// set extended timeout for trigger upgrade response delay
|
|
_genesisMeter.TransmitProtocol.SetResponseTimeout(5000);
|
|
do
|
|
{
|
|
// for repeated entry
|
|
if (!returnValue)
|
|
{
|
|
ReestablishMeterFileSystem();
|
|
}
|
|
|
|
_actualOperation = "Write Lut CRC to meter";
|
|
_operationCtr++;
|
|
returnValue = _genesisMeter.WriteRegister<UInt32>(Register.Genesisflow.LookupFileCrc, LutFile.FileCrc);
|
|
if (!returnValue)
|
|
{
|
|
const String txt = "Meter LUT CRC could not be set!";
|
|
ErrorMessage = txt;
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
_operationCtr--;
|
|
continue;
|
|
}
|
|
|
|
_operationCtr++;
|
|
_actualOperation = "Write meter size";
|
|
returnValue =
|
|
_genesisMeter.WriteRegister(Register.Genesisflow.MeterSize, new[] { (Byte)LutFile.MeterSize });
|
|
if (!returnValue)
|
|
{
|
|
const String txt = "Meter size could not be set!";
|
|
ErrorMessage = txt;
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
_operationCtr--;
|
|
continue;
|
|
}
|
|
|
|
_operationCtr++;
|
|
_actualOperation = "Store calibration to meter";
|
|
returnValue = _genesisMeter.WriteRegister(Register.Genesisflow.StoreCalibration, 1);
|
|
if (!returnValue)
|
|
{
|
|
const String txt = "Meter store calibration failed!";
|
|
ErrorMessage = txt;
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
_operationCtr--;
|
|
continue;
|
|
}
|
|
|
|
// read back all values
|
|
_genesisMeter.CheckRegionSizeLutCrc();
|
|
|
|
var lutFileCrc = $"0x{LutFile.FileCrc:X4}";
|
|
if (!_genesisMeter.LutCrc.Equals(lutFileCrc))
|
|
{
|
|
const String txt = "Meter LUT CRC could not be set!";
|
|
ErrorMessage = txt;
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
_operationCtr--;
|
|
returnValue = false;
|
|
continue;
|
|
}
|
|
|
|
OnProcessUpdate?.Invoke(this,
|
|
new ProcessExecEventArgs($"Read back and validated LUT CRC {_genesisMeter.LutCrc}"));
|
|
|
|
var lutMeterSize = MeterSizeConverter.ConvertMeterSizeEnumToSizeName(LutFile.MeterSize);
|
|
if (!_genesisMeter.MeterSize.Equals(lutMeterSize))
|
|
{
|
|
const String txt = "Meter size could not be set!";
|
|
ErrorMessage = txt;
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
_operationCtr--;
|
|
returnValue = false;
|
|
continue;
|
|
}
|
|
|
|
ErrorMessage = "";
|
|
OnProcessUpdate?.Invoke(this,
|
|
new ProcessExecEventArgs($"Read back and validated meter size {lutMeterSize}"));
|
|
|
|
} while (!returnValue && retryCtr++ < RegisterWriteRetries && !StopUpdateProcess);
|
|
|
|
// set timeout back to default value
|
|
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
|
|
|
|
return returnValue && !StopUpdateProcess;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read meter files of drive 1
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private Boolean ListMeterFilesDrive1()
|
|
{
|
|
// logout and re-login to clear all ongoing processes and clear the Genesis buffers
|
|
ReestablishMeterFileSystem();
|
|
|
|
if (_meterFilesDrive1 == null)
|
|
{
|
|
_meterFilesDrive1 = new List<String>();
|
|
}
|
|
_meterFilesDrive1.Clear();
|
|
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs("List meter files drive 1"));
|
|
if (!_meterFile.ReadMeterFileCatalog(out var meterFilesDrive1, MeterFile.StrMeterDrive1))
|
|
return false;
|
|
|
|
_meterFilesDrive1.AddRange(meterFilesDrive1);
|
|
|
|
// inform overlay system of found files
|
|
foreach (var meterFile in _meterFilesDrive1)
|
|
{
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(meterFile));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erase file!
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private Boolean EraseFile(String fileDriveName)
|
|
{
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($"Erasing {fileDriveName}"));
|
|
var returnValue = _meterFile.UnlockEraseWriteMeterFile(fileDriveName);
|
|
// erase returns always TRUE, even if the erasure failed! Check with catalogue
|
|
_meterFile.EraseMeterFile(fileDriveName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erase old LUT files from meter
|
|
/// </summary>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean EraseLutFiles()
|
|
{
|
|
//counters for actual process information
|
|
var retryCtr = 0;
|
|
if (LutFile == null)
|
|
return false;
|
|
|
|
//set extended timeout for trigger upgrade response delay
|
|
_genesisMeter.TransmitProtocol.SetResponseTimeout(10000);
|
|
var returnValue = true;
|
|
|
|
//erase loop and retry if not successful
|
|
do
|
|
{
|
|
var filesToErase = new[] {
|
|
//"1\\upg00", "1\\upg01", "1\\upg04","1\\upg08","1\\upg09","1\\upg12","1\\upg14","1\\upg15",
|
|
MeterLutFile.StrLutMeterFileName, MeterLutFile.StrLutBackupMeterFileName };
|
|
|
|
// read all files which are already installed
|
|
_actualOperation = "Catalogue installed meter files drive 1";
|
|
_operationCtr++;
|
|
|
|
// read files on drive 1 to verify the LUT installation
|
|
if (ListMeterFilesDrive1())
|
|
{
|
|
foreach (var fileToErase in filesToErase)
|
|
{
|
|
if (!_meterFilesDrive1.Contains(fileToErase))
|
|
continue;
|
|
|
|
_operationCtr++;
|
|
_actualOperation = $"Erase {fileToErase}";
|
|
if (EraseFile(fileToErase))
|
|
{
|
|
ErrorMessage = "";
|
|
continue;
|
|
}
|
|
|
|
ErrorMessage = $"LUT file {fileToErase} not erased!";
|
|
returnValue = false;
|
|
_operationCtr--;
|
|
}
|
|
}
|
|
|
|
if (!returnValue)
|
|
{
|
|
ReestablishMeterFileSystem();
|
|
}
|
|
} while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess);
|
|
|
|
//set timeout back to default value
|
|
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
|
|
|
|
return !StopUpdateProcess && returnValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Download the metrology lookup table files and read the catalog of drive 1
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2023-Jan-20" author="Thomas Wiedebusch">
|
|
/// - Removed list file drive 1 to speed up process. Files will be read back and binary compared!
|
|
/// </remarks>
|
|
private Boolean DownloadLutFiles()
|
|
{
|
|
//counters for actual process information
|
|
var retryCtr = 0;
|
|
if (LutFile == null)
|
|
return false;
|
|
|
|
//set extended timeout for trigger upgrade response delay
|
|
_genesisMeter.TransmitProtocol.SetResponseTimeout(1000);
|
|
var returnValue = true;
|
|
|
|
//write LUT files and retry if not successful
|
|
do
|
|
{
|
|
var filesToDownload = new[] { MeterLutFile.StrLutMeterFileName, MeterLutFile.StrLutBackupMeterFileName };
|
|
|
|
foreach (var fileToDownload in filesToDownload)
|
|
{
|
|
_operationCtr++;
|
|
_actualOperation = $"Write {fileToDownload}";
|
|
|
|
// logout and re-login to clear all ongoing processes and clear the Genesis buffers
|
|
ReestablishMeterFileSystem();
|
|
|
|
_meterFile.UnlockEraseWriteMeterFile(fileToDownload);
|
|
var txt = $"{fileToDownload} successfully written";
|
|
if (_meterFile.WriteMeterFile(fileToDownload, LutFile.BinData.ToArray()))
|
|
{
|
|
ErrorMessage = "";
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
continue;
|
|
}
|
|
|
|
txt = $"Writing of {fileToDownload} failed!";
|
|
ErrorMessage = txt;
|
|
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt));
|
|
returnValue = false;
|
|
_operationCtr--;
|
|
}
|
|
|
|
// read all files on drive 1
|
|
_operationCtr++;
|
|
|
|
if (!returnValue)
|
|
{
|
|
ReestablishMeterFileSystem();
|
|
}
|
|
} while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess);
|
|
|
|
//set timeout back to default value
|
|
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
|
|
|
|
return !StopUpdateProcess && returnValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upload the metrology lookup table files and read the catalog of drive 1
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-01" author="Thomas Wiedebusch">
|
|
/// - Take the different size of original and receive buffer, which is an integer division by 4, into account.
|
|
/// </remarks>
|
|
/// <remarks date="2022-Apr-06" author="Thomas Wiedebusch">
|
|
/// - Exported file compare to <see cref="MeterFile"/>.
|
|
/// </remarks>
|
|
private Boolean UploadAndCompareLutFiles()
|
|
{
|
|
//counters for actual process information
|
|
var retryCtr = 0;
|
|
if (LutFile == null)
|
|
return false;
|
|
|
|
//set extended timeout for trigger upgrade response delay
|
|
_genesisMeter.TransmitProtocol.SetResponseTimeout(1000);
|
|
var returnValue = true;
|
|
|
|
//verify LUT files and retry if not successful
|
|
do
|
|
{
|
|
var filesToUpload = new[] { MeterLutFile.StrLutMeterFileName, MeterLutFile.StrLutBackupMeterFileName };
|
|
|
|
foreach (var fileToUpload in filesToUpload)
|
|
{
|
|
_operationCtr++;
|
|
_actualOperation = $"Read {fileToUpload}";
|
|
|
|
// logout and re-login to clear all ongoing processes and clear the Genesis buffers
|
|
ReestablishMeterFileSystem();
|
|
|
|
if (!_meterFile.VerifyMeterFile(fileToUpload, LutFile.BinData.ToArray()))
|
|
{
|
|
ErrorMessage = $"Meter LUT file is unequal to downloaded {fileToUpload}!";
|
|
returnValue = false;
|
|
_operationCtr--;
|
|
}
|
|
else
|
|
{
|
|
OnProcessUpdate?.Invoke(this,
|
|
new ProcessExecEventArgs($"LUT file {fileToUpload} of meter successfully compared!"));
|
|
}
|
|
}
|
|
|
|
if (!returnValue)
|
|
{
|
|
ReestablishMeterFileSystem();
|
|
}
|
|
} while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess);
|
|
|
|
//set timeout back to default value
|
|
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
|
|
|
|
return !StopUpdateProcess && returnValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load file from memory
|
|
/// </summary>
|
|
/// <param name="filePathName">to binary files</param>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-15" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean LoadLutFile(String filePathName)
|
|
{
|
|
if (!File.Exists(filePathName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
LutFile = null;
|
|
LutFile = new MeterLutFile(filePathName)
|
|
{
|
|
BinData = new List<Byte>(File.ReadAllBytes(filePathName))
|
|
};
|
|
|
|
// validate the file
|
|
return ValidateLutFile();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load file from memory
|
|
/// </summary>
|
|
/// <param name="name">origin Name</param>
|
|
/// <param name="streamData">list of bytes of the file strean</param>
|
|
/// <returns></returns>
|
|
/// <remarks date="2022-Feb-15" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean LoadLutFromStream(String name, List<Byte> streamData )
|
|
{
|
|
LutFile = null;
|
|
LutFile = new MeterLutFile(name)
|
|
{
|
|
BinData = streamData
|
|
};
|
|
|
|
// validate the file
|
|
return ValidateLutFile();
|
|
}
|
|
#endregion
|
|
}
|
|
} |