521 lines
27 KiB
C#
521 lines
27 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Properties;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
|
|
using Xylem.Common.Utils.Crc16Ccitt;
|
|
|
|
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|
{
|
|
/// <summary>
|
|
/// Power correction file stored as reminder and log to meter
|
|
/// </summary>
|
|
public class MeterPowerCorrectionFile
|
|
{
|
|
/// <summary>
|
|
/// Drive and name for power correction file stored on meter
|
|
/// </summary>
|
|
public const String StrMeterPowCorrFileName = "1\\powcorr";
|
|
|
|
|
|
private readonly IGenesisMeter _currentGenesis;
|
|
private readonly MeterFile _meterFile;
|
|
|
|
// position of data in binary data of meter powcorr file
|
|
// file information
|
|
private const Int32 FileLengthIdx = 0;
|
|
private const Int32 FileLengthSize = sizeof(UInt16);
|
|
|
|
private const Int32 FileCrcIdx = FileLengthIdx + FileLengthSize;
|
|
private const Int32 FileCrcSize = sizeof(UInt16);
|
|
|
|
private const Int32 FileDataIdx = FileCrcIdx + FileCrcSize;
|
|
private const Int32 FileHeaderSize = FileLengthSize + FileCrcSize;
|
|
|
|
// common data size
|
|
private const Int32 ChargeSize = sizeof(UInt64);
|
|
private const Int32 TimeSize = sizeof(UInt32);
|
|
private const Int32 FwVersionSize = sizeof(UInt32);
|
|
private const Int32 RadioStateSize = sizeof(Byte);
|
|
private const Int32 PulseAdaptInstalledSize = sizeof(Boolean);
|
|
private const Int32 PulseModeSize = sizeof(Byte);
|
|
private const Int32 PulseSequenceCtrSize = sizeof(Byte);
|
|
private const Int32 PulseEvenDistributionSize = sizeof(Boolean);
|
|
|
|
// production data
|
|
private const Int32 ProdDateTimeIdx = FileDataIdx;
|
|
private const Int32 ProdTimeIdx = ProdDateTimeIdx + TimeSize;
|
|
private const Int32 ProdChargeIdx = ProdTimeIdx + TimeSize;
|
|
private const Int32 ProdRadioStateIdx = ProdChargeIdx + ChargeSize;
|
|
private const Int32 ProdPulseAdaptInstalledIdx = ProdRadioStateIdx + RadioStateSize;
|
|
private const Int32 ProdPulseModeIdx = ProdPulseAdaptInstalledIdx + PulseAdaptInstalledSize;
|
|
private const Int32 ProdPulseSequenceCtrIdx = ProdPulseModeIdx + PulseModeSize;
|
|
private const Int32 ProdPulseEvenDistributionIdx = ProdPulseSequenceCtrIdx + PulseSequenceCtrSize;
|
|
|
|
private const Int32 InitialBatteryLoadIdx = ProdPulseEvenDistributionIdx + PulseEvenDistributionSize;
|
|
private const Int32 InitialBatteryLoadSize = sizeof (UInt16);
|
|
private const Int32 BatteryQuantityIdx = InitialBatteryLoadIdx + InitialBatteryLoadSize;
|
|
private const Int32 BatteryQuantitySize = sizeof(Byte);
|
|
|
|
// field data
|
|
private const Int32 FieldFwVersionIdx = BatteryQuantityIdx + BatteryQuantitySize;
|
|
|
|
private const Int32 FieldDateTimeIdx = FieldFwVersionIdx + FwVersionSize;
|
|
private const Int32 FieldTimeIdx = FieldDateTimeIdx + TimeSize;
|
|
private const Int32 FieldChargeIdx = FieldTimeIdx + TimeSize;
|
|
private const Int32 FieldRadioStateIdx = FieldChargeIdx + ChargeSize;
|
|
private const Int32 FieldPulseAdaptInstalledIdx = FieldRadioStateIdx + RadioStateSize;
|
|
private const Int32 FieldPulseModeIdx = FieldPulseAdaptInstalledIdx + PulseAdaptInstalledSize;
|
|
private const Int32 FieldPulseSequenceCtrIdx = FieldPulseModeIdx + PulseModeSize;
|
|
private const Int32 FieldPulseEvenDistributionIdx = FieldPulseSequenceCtrIdx + PulseSequenceCtrSize;
|
|
|
|
// calculated
|
|
private const Int32 RequiredFwVersionIdx = FieldPulseEvenDistributionIdx + PulseEvenDistributionSize;
|
|
private const Int32 CalcPulseReportLengthIdx = RequiredFwVersionIdx + FwVersionSize;
|
|
private const Int32 CalcPulseReportLengthSize = sizeof(UInt32);
|
|
|
|
private const Int32 CalcPostProdTimeIdx = CalcPulseReportLengthIdx + CalcPulseReportLengthSize;
|
|
private const Int32 CalcOverestimatedChargeIdx = CalcPostProdTimeIdx + TimeSize;
|
|
private const Int32 CalcFixedEstimatedChargeIdx = CalcOverestimatedChargeIdx + ChargeSize;
|
|
private const Int32 CalcMinimumChargeIdx = CalcFixedEstimatedChargeIdx + ChargeSize;
|
|
private const Int32 CalcCorrectedChargeIdx = CalcMinimumChargeIdx + ChargeSize;
|
|
|
|
// estimate file size
|
|
private const Int32 FileSize = CalcCorrectedChargeIdx + ChargeSize;
|
|
|
|
// raw data
|
|
private Byte[] _meterBinData = new Byte[FileSize];
|
|
|
|
/// <summary>
|
|
/// Content of power correction meter file
|
|
/// </summary>
|
|
public readonly List<String> FileContent = new List<String>();
|
|
|
|
/// <summary>
|
|
/// Ctor
|
|
/// </summary>
|
|
/// <param name="currentGenesis"></param>
|
|
/// <remarks date="2024-May-08" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
public MeterPowerCorrectionFile(IGenesisMeter currentGenesis)
|
|
{
|
|
_currentGenesis = currentGenesis;
|
|
_meterFile = new MeterFile(_currentGenesis);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read power correction meter file.
|
|
/// </summary>
|
|
/// <returns>true: file found</returns>
|
|
/// <remarks date="2024-May-08" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
public Boolean ReadPowCorrMeterFile()
|
|
{
|
|
if (_currentGenesis == null || _meterFile == null)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
var loginReminder = _currentGenesis.IsLoggedOn;
|
|
var retVal = _currentGenesis.ReLogin();
|
|
if (retVal)
|
|
{
|
|
FileContent.Clear();
|
|
retVal = _meterFile.ReadMeterFile(StrMeterPowCorrFileName, out var meterBinDataList);
|
|
_meterBinData = meterBinDataList.ToArray();
|
|
// Build a string list of recorded data
|
|
if (retVal)
|
|
{
|
|
retVal = BuildStringListOfPowCorrFileContent();
|
|
}
|
|
}
|
|
|
|
if (!loginReminder)
|
|
_currentGenesis.Logout();
|
|
return retVal;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_currentGenesis.WriteLog(e.Message);
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Build a string list of logged power correction file content.
|
|
/// </summary>
|
|
/// <returns>true: file found</returns>
|
|
/// <remarks date="2024-May-15" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <remarks date="2025-Aug-12" author="Thomas Wiedebusch">
|
|
/// - Formatting changed.
|
|
/// </remarks>
|
|
private Boolean BuildStringListOfPowCorrFileContent()
|
|
{
|
|
if (_meterBinData == null || _meterBinData.Length == 0 || _currentGenesis == null)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
var fc = FileContent;
|
|
var bin = _meterBinData;
|
|
Byte[] value_u8a;
|
|
var ltlStatus = new GenesisStatus.GenesisStatus();
|
|
fc.Clear();
|
|
fc.Add(Resources.StrPowCorrFileInfo);
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[TimeSize], bin, TimeSize, 0, ProdDateTimeIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrDateTime}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(TimeT))}");
|
|
if (CopyByteArray(value_u8a = new Byte[TimeSize], bin, TimeSize, 0, ProdTimeIdx))
|
|
{
|
|
ltlStatus.ExceededLifeTime_s = RegisterConverter.ByteArrayToValue<UInt32>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrTime_s}" +
|
|
$": {ltlStatus.ExceededLifeTime_s:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[ChargeSize], bin, ChargeSize, 0, ProdChargeIdx))
|
|
{
|
|
ltlStatus.DrainedBatteryLoad_uAs = RegisterConverter.ByteArrayToValue<UInt64>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrCharge_uAs}" +
|
|
$": {ltlStatus.DrainedBatteryLoad_uAs:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[InitialBatteryLoadSize], bin, InitialBatteryLoadSize,
|
|
0, InitialBatteryLoadIdx))
|
|
{
|
|
ltlStatus.InitialBatteryLoad_mAh = RegisterConverter.ByteArrayToValue<UInt16>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrInitialBatteryLoad_mAh}" +
|
|
$": {ltlStatus.InitialBatteryLoad_mAh:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[BatteryQuantitySize], bin, BatteryQuantitySize,
|
|
0, BatteryQuantityIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrBatteryQuantity}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
ltlStatus.BatteryQuantity = RegisterConverter.ByteArrayToValue<Byte>(value_u8a);
|
|
|
|
if (GenesisStatusHandler.CalculateLifeTime(ltlStatus))
|
|
{
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrDrainedLoad_percent}" +
|
|
$": {ltlStatus.DrainedBatteryLoadPercent:F2}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[TimeSize], bin, TimeSize, 0, FieldDateTimeIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrDateTime}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(TimeT))}");
|
|
if (CopyByteArray(value_u8a = new Byte[TimeSize], bin, TimeSize, 0, FieldTimeIdx))
|
|
{
|
|
ltlStatus.ExceededLifeTime_s = RegisterConverter.ByteArrayToValue<UInt32>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrTime_s}" +
|
|
$": {ltlStatus.ExceededLifeTime_s:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[ChargeSize], bin, ChargeSize, 0, FieldChargeIdx))
|
|
{
|
|
ltlStatus.DrainedBatteryLoad_uAs = RegisterConverter.ByteArrayToValue<UInt64>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrCharge_uAs}" +
|
|
$": {ltlStatus.DrainedBatteryLoad_uAs:N0}");
|
|
}
|
|
|
|
if (GenesisStatusHandler.CalculateLifeTime(ltlStatus))
|
|
{
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrDrainedLoad_percent}" +
|
|
$": {ltlStatus.DrainedBatteryLoadPercent:F2}");
|
|
}
|
|
if (CopyByteArray(value_u8a = new Byte[RadioStateSize], bin, RadioStateSize, 0, ProdRadioStateIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrRadioSystemState}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
if (CopyByteArray(value_u8a = new Byte[RadioStateSize], bin, RadioStateSize, 0, FieldRadioStateIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrRadioSystemState}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[PulseAdaptInstalledSize], bin, PulseAdaptInstalledSize, 0,
|
|
ProdPulseAdaptInstalledIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrPulseAdapterInstallationState}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Boolean))}");
|
|
if (CopyByteArray(value_u8a = new Byte[PulseAdaptInstalledSize], bin, PulseAdaptInstalledSize, 0,
|
|
FieldPulseAdaptInstalledIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrPulseAdapterAutoDetected}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Boolean))}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[PulseModeSize], bin, PulseModeSize, 0, ProdPulseModeIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrPulseMode}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
if (CopyByteArray(value_u8a = new Byte[PulseModeSize], bin, PulseModeSize, 0, FieldPulseModeIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrPulseMode}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[PulseSequenceCtrSize], bin, PulseSequenceCtrSize, 0,
|
|
ProdPulseSequenceCtrIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrPulseSequenceCounter}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
if (CopyByteArray(value_u8a = new Byte[PulseSequenceCtrSize], bin, PulseSequenceCtrSize, 0,
|
|
FieldPulseSequenceCtrIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrPulseSequenceCounter}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Byte))}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[PulseEvenDistributionSize], bin, PulseEvenDistributionSize, 0,
|
|
ProdPulseEvenDistributionIdx))
|
|
fc.Add($"{Resources.StrPowCorrFactoryValues} - {Resources.StrPowCorrPulseEvenDistribution}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Boolean))}");
|
|
if (CopyByteArray(value_u8a = new Byte[PulseEvenDistributionSize], bin, PulseEvenDistributionSize, 0,
|
|
FieldPulseEvenDistributionIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrPulseEvenDistribution}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(Boolean))}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[FwVersionSize], bin, FwVersionSize, 0, FieldFwVersionIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrOldFwVersion}" +
|
|
$": {GenesisMeter.BuildFlexnetFwVersion(out _, null, value_u8a[1], value_u8a[0])}");
|
|
if (CopyByteArray(value_u8a = new Byte[FwVersionSize], bin, FwVersionSize, 0, RequiredFwVersionIdx))
|
|
fc.Add($"{Resources.StrPowCorrActualValues} - {Resources.StrPowCorrNewFwVersion}" +
|
|
$": {GenesisMeter.BuildFlexnetFwVersion(out _, null, value_u8a[1], value_u8a[0])}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[CalcPulseReportLengthSize], bin, CalcPulseReportLengthSize,
|
|
0, CalcPulseReportLengthIdx))
|
|
fc.Add($"{Resources.StrPowCorrPulseReportLength}" +
|
|
$": {RegisterConverter.ConvertToText(value_u8a, typeof(UInt32))}");
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[TimeSize], bin, TimeSize, 0, CalcPostProdTimeIdx))
|
|
{
|
|
var temp = RegisterConverter.ByteArrayToValue<UInt32>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrPostProdTime_s}" +
|
|
$": {temp:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[ChargeSize], bin, ChargeSize, 0, CalcOverestimatedChargeIdx))
|
|
{
|
|
var temp = RegisterConverter.ByteArrayToValue<UInt64>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrOverestimate_uAs}" +
|
|
$": {temp:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[ChargeSize], bin, ChargeSize, 0, CalcFixedEstimatedChargeIdx))
|
|
{
|
|
var temp = RegisterConverter.ByteArrayToValue<UInt64>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrFixedEstimateCharge_uAs}" +
|
|
$": {temp:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[ChargeSize], bin, ChargeSize, 0, CalcMinimumChargeIdx))
|
|
{
|
|
var temp = RegisterConverter.ByteArrayToValue<UInt64>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrOverestimateLimit_uAs}" +
|
|
$": {temp:N0}");
|
|
}
|
|
|
|
if (CopyByteArray(value_u8a = new Byte[ChargeSize], bin, ChargeSize, 0, CalcCorrectedChargeIdx))
|
|
{
|
|
ltlStatus.DrainedBatteryLoad_uAs = RegisterConverter.ByteArrayToValue<UInt64>(value_u8a);
|
|
fc.Add($"{Resources.StrPowCorrCorrectedCharge_uAs}" +
|
|
$": {ltlStatus.DrainedBatteryLoad_uAs:N0}");
|
|
}
|
|
|
|
if (GenesisStatusHandler.CalculateLifeTime(ltlStatus))
|
|
{
|
|
fc.Add($"{Resources.StrPowCorrCalculation} - {Resources.StrPowCorrDrainedLoad_percent}" +
|
|
$": {ltlStatus.DrainedBatteryLoadPercent:F2}");
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_currentGenesis.WriteLog(e.Message);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy byte arrays
|
|
/// </summary>
|
|
/// <param name="destination">destination array to copy to</param>
|
|
/// <param name="source">array to copy from</param>
|
|
/// <param name="size"></param>
|
|
/// <param name="destinationStartIndex"></param>
|
|
/// <param name="sourceStartIndex"></param>
|
|
/// <returns>true: success</returns>
|
|
/// <remarks date="2024-May-13" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
private Boolean CopyByteArray(Byte[] destination, Byte[] source, Int32 size, Int32 destinationStartIndex = 0,
|
|
Int32 sourceStartIndex = 0)
|
|
{
|
|
if (_currentGenesis == null)
|
|
return false;
|
|
|
|
// avoid OOR copy
|
|
if (destination.Length < size + destinationStartIndex || source.Length < size + sourceStartIndex)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
for (var c = 0; c < size; c++)
|
|
{
|
|
destination[destinationStartIndex + c] = source[sourceStartIndex + c];
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_currentGenesis.WriteLog(e.Message);
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Build the binary data as preparation before sending those to the meter file.
|
|
///
|
|
/// PRECONDITION: PowerCorrectionData has to be filled in advance!
|
|
/// </summary>
|
|
/// <returns>true: success</returns>
|
|
/// <remarks date="2024-May-13..15" author="Thomas Wiedebusch">
|
|
/// - Initial
|
|
/// </remarks>
|
|
/// <param name="powerCorrectionData">power correction</param>
|
|
/// <returns>if successfully copied</returns>
|
|
private Boolean BuildBinData(PowerCorrection powerCorrectionData)
|
|
{
|
|
if (powerCorrectionData == null || _currentGenesis == null)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
if (_meterBinData == null)
|
|
_meterBinData = new Byte[FileSize];
|
|
|
|
var pc = powerCorrectionData;
|
|
|
|
// production
|
|
var timeT = new TimeT();
|
|
var dateTimeUtc = pc.ProductionDateTimeUtc ?? timeT.DateTimeUtc;
|
|
var secSince2000 = timeT.UtcAnyToSecondsSince2000(dateTimeUtc);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(secSince2000),
|
|
TimeSize, ProdDateTimeIdx);
|
|
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionTotalUsedSeconds_s),
|
|
TimeSize, ProdTimeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionTotalUsedCharge_uAs),
|
|
ChargeSize, ProdChargeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionRadioSystemState),
|
|
RadioStateSize, ProdRadioStateIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionPulseAdapterIsInstalled),
|
|
PulseAdaptInstalledSize, ProdPulseAdaptInstalledIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionPulseMode),
|
|
PulseModeSize, ProdPulseModeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionPulseSequenceCounter),
|
|
PulseSequenceCtrSize, ProdPulseSequenceCtrIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ProductionPulseEvenDistribution),
|
|
PulseEvenDistributionSize, ProdPulseEvenDistributionIdx);
|
|
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.InitialBatteryLoad_mAh),
|
|
InitialBatteryLoadSize, InitialBatteryLoadIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.BatteryQuantity),
|
|
BatteryQuantitySize, BatteryQuantityIdx);
|
|
|
|
// field
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualFwVersion),
|
|
FwVersionSize, FieldFwVersionIdx);
|
|
|
|
// reset timeT to 2000
|
|
timeT.SecondsSince2000 = 0;
|
|
dateTimeUtc = pc.ActualDateTimeUtc ?? timeT.DateTimeUtc;
|
|
secSince2000 = timeT.UtcAnyToSecondsSince2000(dateTimeUtc);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(secSince2000),
|
|
TimeSize, FieldDateTimeIdx);
|
|
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualTotalUsedSeconds_s),
|
|
TimeSize, FieldTimeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualTotalUsedCharge_uAs),
|
|
ChargeSize, FieldChargeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualRadioSystemState),
|
|
RadioStateSize, FieldRadioStateIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualPulseAdapterIsInstalled),
|
|
PulseAdaptInstalledSize, FieldPulseAdaptInstalledIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualPulseMode),
|
|
PulseModeSize, FieldPulseModeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualPulseSequenceCounter),
|
|
PulseSequenceCtrSize, FieldPulseSequenceCtrIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.ActualPulseEvenDistribution),
|
|
PulseEvenDistributionSize, FieldPulseEvenDistributionIdx);
|
|
|
|
// calculations
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.RequiredFwVersion),
|
|
FwVersionSize, RequiredFwVersionIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.PulseReportLength),
|
|
CalcPulseReportLengthSize, CalcPulseReportLengthIdx);
|
|
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.PostProductionTotalUsedSeconds_s),
|
|
TimeSize, CalcPostProdTimeIdx);
|
|
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.OverestimatedTotalUsedCharge_uAs),
|
|
ChargeSize, CalcOverestimatedChargeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.FixedEstimateTotalUsedCharge_uAs),
|
|
ChargeSize, CalcFixedEstimatedChargeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.MinimumTotalUsedCharge_uAs),
|
|
ChargeSize, CalcMinimumChargeIdx);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(pc.CorrectedTotalUsedCharge_uAs),
|
|
ChargeSize, CalcCorrectedChargeIdx);
|
|
|
|
// add file information
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(FileSize), FileLengthSize);
|
|
var crc = Crc16Ccitt.CalculateReversedLsb8408(_meterBinData);
|
|
CopyByteArray(_meterBinData, RegisterConverter.ValueToByteArray(crc), FileCrcSize, FileCrcIdx);
|
|
return true;
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_currentGenesis.WriteLog(e.Message);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Write the meter power correction file.
|
|
/// </summary>
|
|
/// <returns>true successfully written </returns>
|
|
/// <remarks date="2024-May-08..15" author="Thomas Wiedebusch">
|
|
/// - Initial.
|
|
/// </remarks>
|
|
/// <param name="powerCorrectionData"></param>
|
|
/// <returns>true if successfully written</returns>
|
|
public Boolean WritePowCorrMeterFile(PowerCorrection powerCorrectionData)
|
|
{
|
|
if (_currentGenesis == null || _meterFile == null || powerCorrectionData == null)
|
|
return false;
|
|
|
|
try
|
|
{
|
|
|
|
if (!BuildBinData(powerCorrectionData))
|
|
return false;
|
|
BuildStringListOfPowCorrFileContent();
|
|
|
|
var loginReminder = _currentGenesis.IsLoggedOn;
|
|
var retVal = _currentGenesis.ReLogin();
|
|
if (retVal)
|
|
{
|
|
_meterFile.UnlockEraseWriteMeterFile(StrMeterPowCorrFileName);
|
|
retVal = _meterFile.WriteMeterFile(StrMeterPowCorrFileName, _meterBinData.ToArray());
|
|
}
|
|
|
|
if (!loginReminder)
|
|
_currentGenesis.Logout();
|
|
return retVal;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_currentGenesis.WriteLog(e.Message);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|