merege main to dev
This commit is contained in:
@@ -14,5 +14,5 @@ using System.Reflection;
|
||||
//[assembly: AssemblyVersion("1.2.*.0")]
|
||||
|
||||
|
||||
[assembly: AssemblyVersion("2.6.7.*")]
|
||||
[assembly: AssemblyFileVersion("2.6.7.0")]
|
||||
[assembly: AssemblyVersion("2.6.8.*")]
|
||||
[assembly: AssemblyFileVersion("2.6.8.0")]
|
||||
@@ -4,12 +4,21 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<<<<<<<< HEAD:Common/CommonCore/Common.Abstraction/Common.Abstraction.csproj
|
||||
<ProjectGuid>{1743B349-E347-4DCF-A106-15AE3F95C3A3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Common.Abstraction</RootNamespace>
|
||||
<AssemblyName>Common.Abstraction</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
========
|
||||
<ProjectGuid>{197185D3-53B7-41A1-A099-CE9F85D5C8F9}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LaaProduction.Http</RootNamespace>
|
||||
<AssemblyName>LaaProduction.Http</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
>>>>>>>> main:LaaProductionWeb/LaaProduction.Http/LaaProduction.Http.csproj
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
@@ -31,6 +40,9 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -41,10 +53,25 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<<<<<<<< HEAD:Common/CommonCore/Common.Abstraction/Common.Abstraction.csproj
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Interfaces\" />
|
||||
========
|
||||
<Compile Include="HttpClient.cs" />
|
||||
<Compile Include="HttpMessage.cs" />
|
||||
<Compile Include="HttpResponse[T].cs" />
|
||||
<Compile Include="Interfaces\IHttpClient.cs" />
|
||||
<Compile Include="Interfaces\IHttpErrorResponse.cs" />
|
||||
<Compile Include="Interfaces\IHttpMessage.cs" />
|
||||
<Compile Include="Interfaces\IHttpResponse[T].cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="README.md" />
|
||||
>>>>>>>> main:LaaProductionWeb/LaaProduction.Http/LaaProduction.Http.csproj
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -5,12 +5,21 @@ using System.Runtime.InteropServices;
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
<<<<<<<< HEAD:Common/CommonCore/Common.Abstraction/Properties/AssemblyInfo.cs
|
||||
[assembly: AssemblyTitle("Common.Abstraction")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Common.Abstraction")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
========
|
||||
[assembly: AssemblyTitle("LaaProduction.Http")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("LaaProduction.Http")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2024")]
|
||||
>>>>>>>> main:LaaProductionWeb/LaaProduction.Http/Properties/AssemblyInfo.cs
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -20,7 +29,11 @@ using System.Runtime.InteropServices;
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
<<<<<<<< HEAD:Common/CommonCore/Common.Abstraction/Properties/AssemblyInfo.cs
|
||||
[assembly: Guid("1743b349-e347-4dcf-a106-15ae3f95c3a3")]
|
||||
========
|
||||
[assembly: Guid("197185d3-53b7-41a1-a099-ce9f85d5c8f9")]
|
||||
>>>>>>>> main:LaaProductionWeb/LaaProduction.Http/Properties/AssemblyInfo.cs
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
using Xylem.Common.CommonCore.Configuration;
|
||||
using Xylem.Common.CommonCore.Consts;
|
||||
@@ -28,45 +29,43 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <summary>
|
||||
/// PCB ID for pre update read for comparison
|
||||
/// </summary>
|
||||
private String _pcbIdInitialRegisterRead = "X";
|
||||
private String _pcbIdInitialRegisterRead = Constants.StrUnknown;
|
||||
|
||||
/// <summary>
|
||||
/// PCB ID for pre update write for comparison
|
||||
/// </summary>
|
||||
private String _pcbIdRecoveryRegisters = "X";
|
||||
private String _pcbIdRecoveryRegisters = Constants.StrUnknown;
|
||||
|
||||
/// <summary>
|
||||
/// PCB ID for post update for comparison
|
||||
/// </summary>
|
||||
private String _pcbIdFinalRegisterRead = Constants.StrUnknown;
|
||||
|
||||
/// <summary>
|
||||
/// Collection of recovery registers and values
|
||||
/// </summary>
|
||||
public List<RecoveryRegisterItem> RegistersSetup;
|
||||
|
||||
/// <summary>
|
||||
/// Register content on initial connect to keep those during update
|
||||
/// </summary>
|
||||
private readonly MeterRegisters _initialReadRegisters = new MeterRegisters();
|
||||
private MeterRegisters _initialReadRegisters = new MeterRegisters();
|
||||
|
||||
/// <summary>
|
||||
/// Register content after all operation had been performed
|
||||
/// </summary>
|
||||
private readonly MeterRegisters _finalReadRegisters = new MeterRegisters();
|
||||
private MeterRegisters _finalReadRegisters = new MeterRegisters();
|
||||
|
||||
/// <summary>
|
||||
/// Register which shall be restored after change of FW or after register recovery
|
||||
/// </summary>
|
||||
private readonly MeterRegisters _restoreRegisters = new MeterRegisters();
|
||||
private readonly MeterRegisters _recoveryRegisters = new MeterRegisters();
|
||||
|
||||
/// <summary>
|
||||
/// Register access event for message dispatcher to caller
|
||||
/// </summary>
|
||||
public event EventHandler<ProcessExecEventArgs> OnProcessUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// List for parameters which need to be removed from parameter list as they mustn't be accessed
|
||||
/// </summary>
|
||||
private static readonly List<String> _prohibitedParameters = new List<String>
|
||||
{
|
||||
"CUSTOMER_AppArrangement"
|
||||
};
|
||||
/// <summary>
|
||||
/// List for un-reversed parameters, all others need to be swapped byte-wise
|
||||
/// </summary>
|
||||
@@ -81,51 +80,70 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// </summary>
|
||||
private static readonly List<String> _excludedFromCompareParameters = new List<String>
|
||||
{
|
||||
"SENSUSRADIO_UpgFWVersion" // After a FW-Update the FW version has changed and the compare will fail
|
||||
"SENSUSRADIO_UpgFWVersion" // After a FW-Update the FW version has changed and the compare will fail
|
||||
};
|
||||
/// <summary>
|
||||
/// Pre programming parameters for all devices defined here, will be filled with radio parameters
|
||||
/// if meter has radio
|
||||
/// </summary>
|
||||
private static readonly List<ProgrammingParameters> _prepareProgramming = new List<ProgrammingParameters>
|
||||
private static readonly List<RecoveryRegisterItem> _prepareProgramming = new List<RecoveryRegisterItem>
|
||||
{
|
||||
// The display needs to be unsealed for change of unit and resolution
|
||||
new ProgrammingParameters("GENESISFLOW_SealDisplay", new Byte[] { 0x00 })
|
||||
new RecoveryRegisterItem("GENESISFLOW_SealDisplay", new Byte[] { 0x00 })
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// ReSharper disable once CollectionNeverQueried.Local IS FOR DEBUG
|
||||
private readonly List<RecoveryRegisterItem> _failedComparisonRegisters = new List<RecoveryRegisterItem>();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// ReSharper disable once CollectionNeverQueried.Local IS FOR DEBUG
|
||||
private List<String> _dbParameterRegisterList = new List<String>();
|
||||
private readonly List<String> _recoveryRegisterList = new List<String>();
|
||||
private List<String> _initialRegisterList = new List<String>();
|
||||
private List<String> _finalRegisterList = new List<String>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Post programming parameters for radio only
|
||||
/// </summary>
|
||||
private static readonly List<ProgrammingParameters> _finalizeProgrammingRadioOnly = new List<ProgrammingParameters>
|
||||
private static readonly List<RecoveryRegisterItem> _finalizeProgrammingRadioOnly = new List<RecoveryRegisterItem>
|
||||
{
|
||||
new ProgrammingParameters("LOGGER_TriggerLogFlush", new Byte[] { 0x01 }),
|
||||
new ProgrammingParameters("PERIODICLOG_ResetCounter", new Byte[] { 0x00 }),
|
||||
new RecoveryRegisterItem("LOGGER_TriggerLogFlush", new Byte[] { 0x01 }),
|
||||
// set counter to 0 as this is a value how often the radio detected a reset
|
||||
new RecoveryRegisterItem("PERIODICLOG_ResetCounter", new Byte[] { 0x00 }),
|
||||
// System state 0xFF will force a storage of all parameters and reset, followed by system state 0x02
|
||||
// for customer mode, the reset needs only a few milliseconds
|
||||
// Attention logout-delay-login required after this step!
|
||||
new ProgrammingParameters("SENSUSRADIO_SystemState", new Byte[] { 0xFF })
|
||||
new RecoveryRegisterItem("SENSUSRADIO_SystemState", new Byte[] { 0xFF })
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Post programming parameters for all devices
|
||||
/// </summary>
|
||||
private static readonly List<ProgrammingParameters> _finalizeProgramming = new List<ProgrammingParameters>
|
||||
private static readonly List<RecoveryRegisterItem> _finalizeProgramming = new List<RecoveryRegisterItem>
|
||||
{
|
||||
new ProgrammingParameters("GENESISFLOW_SealDisplay", new Byte[] { 0x01 }),
|
||||
new ProgrammingParameters("GENESISFLOW_TriggerIdle", new Byte[] { 0x00 }),
|
||||
new RecoveryRegisterItem("GENESISFLOW_SealDisplay", new Byte[] { 0x01 }),
|
||||
// trigger idle 0 releases the display to normal operation
|
||||
new RecoveryRegisterItem("GENESISFLOW_TriggerIdle", new Byte[] { 0x00 }),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Post programming parameters for EOL (end of line, prepare for shipping workplace)
|
||||
/// </summary>
|
||||
private static readonly List<ProgrammingParameters> _finalizeProgrammingEol = new List<ProgrammingParameters>
|
||||
private static readonly List<RecoveryRegisterItem> _finalizeProgrammingEol = new List<RecoveryRegisterItem>
|
||||
{
|
||||
new ProgrammingParameters("GENESISFLOW_ResetAccumulators", new Byte[] { 0x01 }),
|
||||
new ProgrammingParameters("NFC_EraseRMA", new Byte[] { 0x01 })
|
||||
new RecoveryRegisterItem("GENESISFLOW_ResetAccumulators", new Byte[] { 0x01 }),
|
||||
new RecoveryRegisterItem("NFC_EraseRMA", new Byte[] { 0x01 }),
|
||||
new RecoveryRegisterItem("CUSTOMER_RebootCount", new Byte[] {0x00})
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Actual Port Counter
|
||||
/// Actual register counter
|
||||
/// </summary>
|
||||
public Int32 ActualRegisterCtr;
|
||||
|
||||
@@ -179,9 +197,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2024-01-17" author="Thomas Wiedebusch">
|
||||
/// - Data base access imported to have a common interface for programming parameters for EOL (shipping) and CUST.
|
||||
/// </remarks>
|
||||
public static Boolean DownloadProgrammingParametersFromDb(String pcbId, out List<RecoveryRegisterItem> recoveryRegisters)
|
||||
/// <remarks date="2024-01-29" author="Thomas Wiedebusch">
|
||||
/// - Removed prohibited parameters.
|
||||
/// </remarks>
|
||||
public static Boolean DownloadProgrammingParametersFromDb(String pcbId, List<RecoveryRegisterItem> recoveryRegisters)
|
||||
{
|
||||
recoveryRegisters = new List<RecoveryRegisterItem>();
|
||||
try
|
||||
{
|
||||
var url = $"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetProgrammingParameters?PcbID={pcbId}";
|
||||
@@ -207,27 +227,43 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
// reverse byte order for all parameters except those listed below
|
||||
if (!string.IsNullOrEmpty(proPar.RegisterName))
|
||||
{
|
||||
// ATTENTION: These parameters are coming out of the DB and need to be removed from list
|
||||
if (RegisterRestorer._prohibitedParameters.Contains(proPar.RegisterName))
|
||||
{
|
||||
}
|
||||
// ATTENTION: These parameters are coming out of the DB in wrong order
|
||||
if (RegisterRestorer._unRevertedParameters.Contains(proPar.RegisterName))
|
||||
if (_unRevertedParameters.Contains(proPar.RegisterName))
|
||||
{
|
||||
// skip VAKO if equally register is set in CSD or on read only access
|
||||
if (proPar.Source == ProgrammingSource.Vako && sortableProgrammingParameters.Any(a =>
|
||||
a.Source == ProgrammingSource.Csd && proPar.RegisterName.Equals(a.RegisterName)))
|
||||
// Add parameter if it is not in the list
|
||||
if (sortableProgrammingParameters.All(a => !proPar.RegisterName.Equals(a.RegisterName)))
|
||||
{
|
||||
sortableProgrammingParameters.Add(proPar);
|
||||
continue;
|
||||
sortableProgrammingParameters.Add(proPar);
|
||||
}
|
||||
// if parameter from VAKO is in the list and the new is from CSD, replace this with CSD
|
||||
if (proPar.Source == ProgrammingSource.Csd && sortableProgrammingParameters.Any(a =>
|
||||
proPar.RegisterName.Equals(a.RegisterName) && a.Source == ProgrammingSource.Vako))
|
||||
{
|
||||
var removeProPar =
|
||||
sortableProgrammingParameters.Where(a => proPar.RegisterName.Equals(a.RegisterName));
|
||||
sortableProgrammingParameters.Remove(removeProPar.LastOrDefault());
|
||||
sortableProgrammingParameters.Add(proPar);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip VAKO if equally register is set in CSD or on read only access
|
||||
if (proPar.Source == ProgrammingSource.Vako && sortableProgrammingParameters.Any(a =>
|
||||
a.Source == ProgrammingSource.Csd && proPar.RegisterName.Equals(a.RegisterName)))
|
||||
// Add parameter if it is not in the list
|
||||
if (sortableProgrammingParameters.All(a => !proPar.RegisterName.Equals(a.RegisterName)))
|
||||
{
|
||||
sortableProgrammingParameters.Add(new ProgrammingParameters(proPar.RegisterName,
|
||||
proPar.RegisterValue.Reverse().ToArray(), proPar.Source));
|
||||
continue;
|
||||
sortableProgrammingParameters.Add(new ProgrammingParameters(proPar.RegisterName,
|
||||
proPar.RegisterValue.Reverse().ToArray(), proPar.Source));
|
||||
}
|
||||
// if parameter from VAKO is in the list and the new is from CSD, replace this with CSD
|
||||
if (proPar.Source == ProgrammingSource.Csd && sortableProgrammingParameters.Any(a =>
|
||||
proPar.RegisterName.Equals(a.RegisterName) && a.Source == ProgrammingSource.Vako))
|
||||
{
|
||||
var removeProPar = sortableProgrammingParameters.Where(a => proPar.RegisterName.Equals(a.RegisterName));
|
||||
sortableProgrammingParameters.Remove(removeProPar.LastOrDefault());
|
||||
sortableProgrammingParameters.Add(new ProgrammingParameters(proPar.RegisterName,
|
||||
proPar.RegisterValue.Reverse().ToArray(), proPar.Source));
|
||||
}
|
||||
}
|
||||
} // register for this FW is defined
|
||||
else
|
||||
@@ -245,11 +281,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
{
|
||||
foreach (var proPar in sortableProgrammingParameters)
|
||||
{
|
||||
var recReg = new RecoveryRegisterItem
|
||||
{
|
||||
RegisterIdent = proPar.RegisterName,
|
||||
WriteValue = proPar.RegisterValue
|
||||
};
|
||||
var recReg = new RecoveryRegisterItem(proPar.RegisterName, proPar.RegisterValue);
|
||||
recoveryRegisters.Add(recReg);
|
||||
}
|
||||
}
|
||||
@@ -309,7 +341,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// </remarks>
|
||||
public Boolean EolProgrammingRegisters(List<RecoveryRegisterItem> recoveryRegistersDb)
|
||||
{
|
||||
// mark EOL as true to force Accu reset
|
||||
// mark EOL as true to force accu reset
|
||||
return RecoverRegisters(recoveryRegistersDb, true);
|
||||
}
|
||||
|
||||
@@ -343,6 +375,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// - Remind pcbId as already recovered before the true return,
|
||||
/// - Exclude lock of repeated execution for EOL.
|
||||
/// </remarks>
|
||||
/// <remarks date="2024-Jan-29" author="Thomas Wiedebusch">
|
||||
/// - Avoid writing of parameters if not writable. The DB delivers parameters which exclusively have to be
|
||||
/// compared to the specified value.
|
||||
/// </remarks>
|
||||
public Boolean RecoverRegisters(List<RecoveryRegisterItem> recoveryRegistersDb, Boolean eolProgramming = false)
|
||||
{
|
||||
if (_currentGenesis == null ||
|
||||
@@ -361,6 +397,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
StopRegisterAccess = false;
|
||||
ActualRegisterCtr = 0;
|
||||
|
||||
// Build string list for debug
|
||||
_dbParameterRegisterList.Clear();
|
||||
_dbParameterRegisterList = recoveryRegistersDb.Select(register => register.RegisterIdent).ToList();
|
||||
_dbParameterRegisterList.Sort();
|
||||
|
||||
// write values to Genesis
|
||||
_currentGenesis.ReLogin();
|
||||
if (!_currentGenesis.IsLoggedOn)
|
||||
@@ -370,14 +411,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
|
||||
|
||||
// prepare list for finalization depending on SENSUSRADIO installation
|
||||
var finalizeProgrammingAll = new List<ProgrammingParameters>();
|
||||
var finalizeProgrammingAll = new List<RecoveryRegisterItem>();
|
||||
if (recoveryRegistersDb.Any(x => x.RegisterIdent.Contains("SENSUSRADIO")))
|
||||
{
|
||||
finalizeProgrammingAll.AddRange(_finalizeProgrammingRadioOnly);
|
||||
}
|
||||
// add EOL sequence if called
|
||||
// add EOL (shipping reset of accumulators, alarms and setup of manufacturing date)
|
||||
if (eolProgramming)
|
||||
{
|
||||
finalizeProgrammingAll.AddRange(_finalizeProgrammingEol);
|
||||
}
|
||||
|
||||
// standard end of programming sequence
|
||||
finalizeProgrammingAll.AddRange(_finalizeProgramming);
|
||||
|
||||
@@ -396,15 +440,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
|
||||
try
|
||||
{
|
||||
_currentGenesis.WriteRegister(prepRecReg.RegisterName, prepRecReg.RegisterValue);
|
||||
_currentGenesis.WriteRegister(prepRecReg.RegisterIdent, prepRecReg.WriteValue);
|
||||
|
||||
// if this call does not throw an exception, the register is present
|
||||
var regDef = meterRegisters.GetRegisterDefinitionByName(prepRecReg.RegisterName);
|
||||
var regDef = meterRegisters.GetRegisterDefinitionByName(prepRecReg.RegisterIdent);
|
||||
|
||||
var strRawAndConvertedValue = "";
|
||||
try
|
||||
{
|
||||
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, prepRecReg.RegisterValue);
|
||||
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, prepRecReg.WriteValue);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -438,22 +482,26 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
|
||||
try
|
||||
{
|
||||
_currentGenesis.WriteRegister(recReg.RegisterIdent, recReg.WriteValue);
|
||||
|
||||
// if this call does not throw an exception, the register is present
|
||||
var regDef = meterRegisters.GetRegisterDefinitionByName(recReg.RegisterIdent);
|
||||
|
||||
// avoid register write if not allowed
|
||||
if (regDef.RegisterDetail.Privilege.Lvl8 != Access.RW)
|
||||
continue;
|
||||
|
||||
_currentGenesis.WriteRegister(recReg.RegisterIdent, recReg.WriteValue);
|
||||
|
||||
var strRawAndConvertedValue = "";
|
||||
try
|
||||
{
|
||||
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, recReg.WriteValue);
|
||||
// replace value in _restoreRegister with the required recovery value
|
||||
_restoreRegisters?.Set(regDef, recReg.WriteValue);
|
||||
_recoveryRegisters?.Set(regDef, recReg.WriteValue);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_currentGenesis.WriteLog("Could not replace register value of " + recReg.RegisterIdent + "; " + ex.Message);
|
||||
// nothing to do
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -483,15 +531,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
|
||||
try
|
||||
{
|
||||
_currentGenesis.WriteRegister(finalRecReg.RegisterName, finalRecReg.RegisterValue);
|
||||
_currentGenesis.WriteRegister(finalRecReg.RegisterIdent, finalRecReg.WriteValue);
|
||||
|
||||
// if this call does not throw an exception, the register is present
|
||||
var regDef = meterRegisters.GetRegisterDefinitionByName(finalRecReg.RegisterName);
|
||||
var regDef = meterRegisters.GetRegisterDefinitionByName(finalRecReg.RegisterIdent);
|
||||
|
||||
var strRawAndConvertedValue = "";
|
||||
try
|
||||
{
|
||||
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, finalRecReg.RegisterValue);
|
||||
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, finalRecReg.WriteValue);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -519,6 +567,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
_pcbIdRecoveryRegisters = _currentGenesis.PcbId;
|
||||
|
||||
_currentGenesis?.Logout();
|
||||
|
||||
// Wait for completion as storing needs a certain time
|
||||
Thread.Sleep(1000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -542,19 +594,23 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2023-Dec-11" author="Thomas Wiedebusch">
|
||||
/// - Avoid message event if message is empty.
|
||||
/// </remarks>
|
||||
/// <remarks date="2024-Jan-23" author="Thomas Wiedebusch">
|
||||
/// - Remind registers which failed the comparison including values.
|
||||
/// </remarks>
|
||||
public Boolean CompareRegisters()
|
||||
{
|
||||
if (_pcbIdFinalRegisterRead != _pcbIdInitialRegisterRead ||
|
||||
_restoreRegisters == null ||
|
||||
_recoveryRegisters == null ||
|
||||
_finalReadRegisters == null)
|
||||
return false;
|
||||
|
||||
StopRegisterAccess = false;
|
||||
ActualRegisterCtr = 0;
|
||||
var retVal = true;
|
||||
_failedComparisonRegisters?.Clear();
|
||||
|
||||
// build a string list of the registers being able to sort those
|
||||
var registerNames = _restoreRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
|
||||
var registerNames = _recoveryRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
|
||||
// Remove all excluded registers
|
||||
foreach (var regName in _excludedFromCompareParameters.Where(regName => registerNames.Any(reg => reg == regName)))
|
||||
{
|
||||
@@ -570,14 +626,14 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
{
|
||||
ActualRegisterCtr++;
|
||||
|
||||
var regDef = _restoreRegisters.GetRegisterDefinitionByName(regName);
|
||||
var regDef = _recoveryRegisters.GetRegisterDefinitionByName(regName);
|
||||
|
||||
var overallProcessCtrPercent = 100.0 * ActualRegisterCtr / registersCount;
|
||||
|
||||
try
|
||||
{
|
||||
// Get the raw byte array of this register
|
||||
var restorableRawRegister = _restoreRegisters.Get(regName);
|
||||
var restorableRawRegister = _recoveryRegisters.Get(regName);
|
||||
var finalReadRawRegister = _finalReadRegisters.Get(regName);
|
||||
|
||||
// take the size into account as a read value will be filled up to a chunk of 4 bytes
|
||||
@@ -661,6 +717,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
|
||||
strRequiredRegisterValue += $" - {Resources.StrMeterValue}: ({strReadBackRegisterValue})" +
|
||||
$" - {Resources.StrRegisterCompareFailed}";
|
||||
_failedComparisonRegisters?.Add(new RecoveryRegisterItem(regName, restorableRawRegister,
|
||||
finalReadRawRegister));
|
||||
retVal = false;
|
||||
}
|
||||
}
|
||||
@@ -728,23 +786,19 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the pre-defined dictionary
|
||||
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
|
||||
|
||||
// extract all registers which can be read and create two dictionaries for before update to safe program
|
||||
// internally the register content for comparison ability.
|
||||
foreach (var reg in meterRegisters.MeterRegisterDic.Where(r => r.Key.RegisterDetail?.Version.First != null
|
||||
&& r.Key.RegisterDetail.Version.Last != null && r.Key.RestoreCapability.StaticTypeValue != null
|
||||
&& r.Key.DataType != typeof(Rpc) && r.Key.IsAvailable &&
|
||||
(r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW || r.Key.RegisterDetail.Privilege.Lvl8 == Access.RO)))
|
||||
{
|
||||
_finalReadRegisters.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
|
||||
}
|
||||
// create a dictionary for final read being able to compare those with the initial read and restored
|
||||
if (!BuildReadableRegisterDictionary(ref _finalReadRegisters))
|
||||
return false;
|
||||
|
||||
// log to report file the after update register read string
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrReadRegister}", 0,
|
||||
Resources.StrReadRegistersAfterUpdate));
|
||||
|
||||
// Build string list for debug
|
||||
_finalRegisterList.Clear();
|
||||
_finalRegisterList = _finalReadRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
|
||||
_finalRegisterList.Sort();
|
||||
|
||||
// executes login read logout
|
||||
return ReadRegistersSet(_finalReadRegisters);
|
||||
}
|
||||
@@ -785,13 +839,83 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
// deny update of registers if already done
|
||||
if (_pcbIdInitialRegisterRead == _currentGenesis.PcbId &&
|
||||
_initialReadRegisters.MeterRegisterDic.Count > 0 &&
|
||||
_restoreRegisters.MeterRegisterDic.Count > 0)
|
||||
_recoveryRegisters.MeterRegisterDic.Count > 0)
|
||||
return true;
|
||||
|
||||
// remind the PCB ID before update for comparison
|
||||
_pcbIdInitialRegisterRead = _currentGenesis.PcbId;
|
||||
_initialReadRegisters.MeterRegisterDic.Clear();
|
||||
_restoreRegisters.MeterRegisterDic.Clear();
|
||||
|
||||
// create the dictionaries out of the configuration.json
|
||||
if (!BuildInitialDictionaries())
|
||||
return false;
|
||||
|
||||
// log to report file the initial register read string
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrReadRegister}", 0,
|
||||
Resources.StrReadRegistersBeforeUpdate));
|
||||
|
||||
return ReadRegistersSet(_initialReadRegisters, _recoveryRegisters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get DEFINED registers from GenesisMeter class and build a list all registers which are flagged
|
||||
/// with read write (RW) or read only (RO). Build a list of all registers being able to restore flagged
|
||||
/// with <see cref="StaticType"/> equals <see cref="StaticType.RestoreRequired"/>".
|
||||
/// The defined registers are based on the "configuration.json" and the installed application with
|
||||
/// a specific version.
|
||||
/// </summary>
|
||||
/// <returns>true if registers could be read</returns>
|
||||
/// <remarks date="2024-Jan-22" author="Thomas Wiedebusch">
|
||||
/// - Initial from <see cref="InitialReadRegisters"/>.
|
||||
/// </remarks>
|
||||
private Boolean BuildInitialDictionaries()
|
||||
{
|
||||
if (_currentGenesis == null)
|
||||
return false;
|
||||
|
||||
_recoveryRegisters.MeterRegisterDic.Clear();
|
||||
_recoveryRegisterList.Clear();
|
||||
|
||||
// create a dictionary for initial read being able to compare those with the final read and restored
|
||||
if (!BuildReadableRegisterDictionary(ref _initialReadRegisters))
|
||||
return false;
|
||||
|
||||
// take the pre-selected registers for final compare restore capability check even if the registers after
|
||||
// the update may have changed, only registers which are present before the update can be restored!
|
||||
foreach (var reg in _initialReadRegisters.MeterRegisterDic.Where(r =>
|
||||
r.Key.RestoreCapability.CheckRestoreCapability() &&
|
||||
r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW))
|
||||
{
|
||||
_recoveryRegisters.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
|
||||
_recoveryRegisterList.Add(reg.Key.GetIdent());
|
||||
}
|
||||
_recoveryRegisterList.Sort();
|
||||
|
||||
// Build string list for debug
|
||||
_initialRegisterList.Clear();
|
||||
_initialRegisterList = _initialReadRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
|
||||
_initialRegisterList.Sort();
|
||||
|
||||
return _recoveryRegisters.MeterRegisterDic.Count > 0 && _initialReadRegisters.MeterRegisterDic.Count > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get DEFINED registers from GenesisMeter class and build a list all registers which are flagged
|
||||
/// with read write (RW) or read only (RO).
|
||||
/// The defined registers are based on the "configuration.json" and the installed application with
|
||||
/// a specific version.
|
||||
/// </summary>
|
||||
/// <para name = "registers">all readable registers dictionary creation </para>
|
||||
/// <returns>true if register dictionary is not empty</returns>
|
||||
/// <returns>true if registers could be read</returns>
|
||||
/// <remarks date="2024-Jan-22" author="Thomas Wiedebusch">
|
||||
/// - Initial from <see cref="InitialReadRegisters"/>.
|
||||
/// </remarks>
|
||||
private Boolean BuildReadableRegisterDictionary(ref MeterRegisters registers)
|
||||
{
|
||||
if (_currentGenesis == null || registers?.MeterRegisterDic == null)
|
||||
return false;
|
||||
|
||||
registers.MeterRegisterDic.Clear();
|
||||
|
||||
// get the pre-defined dictionary
|
||||
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
|
||||
@@ -803,23 +927,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
&& r.Key.DataType != typeof(Rpc) && r.Key.IsAvailable &&
|
||||
(r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW || r.Key.RegisterDetail.Privilege.Lvl8 == Access.RO)))
|
||||
{
|
||||
_initialReadRegisters.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
|
||||
registers.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
|
||||
}
|
||||
|
||||
// take the pre-selected registers for final compare restore capability check even if the registers after
|
||||
// the update may have changed, only registers which are present before the update can be restored!
|
||||
foreach (var reg in _initialReadRegisters.MeterRegisterDic.Where(r =>
|
||||
r.Key.RestoreCapability.CheckRestoreCapability() &&
|
||||
r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW))
|
||||
{
|
||||
_restoreRegisters.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
|
||||
}
|
||||
|
||||
// log to report file the initial register read string
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrReadRegister}", 0,
|
||||
Resources.StrReadRegistersBeforeUpdate));
|
||||
|
||||
return ReadRegistersSet(_initialReadRegisters, _restoreRegisters);
|
||||
return registers.MeterRegisterDic.Count > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,6 +7,24 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
/// </summary>
|
||||
public class RecoveryRegisterItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Ctor
|
||||
/// </summary>
|
||||
public RecoveryRegisterItem()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ctor for write access parameter setup
|
||||
/// </summary>
|
||||
public RecoveryRegisterItem(String registerIdent, Byte[] writeValue, Byte[] readBackValue = null)
|
||||
{
|
||||
RegisterIdent = registerIdent;
|
||||
WriteValue = writeValue;
|
||||
ReadBackValue = readBackValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Register name, use the latest configuration.json to make sure that the address will be correct
|
||||
/// </summary>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
c43c40a030005a8f189e6179faf40a6d42bfef5c
|
||||
bf6bb8fceb3db5a9977dadc407cf576684bf7127
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("OmniPlus")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("OmniPlus")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2023")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f8d84b9a-0fcf-4083-b067-8c39b7314152")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
+1
-1
@@ -1 +1 @@
|
||||
65d75c3322f8a137c69963cfdc0cb6f1ffacf62a
|
||||
247396738e2c5d26ac00f9df05c0cc5c61d7f33a
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace Xylem.Common.Ui.GenesisToolBox.Infrastructure
|
||||
{
|
||||
internal class ADLoginModel
|
||||
internal class LDAPLoginModel
|
||||
{
|
||||
public string Assembly { get; set; }
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
var version = SoftwareVersion.Current;
|
||||
var user = new LDAPUser();
|
||||
|
||||
Login(new ADLoginModel
|
||||
Login(new LDAPLoginModel
|
||||
{
|
||||
Assembly = version.AssemblyName.Name,
|
||||
Email = user.Email,
|
||||
@@ -47,8 +47,8 @@
|
||||
/// <summary>
|
||||
/// Sends login request and obtains an bearer authorization token.
|
||||
/// </summary>
|
||||
/// <param name="model"><see cref="ADLoginModel"/> - containing all software and user info required for authentication.</param>
|
||||
public static void Login(ADLoginModel model)
|
||||
/// <param name="model"><see cref="LDAPLoginModel"/> - containing all software and user info required for authentication.</param>
|
||||
public static void Login(LDAPLoginModel model)
|
||||
{
|
||||
var authenticationResponse = LocalWebRequest.PostRequestAndGetResponseAsync(
|
||||
url: $"{ServiceUrls.LaaProductionAPI}/LaaProductionWeb/API/Login/AD",
|
||||
|
||||
Reference in New Issue
Block a user