merege main to dev

This commit is contained in:
Stoyan Zlatev
2024-02-09 08:04:07 +01:00
26 changed files with 394 additions and 230 deletions
+2 -2
View File
@@ -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 @@
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 @@
65d75c3322f8a137c69963cfdc0cb6f1ffacf62a
247396738e2c5d26ac00f9df05c0cc5c61d7f33a
@@ -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",