GenesisMeter: - Removed retries on "ReadMeterFwAndAssignRegisters" as the reties will be handled by the RequestProtocol

This commit is contained in:
Thomas Wiedebusch
2023-02-13 11:39:12 +01:00
parent 204377fb30
commit b22994fc67
6 changed files with 58 additions and 54 deletions
+1 -1
View File
@@ -155,7 +155,7 @@
</site>
<site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\Users\drabesch_ro\Repo\lab\la_operations\laa_production\Common\Service\MeterProcessState" />
<virtualDirectory path="/" physicalPath="D:\Projekte\SENSUS_GitLab\laa_production\Common\Service\MeterProcessState" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:56011:localhost" />
+1
View File
@@ -27,6 +27,7 @@
<s:Boolean x:Key="/Default/Environment/ExcludedFiles/FilesAndFoldersToSkip/=1057AD21_002DBA22_002D4CAB_002DB3FE_002D88C5C9980E6A_002Fd_003AScripts_002Ff_003Ajquery_002D1_002E10_002E2_002Eintellisense_002Ejs/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/Environment/Hierarchy/Build/SolBuilderDuo/UseMsbuildSolutionBuilder/@EntryValue">NewVersion</s:String>
<s:Boolean x:Key="/Default/Environment/Hierarchy/EntityFrameworkOptions/IsAlreadyNotifiedAboutEntityFramework/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/Environment/Highlighting/HighlightingSourceSnapshotLocation/@EntryValue">C:\Users\Thomas\AppData\Local\Temp\JetBrains\ReSharperPlatformVs15\vAny_33007af5\CoverageData\_Common.-1885154465\Snapshot\snapshot.utdcvr</s:String>
@@ -1263,7 +1263,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
try
{
var radioFrequencyRaw = ReadRegister(Register.Sensusradio.FrequencyIndicator);
if (radioFrequencyRaw != null )
if (radioFrequencyRaw != null)
{
Region = "EMEA";
RadioFrequencyMhz = RegisterConverter.ConvertTo<Int32>(radioFrequencyRaw);
@@ -1283,7 +1283,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
LutCrc = "?";
}
}
/// <summary>
/// Reading all applications which can be found in the configuration.json and have been stored
/// to the meter register dictionary in advance.
@@ -1313,6 +1313,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <remarks date="2023-Jan-16" author="Thomas Wiedebusch">
/// - Checked meter size string for "DN", than it cannot be an EMEA version.
/// </remarks>
/// <remarks date="2023-Feb-13" author="Thomas Wiedebusch">
/// - Removed retry as this will be handled by the <see cref="RequestProtocol"/>.
/// </remarks>
private void ReadMeterFirmwareAndAssignRegisters()
{
//avoid overwriting of list if this already exits
@@ -1329,39 +1332,32 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
UInt16 readFwCrc = 0;
var isInstalled = false;
var versionString = "";
var recount = 4;
while (recount > 0)
if (WriteRegister(Register.System.CheckFwPresence, appVersionToRead.AppId))
{
recount -= 1;
//read version, skip retries on SYSTEM 0x04-> FW nor present is a valid feedback
var readFwVersionBytes = ReadRegister(Register.System.CheckFwPresence, 4);
if (WriteRegister(Register.System.CheckFwPresence, appVersionToRead.AppId))
//the FW version as Uint32 will be used for comparison with the configuration.json
if (readFwVersionBytes != null && readFwVersionBytes.Length > 0)
{
//read version, skip retries on SYSTEM 0x04-> FW nor present is a valid feedback
var readFwVersionBytes = ReadRegister(Register.System.CheckFwPresence, 4);
readFwVersion = (UInt32)(((readFwVersionBytes[1] & 0xF0) >> 4) * 10 +
(readFwVersionBytes[1] & 0x0F)) * 100;
readFwVersion += (UInt32)(((readFwVersionBytes[0] & 0xF0) >> 4) * 10 +
(readFwVersionBytes[0] & 0x0F));
//build the version string, because e.g. FLEXNETVERSION is one application which does not
//follow the same rule. After the upper conversion, the hexadecimal outline will be lost
versionString = BuildFwVersionString(readFwVersionBytes[1], readFwVersionBytes[0]);
if (appVersionToRead.AppName == "FLEXNETVERSION")
FwVersion = versionString;
//the FW version as Uint32 will be used for comparison with the configuration.json
if (readFwVersionBytes != null && readFwVersionBytes.Length > 0)
if (readFwVersion != 0)
{
readFwVersion = (UInt32)(((readFwVersionBytes[1] & 0xF0) >> 4) * 10 +
(readFwVersionBytes[1] & 0x0F)) * 100;
readFwVersion += (UInt32)(((readFwVersionBytes[0] & 0xF0) >> 4) * 10 +
(readFwVersionBytes[0] & 0x0F));
//build the version string, because e.g. FLEXNETVERSION is one application which does not
//follow the same rule. After the upper conversion, the hexadecimal outline will be lost
versionString = BuildFwVersionString(readFwVersionBytes[1], readFwVersionBytes[0]);
if (appVersionToRead.AppName == "FLEXNETVERSION")
FwVersion = versionString;
if (readFwVersion != 0)
isInstalled = true;
//write application Id to CRC register
if (WriteRegister(Register.System.CheckFwCrc, appVersionToRead.AppId))
{
isInstalled = true;
//write application Id to CRC register
if (WriteRegister(Register.System.CheckFwCrc, appVersionToRead.AppId))
{
readFwCrc = RegisterConverter.ConvertTo<UInt16>(ReadRegister(Register.System.CheckFwCrc));
}
break;
readFwCrc = RegisterConverter.ConvertTo<UInt16>(ReadRegister(Register.System.CheckFwCrc));
}
}
}
@@ -1381,7 +1377,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
CheckRegionSizeLutCrc();
//read metrology upgrade permission
MetrologyUpgradePermission = RegisterConverter.ConvertTo<Byte>(
ReadRegister(Register.System.MetrologyUpgradePermission));
@@ -1491,7 +1487,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
var registerAddForOldConfigs = registerToPotentialAdd.GroupBy(item => item.GetIdent())
.Select(grp => grp.Aggregate((max, cur) =>
(max == null || cur.RegisterDetail.Version.Last > max.RegisterDetail.Version.Last) ?
(max == null || cur.RegisterDetail.Version.Last > max.RegisterDetail.Version.Last) ?
cur : max));
foreach (var registerAddOldConfig in registerAddForOldConfigs)
@@ -109,7 +109,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// </summary>
public Int32 AdditionalRetryTimeoutMs;
private Int32 _timeOutMs;
private Int32 _maxTimeOutMs;
private readonly String _ident;
@@ -215,38 +215,41 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
//set timeout for one communication trial adding the transmit protocol specific timeout and
//increase the timeout with each retry
_timeOutMs = _recordInProcess.ResponseTimeoutMs + AdditionalRetryTimeoutMs +
_maxTimeOutMs = _recordInProcess.ResponseTimeoutMs + AdditionalRetryTimeoutMs +
CommunicationConfig.ResponseTimeoutMs * (_recordInProcess.RetryCtr + 1);
//start initial communication or retry
OnRecordReadyToSend?.Invoke(this, new ListBytePortDataEventArgs(_recordInProcess.EncodedRequestData));
//time reminder of request record
var requestTimeUtc = DateTimeOffset.UtcNow;
Int32 responseTimeMs;
Int32 actualResponseWaitTimeMs;
//wait for communication acknowledge or until timeout, this also handles the inter record send delay
do
{
//minimum delay is the inter record send delay
Thread.Sleep(interRecordSendDelayMs);
var timeoutTimeUtc = DateTimeOffset.UtcNow;
var timeSpan = timeoutTimeUtc - requestTimeUtc;
var actualTimeUtc = DateTimeOffset.UtcNow;
//actual time difference from request to now
var timeSpan = actualTimeUtc - requestTimeUtc;
//avoid total milliseconds below zero at time overflow
if (timeSpan.TotalMilliseconds < 0)
{
requestTimeUtc = DateTimeOffset.UtcNow;
}
responseTimeMs = (Int32)timeSpan.TotalMilliseconds;
actualResponseWaitTimeMs = (Int32)timeSpan.TotalMilliseconds;
} while (_recordInProcess.Acknowledge != RequestAcknowledgeState.Ok &&
_recordInProcess.SkipRetryErrorCode != _recordInProcess.ResponseErrorCode &&
_timeOutMs > responseTimeMs);
_maxTimeOutMs > actualResponseWaitTimeMs);
//if timeout value reaches zero, the response hasn't been received or the delay until
//next communication needed to be hold
if (_timeOutMs <= responseTimeMs)
if (_maxTimeOutMs <= actualResponseWaitTimeMs)
{
_logger.Error(_recordInProcess.Acknowledge == RequestAcknowledgeState.NoResponse
? $"{_ident} Response timeout({responseTimeMs}ms)"
: $"{_ident} Communication delay({responseTimeMs}ms)");
? $"{_ident} Response timeout({actualResponseWaitTimeMs}ms)"
: $"{_ident} Communication delay({actualResponseWaitTimeMs}ms)");
}
//skip loop to handle re-authorization
@@ -395,28 +398,32 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// <remarks date="2022-Oct-04" author="T.Wiedebusch">
/// - On wakeup message exit this routine.
/// </remarks>
/// <remarks date="2023-Feb-13" author="T.Wiedebusch">
/// - Early exit on _recordInProcess == null,
/// - Wakeup message retries from 5 to 2,
/// - Removed error base from error code decision as error base is only the AppId
/// </remarks>
public override void DecodeRecord(IPortDataEventArgs data)
{
if (_recordInProcess == null) return;
//new request has to be analyzed
_recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded;
//the request response record covers the entire request protocol
var responseRecord = GetTransmitProtocol().DecodeDataForLogicLayer((List<Byte>)data.GetData());
//if the current record is invalid or on protocol decoding failure
if (null == _recordInProcess || responseRecord.Count == 0)
//on protocol decoding failure
if (responseRecord.Count == 0)
{
if (_recordInProcess != null)
_recordInProcess.Acknowledge = RequestAcknowledgeState.DecodingError;
_recordInProcess.Acknowledge = RequestAcknowledgeState.DecodingError;
_logger.Debug($"{_ident} Message decoding error.");
//reset timeout to a normal value if timeout is extremely high but response received
if (_timeOutMs > CommunicationConfig.BusyTimeoutMs)
_timeOutMs = CommunicationConfig.BusyTimeoutMs;
if (_maxTimeOutMs > CommunicationConfig.BusyTimeoutMs)
_maxTimeOutMs = CommunicationConfig.BusyTimeoutMs;
return;
}
//avoid wakeup retry on acknowledged record
if (responseRecord.Count == WakeupMessage.Length
&& null != _recordInProcess
&& RequestAcknowledgeState.Ok != _recordInProcess.Acknowledge)
{
// check for wakeup message
@@ -431,7 +438,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
{
_recordInProcess.Acknowledge = RequestAcknowledgeState.WakeupMessage;
//initiate a single retry on wakeup message response
if ( _recordInProcess.WakeupMessageRetryCtr < 5)
if ( _recordInProcess.WakeupMessageRetryCtr < 2)
{
_recordInProcess.WakeupMessageRetryCtr++;
_logger.Debug($"{_ident} Wakeup message({_recordInProcess.WakeupMessageRetryCtr}) received");
@@ -446,8 +453,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
// reset retry counter to get all required retries
_recordInProcess.RetryCtr = -1;
//reset timeout to a normal value if timeout is extremely high but response received
if (_timeOutMs > CommunicationConfig.BusyTimeoutMs)
_timeOutMs = CommunicationConfig.BusyTimeoutMs;
if (_maxTimeOutMs > CommunicationConfig.BusyTimeoutMs)
_maxTimeOutMs = CommunicationConfig.BusyTimeoutMs;
return;
}
@@ -501,7 +508,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
}
//examine error code, if base (AppId) is not 0 the reason 0 may be an error!!!!
if (_recordInProcess.ResponseErrorBase != 0 || _recordInProcess.ResponseErrorReason != 0)
if (/*_recordInProcess.ResponseErrorBase != 0 ||*/ _recordInProcess.ResponseErrorReason != 0)
{
_logger.Warn($"{_ident} Error code received(0x{_recordInProcess.ResponseErrorBase:X2}" +
$"{_recordInProcess.ResponseErrorReason:X2})");
@@ -1 +1 @@
5ed75d99ee45ff67821090f1b3dbb001dd9e4fe3
1a3d4919c9c702245832d925951f2b7cb72fc333
@@ -1 +1 @@
0d85a5b3a7561b41163c20e5dc7713bcd0d65555
f64d563def603c89cafafa61a3219ba97e1e344c