ReSharper: RequestProtocol, MeterFwUpdate
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=a44a776d_002Dd671_002D4675_002Dac7b_002Db6775ec7f289/@EntryIndexedValue"><SessionState ContinuousTestingIsOn="True" ContinuousTestingMode="1" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=a44a776d_002Dd671_002D4675_002Dac7b_002Db6775ec7f289/@EntryIndexedValue"><SessionState ContinuousTestingIsOn="True" ContinuousTestingMode="1" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||||
<Solution />
|
<Solution />
|
||||||
</SessionState></s:String>
|
</SessionState></s:String>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Limit retries to this value.
|
/// Limit retries to this value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const Int32 MaxRequestRetries = 6;
|
private const Int32 MaxRequestRetries = 6;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send delay between records in milliseconds before
|
/// Send delay between records in milliseconds before
|
||||||
@@ -55,6 +55,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig
|
|||||||
/// response from meter.
|
/// response from meter.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const Int32 InterRecordSendDelayMs = 5;
|
public const Int32 InterRecordSendDelayMs = 5;
|
||||||
|
//public const Int32 InterRecordSendDelayMs = 50;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout before retry will be initiated in milliseconds
|
/// Timeout before retry will be initiated in milliseconds
|
||||||
|
|||||||
@@ -1746,6 +1746,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
|||||||
var data = RegisterConverter.ConvertFrom(value);
|
var data = RegisterConverter.ConvertFrom(value);
|
||||||
_logger.Info( $"Slot:{Slot} - Write register({regDef.RegisterName}), " +
|
_logger.Info( $"Slot:{Slot} - Write register({regDef.RegisterName}), " +
|
||||||
$"record({BitConverter.ToString(data.ToArray())})");
|
$"record({BitConverter.ToString(data.ToArray())})");
|
||||||
|
|
||||||
PreRegisterWrite(regDef, data);
|
PreRegisterWrite(regDef, data);
|
||||||
|
|
||||||
var command = data.Length > RegisterDefinition.ChunkSize ?
|
var command = data.Length > RegisterDefinition.ChunkSize ?
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
//package file search string for applications including blank!!!!
|
//package file search string for applications including blank!!!!
|
||||||
private const String StrPackageFileAppId = "Id ";
|
private const String StrPackageFileAppId = "Id ";
|
||||||
private const String StrPackageFileAppCrc = "CRC ";
|
private const String StrPackageFileAppCrc = "CRC ";
|
||||||
|
private const String StrPackageFileAppCrc16 = "CRC16 ";
|
||||||
private const String StrPackageFileAppVersion = "version ";
|
private const String StrPackageFileAppVersion = "version ";
|
||||||
|
|
||||||
//binary file name is a combination of "binfile" application ID underline version
|
//binary file name is a combination of "binfile" application ID underline version
|
||||||
@@ -102,7 +103,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Double? CoreRevisionMinimum
|
public Double? CoreRevisionMinimum
|
||||||
{
|
{
|
||||||
get; private set;
|
get; set;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Core revision maximum as double for comparison
|
/// Core revision maximum as double for comparison
|
||||||
@@ -2017,6 +2018,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
/// <remarks date="2020-Dec-02" author="Thomas Wiedebusch">
|
/// <remarks date="2020-Dec-02" author="Thomas Wiedebusch">
|
||||||
/// - Extraction of valid core revisions min/max.
|
/// - Extraction of valid core revisions min/max.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Nov-07" author="Thomas Wiedebusch">
|
||||||
|
/// - CRC16 added:
|
||||||
|
/// old versions will contain CRC without a number,
|
||||||
|
/// new versions starting with 2022-11-04_NA_B122B contain a CRC16 and CRC32 identifier.
|
||||||
|
/// - File line check modified to be immune against multiple blanks behind the field identifier.
|
||||||
|
/// </remarks>
|
||||||
public Boolean ValidateFileAppsWithPackageFile()
|
public Boolean ValidateFileAppsWithPackageFile()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_packageDescriptionFile) || FileApps.Count == 0 ||
|
if (string.IsNullOrEmpty(_packageDescriptionFile) || FileApps.Count == 0 ||
|
||||||
@@ -2031,9 +2038,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
{
|
{
|
||||||
//find a line which contains all required information
|
//find a line which contains all required information
|
||||||
validAppsCtr += packageFileLines.Count(line =>
|
validAppsCtr += packageFileLines.Count(line =>
|
||||||
line.Contains($"{StrPackageFileAppId}{ConvertAppIdToString(fileApp.AppId)}") &&
|
line.Contains($"{StrPackageFileAppId}") &&
|
||||||
line.Contains($"{StrPackageFileAppCrc}{ConvertCrcToString(fileApp.Crc)}") &&
|
line.Contains($"{ConvertAppIdToString(fileApp.AppId)}") &&
|
||||||
line.Contains($"{StrPackageFileAppVersion}{fileApp.StrVersion}"));
|
(line.Contains($"{StrPackageFileAppCrc}") ||
|
||||||
|
line.Contains($"{StrPackageFileAppCrc16}")) &&
|
||||||
|
line.Contains($"{ConvertCrcToString(fileApp.Crc)}") &&
|
||||||
|
line.Contains($"{StrPackageFileAppVersion}") &&
|
||||||
|
line.Contains($"{fileApp.StrVersion}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//extract the core revision fields
|
//extract the core revision fields
|
||||||
|
|||||||
+8
@@ -5,6 +5,14 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum RequestAcknowledgeState
|
public enum RequestAcknowledgeState
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Acknowledge code for unassigned command
|
||||||
|
/// </summary>
|
||||||
|
CommandNotAssigned,
|
||||||
|
/// <summary>
|
||||||
|
/// Acknowledge code not set, will be used initially
|
||||||
|
/// </summary>
|
||||||
|
NotDecoded,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Response missing
|
/// Response missing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -166,24 +166,43 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// <remarks date="2021-Feb-02" author="T.Wiedebusch">
|
/// <remarks date="2021-Feb-02" author="T.Wiedebusch">
|
||||||
/// - Avoid enqueue of _recordInProcess if retry counter is 0.
|
/// - Avoid enqueue of _recordInProcess if retry counter is 0.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Nov-04" author="T.Wiedebusch">
|
||||||
|
/// - Additional DEBUG information included about FIFO and loops.
|
||||||
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Nov-07" author="T.Wiedebusch">
|
||||||
|
/// - Command not assigned response for recordInProcess == null.
|
||||||
|
/// </remarks>
|
||||||
public RequestAcknowledgeState ProcessRecordList()
|
public RequestAcknowledgeState ProcessRecordList()
|
||||||
{
|
{
|
||||||
_logger.Trace(" 1 ProcessRecordList");
|
_logger.Trace($" Enry to ProcessRecordList, FIFO contains ({_recordsSendFifo.Count}) records");
|
||||||
|
|
||||||
//The inter record send delay has to be hold before trying to communicate again
|
//The inter record send delay has to be hold before trying to communicate again
|
||||||
const Int32 interRecordSendDelayMs = CommunicationConfig.InterRecordSendDelayMs;
|
const Int32 interRecordSendDelayMs = CommunicationConfig.InterRecordSendDelayMs;
|
||||||
|
|
||||||
|
//remind counter for FIFO and therefore execution loops
|
||||||
|
var loopCounter = 0;
|
||||||
|
|
||||||
//check if FIFO is empty and get the actual record to process out of it
|
//check if FIFO is empty and get the actual record to process out of it
|
||||||
while (_recordsSendFifo.TryDequeue(out var internalRecord))
|
while (_recordsSendFifo.TryDequeue(out var internalRecord))
|
||||||
{
|
{
|
||||||
_logger.Trace(" 1 TryDequeue ProcessRecordList");
|
// Starting with record number 1
|
||||||
|
loopCounter++;
|
||||||
|
_logger.Trace($"Record({loopCounter}) - Dequeued from FIFO");
|
||||||
|
|
||||||
|
//pointer to new record
|
||||||
_recordInProcess = internalRecord;
|
_recordInProcess = internalRecord;
|
||||||
|
if (_recordInProcess == null) return RequestAcknowledgeState.CommandNotAssigned;
|
||||||
|
|
||||||
|
//mark record as answer outstanding
|
||||||
|
_recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
_logger.Trace(" 1 TryDequeue DO ProcessRecordList");
|
_logger.Trace($"Record({loopCounter}) - Processing");
|
||||||
//log retries
|
//log retries
|
||||||
if (_recordInProcess.RetryCtr > 0)
|
if (_recordInProcess.RetryCtr > 0)
|
||||||
{
|
{
|
||||||
_logger.Debug($"{_ident} Retry({_recordInProcess.RetryCtr})");
|
_logger.Debug($"{_ident} Retry({_recordInProcess.RetryCtr})");
|
||||||
|
_logger.Trace($"Record({loopCounter}) - Retry({_recordInProcess.RetryCtr})");
|
||||||
}
|
}
|
||||||
|
|
||||||
//log request protocol content
|
//log request protocol content
|
||||||
@@ -216,6 +235,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
requestTimeUtc = DateTimeOffset.UtcNow;
|
requestTimeUtc = DateTimeOffset.UtcNow;
|
||||||
}
|
}
|
||||||
responseTimeMs = (Int32)timeSpan.TotalMilliseconds;
|
responseTimeMs = (Int32)timeSpan.TotalMilliseconds;
|
||||||
|
|
||||||
} while (_recordInProcess.Acknowledge != RequestAcknowledgeState.Ok &&
|
} while (_recordInProcess.Acknowledge != RequestAcknowledgeState.Ok &&
|
||||||
_recordInProcess.SkipRetryErrorCode != _recordInProcess.ResponseErrorCode &&
|
_recordInProcess.SkipRetryErrorCode != _recordInProcess.ResponseErrorCode &&
|
||||||
_timeOutMs > responseTimeMs);
|
_timeOutMs > responseTimeMs);
|
||||||
@@ -249,6 +269,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
_recordInProcess.SkipRetryErrorCode != _recordInProcess.ResponseErrorCode);
|
_recordInProcess.SkipRetryErrorCode != _recordInProcess.ResponseErrorCode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _recordInProcess.Acknowledge;
|
return _recordInProcess.Acknowledge;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,8 +392,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// <remarks date="2022-Oct-02" author="T.Wiedebusch">
|
/// <remarks date="2022-Oct-02" author="T.Wiedebusch">
|
||||||
/// - On wakeup message 5 retires are allowed to avoid an infinite loop.
|
/// - On wakeup message 5 retires are allowed to avoid an infinite loop.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Oct-04" author="T.Wiedebusch">
|
||||||
|
/// - On wakeup message exit this routine.
|
||||||
|
/// </remarks>
|
||||||
public override void DecodeRecord(IPortDataEventArgs data)
|
public override void DecodeRecord(IPortDataEventArgs data)
|
||||||
{
|
{
|
||||||
|
//new request has to be analyzed
|
||||||
|
_recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded;
|
||||||
//the request response record covers the entire request protocol
|
//the request response record covers the entire request protocol
|
||||||
var responseRecord = GetTransmitProtocol().DecodeDataForLogicLayer((List<Byte>)data.GetData());
|
var responseRecord = GetTransmitProtocol().DecodeDataForLogicLayer((List<Byte>)data.GetData());
|
||||||
|
|
||||||
@@ -405,10 +431,18 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
{
|
{
|
||||||
_recordInProcess.Acknowledge = RequestAcknowledgeState.WakeupMessage;
|
_recordInProcess.Acknowledge = RequestAcknowledgeState.WakeupMessage;
|
||||||
//initiate a single retry on wakeup message response
|
//initiate a single retry on wakeup message response
|
||||||
if ( _recordInProcess.WakeupMessageRetryCtr < 10)
|
if ( _recordInProcess.WakeupMessageRetryCtr < 5)
|
||||||
{
|
{
|
||||||
_logger.Debug($"{_ident} Wakeup message received");
|
|
||||||
_recordInProcess.WakeupMessageRetryCtr++;
|
_recordInProcess.WakeupMessageRetryCtr++;
|
||||||
|
_logger.Debug($"{_ident} Wakeup message({_recordInProcess.WakeupMessageRetryCtr}) received");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if it is not identified as valid wakeup message it is something unknown
|
||||||
|
_recordInProcess.Acknowledge = RequestAcknowledgeState.DecodingError;
|
||||||
|
_logger.Debug($"{_ident} Message decoding error.");
|
||||||
|
}
|
||||||
// reset retry counter to get all required retries
|
// reset retry counter to get all required retries
|
||||||
_recordInProcess.RetryCtr = -1;
|
_recordInProcess.RetryCtr = -1;
|
||||||
//reset timeout to a normal value if timeout is extremely high but response received
|
//reset timeout to a normal value if timeout is extremely high but response received
|
||||||
@@ -416,8 +450,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
_timeOutMs = CommunicationConfig.BusyTimeoutMs;
|
_timeOutMs = CommunicationConfig.BusyTimeoutMs;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//log request protocol content
|
//log request protocol content
|
||||||
@@ -550,6 +582,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
if (command == Commands.MultipleReadData && meterRegister != null && meterRegister.DataType == typeof(String))
|
if (command == Commands.MultipleReadData && meterRegister != null && meterRegister.DataType == typeof(String))
|
||||||
{
|
{
|
||||||
var completeResponse = new List<Byte>();
|
var completeResponse = new List<Byte>();
|
||||||
|
//TODO THW check this including the recursive call CommandToMeter
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var cRecord = CommandToMeter(Commands.ReadData, meterRegister, payload, expectedLength,
|
var cRecord = CommandToMeter(Commands.ReadData, meterRegister, payload, expectedLength,
|
||||||
@@ -668,7 +701,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Analyzes the error code
|
/// Analyzes the error code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CheckErrorCode()
|
private void CheckErrorCode()
|
||||||
{
|
{
|
||||||
if (_recordInProcess.ResponseErrorBase == (Byte)ConfigExErrors.Base)
|
if (_recordInProcess.ResponseErrorBase == (Byte)ConfigExErrors.Base)
|
||||||
{
|
{
|
||||||
@@ -709,7 +742,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Boolean ContainsRegisterIdent(String registerName)
|
public Boolean ContainsRegisterIdent(String registerName)
|
||||||
{
|
{
|
||||||
return _recordsSendFifo.Any(a => a.Register.GetIdent().ToLower() == registerName.ToLower());
|
return _recordsSendFifo.Any(a => string.Equals(a.Register.GetIdent(),
|
||||||
|
registerName, StringComparison.CurrentCultureIgnoreCase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class RequestRecord
|
public class RequestRecord
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Indicates the base command <see cref="Commands" />
|
|
||||||
/// </summary>
|
|
||||||
public readonly Byte Command;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the base command <see cref="Commands" />
|
/// Indicates the base command <see cref="Commands" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -65,12 +60,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data containing the request protocol
|
/// Data containing the request protocol
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Byte> RequestProtocolData;
|
public readonly List<Byte> RequestProtocolData;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Encoded with transmit protocol, ready to stream to port as is
|
/// Encoded with transmit protocol, ready to stream to port as is
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Byte> EncodedRequestData { get; internal set; }
|
public List<Byte> EncodedRequestData { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracted payload of response
|
/// Extracted payload of response
|
||||||
@@ -85,12 +80,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// avoid logging for e.g. password
|
/// avoid logging for e.g. password
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Boolean HideDataInLog;
|
public readonly Boolean HideDataInLog;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// error mask to skip retries for functional errors <see cref="ResponseErrorCode"/>
|
/// error mask to skip retries for functional errors <see cref="ResponseErrorCode"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public UInt16 SkipRetryErrorCode;
|
public readonly UInt16 SkipRetryErrorCode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ctor for an base command <see cref="Commands" />
|
/// Ctor for an base command <see cref="Commands" />
|
||||||
@@ -106,7 +101,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
|
|||||||
Int32 responseTimeoutMs = 100, RegisterDefinition register = null, Boolean hideDataInLog = false,
|
Int32 responseTimeoutMs = 100, RegisterDefinition register = null, Boolean hideDataInLog = false,
|
||||||
UInt16 skipRetryErrorCode = CommunicationConfig.SkipRetryErrorCode)
|
UInt16 skipRetryErrorCode = CommunicationConfig.SkipRetryErrorCode)
|
||||||
{
|
{
|
||||||
Command = command;
|
|
||||||
ResponseCommand = (Byte)(command + 1);
|
ResponseCommand = (Byte)(command + 1);
|
||||||
Register = register;
|
Register = register;
|
||||||
RequestProtocolData = requestProtocolData;
|
RequestProtocolData = requestProtocolData;
|
||||||
|
|||||||
@@ -1589,6 +1589,13 @@ namespace Xylem.Common.Ui.GenesisToolBox
|
|||||||
|
|
||||||
#region ExternalCalls
|
#region ExternalCalls
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="slot"></param>
|
||||||
|
/// <param name="binaryPath"></param>
|
||||||
|
/// <param name="packageInfoPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public Boolean Prepare(Int32 slot, String binaryPath, String packageInfoPath)
|
public Boolean Prepare(Int32 slot, String binaryPath, String packageInfoPath)
|
||||||
{
|
{
|
||||||
_updateGui = false;
|
_updateGui = false;
|
||||||
@@ -1675,7 +1682,13 @@ namespace Xylem.Common.Ui.GenesisToolBox
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
public MsgEventargs LastMsgEvent;
|
public MsgEventargs LastMsgEvent;
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
public class MsgEventargs : EventArgs
|
public class MsgEventargs : EventArgs
|
||||||
{
|
{
|
||||||
public String Text;
|
public String Text;
|
||||||
|
|||||||
Reference in New Issue
Block a user