BaseSerialPort:

- Flush buffer (DiscardInBuffer) removed as some bytes are missing from time to time.  The IrDA sniffer showed these on the communication line, but they are incompletely received.  Assuming the DiscardInBuffer may be delayed, so the incoming data will be scrapped.

IrdaTransmitProtocol:
- WakeUpMessage marked and debug output
This commit is contained in:
Thomas Wiedebusch
2022-07-15 17:18:12 +02:00
parent 2f87d186a0
commit bac97f8e57
7 changed files with 49 additions and 16 deletions
+1 -1
View File
@@ -155,7 +155,7 @@
</site> </site>
<site name="MeterProcessState" id="2"> <site name="MeterProcessState" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool"> <application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\ProgrammeSensus\Repo\Lab\La_Operations\laa_production\Common\Service\MeterProcessState" /> <virtualDirectory path="/" physicalPath="D:\Projekte\SENSUS_GitLab\laa_production\Common\Service\MeterProcessState" />
</application> </application>
<bindings> <bindings>
<binding protocol="http" bindingInformation="*:56011:localhost" /> <binding protocol="http" bindingInformation="*:56011:localhost" />
@@ -409,6 +409,11 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts
/// <remarks date="2019-Dec-14" author="T.Wiedebusch"> /// <remarks date="2019-Dec-14" author="T.Wiedebusch">
/// - Flush buffer if received length is 0. /// - Flush buffer if received length is 0.
/// </remarks> /// </remarks>
/// <remarks date="2022-Jul-15" author="T.Wiedebusch">
/// - Flush buffer (DiscardInBuffer) removed as some bytes are missing from time to time.
/// The IrDA sniffer showed these on the communication line, but they are incompletely received.
/// Assuming the DiscardInBuffer may be delayed, so the incoming data will be scrapped.
/// </remarks>
private void ReadingThreadLoop() private void ReadingThreadLoop()
{ {
//put the receive thread to JoinWaitSleep to avoid reading and logger output for timeout on //put the receive thread to JoinWaitSleep to avoid reading and logger output for timeout on
@@ -464,7 +469,7 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts
rxByte = (Byte)_serialPort.ReadByte(); rxByte = (Byte)_serialPort.ReadByte();
//record raw data stream for output on missing sync-byte to investigate this issue //record raw data stream for output on missing sync-byte to investigate this issue
rxRawRecord.Add(rxByte); rxRawRecord.Add(rxByte);
} while ((_serialPort.BytesToRead > 0) && (PortSettingsForTransmitProtocol.ProtSyncByte != rxByte)); } while (_serialPort.BytesToRead > 0 && PortSettingsForTransmitProtocol.ProtSyncByte != rxByte);
// if syncByte has not been detected skip read loop and wait for next incoming record // if syncByte has not been detected skip read loop and wait for next incoming record
if (PortSettingsForTransmitProtocol.ProtSyncByte == rxByte) if (PortSettingsForTransmitProtocol.ProtSyncByte == rxByte)
@@ -545,10 +550,10 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts
catch (TimeoutException) catch (TimeoutException)
{ {
//flush receive buffer at timeout to force task to enter JoinWaitSleep state in finally //flush receive buffer at timeout to force task to enter JoinWaitSleep state in finally
if (_serialPort.IsOpen) //if (_serialPort.IsOpen)
{ //{
_serialPort.DiscardInBuffer(); // _serialPort.DiscardInBuffer();
} //}
_byteDataLogger.Trace($"{Ident} Read timeout({InterByteReadDelayMs}ms)"); _byteDataLogger.Trace($"{Ident} Read timeout({InterByteReadDelayMs}ms)");
//_byteDataLogger.Trace($"{Ident} Read timeout({PortSettingsForTransmitProtocol.ResponseTimeoutMs}ms)"); //_byteDataLogger.Trace($"{Ident} Read timeout({PortSettingsForTransmitProtocol.ResponseTimeoutMs}ms)");
@@ -655,6 +660,7 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts
_serialPort.Write(txByteList.ToArray(), 0, txByteList.Count); _serialPort.Write(txByteList.ToArray(), 0, txByteList.Count);
//TODO THW flush before sending NOT after
// flush the buffer for MOXA, to avoid two subsequent communications assembled to one communication! // flush the buffer for MOXA, to avoid two subsequent communications assembled to one communication!
_serialPort.BaseStream.Flush(); _serialPort.BaseStream.Flush();
@@ -13,7 +13,6 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
// Format of IrDA transmit protocol: // Format of IrDA transmit protocol:
// IrdaSyncByte|IrdaSend/ReceiveHeader|IrdaPayLoadLength|IrdaCommand/Message| // IrdaSyncByte|IrdaSend/ReceiveHeader|IrdaPayLoadLength|IrdaCommand/Message|
// IrdaPayLoad|IrdaCrc LSB|IrdaCrc MSB // IrdaPayLoad|IrdaCrc LSB|IrdaCrc MSB
private const Byte IrdaSyncByte = 0x9B; private const Byte IrdaSyncByte = 0x9B;
// Encoding of IrdaSendHeader (LAT: listen after talk, LAT 10b: 500ms) // Encoding of IrdaSendHeader (LAT: listen after talk, LAT 10b: 500ms)
@@ -25,6 +24,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
// Bits: 0| 1| 10| 0| 001 // Bits: 0| 1| 10| 0| 001
// standard frame|register to adapter|LAT|reserved|optical message // standard frame|register to adapter|LAT|reserved|optical message
private const Byte IrdaReceiveHeader = 0x61; private const Byte IrdaReceiveHeader = 0x61;
// Mask out the LAT and the reserved bit for the IrdaReceiveHeader // Mask out the LAT and the reserved bit for the IrdaReceiveHeader
private const Byte IrdaReceiveHeaderMask = 0xC7; private const Byte IrdaReceiveHeaderMask = 0xC7;
@@ -34,6 +34,10 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
// data from register (water meter) to adapter (software) referred as optical message // data from register (water meter) to adapter (software) referred as optical message
private const Byte IrdaMessage = 0x03; private const Byte IrdaMessage = 0x03;
// wakeup from register (water meter) to adapter (software) wakeup message length of IrDA
private static readonly Byte[] IrdaWakeupMessage =
{IrdaSyncByte, 0x41, 0x03, 0x04, 0x00, 0xFF, 0xFF, 0xED, 0x6E };
// IrdaSyncByte|IrdaReceiveHeader|IrdaPayLoadLength|IrdaMessage|CRC LSB|CRC MSB // IrdaSyncByte|IrdaReceiveHeader|IrdaPayLoadLength|IrdaMessage|CRC LSB|CRC MSB
private const Int32 IrdaProtocolFrameLength = 6; private const Int32 IrdaProtocolFrameLength = 6;
@@ -49,7 +53,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
//private const Int32 DefaultResponseTimeoutMs = 50; //private const Int32 DefaultResponseTimeoutMs = 50;
private const Int32 DefaultResponseTimeoutMs = 150; private const Int32 DefaultResponseTimeoutMs = 150;
private Int32 _responseTimeoutMs = DefaultResponseTimeoutMs; private Int32 _responseTimeoutMs = DefaultResponseTimeoutMs;
private const UInt32 BaudRate = 115200; private const UInt32 BaudRate = 115200;
private readonly UInt32? _receiveBufferFlushThreshold = 1; private readonly UInt32? _receiveBufferFlushThreshold = 1;
@@ -65,7 +69,7 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
_responseTimeoutMs = DefaultResponseTimeoutMs; _responseTimeoutMs = DefaultResponseTimeoutMs;
} }
/// <inheritdoc /> /// <inheritdoc />
public IrdaTransmitProtocol(String portName) : base (portName) public IrdaTransmitProtocol(String portName) : base(portName)
{ {
} }
@@ -84,6 +88,9 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
/// <remarks date="2020-Dec-19" author="T.Wiedebusch"> /// <remarks date="2020-Dec-19" author="T.Wiedebusch">
/// - Removed IrdaMessage identifier check as it was observed receiving a 0x03 or a 0x04 in this field. /// - Removed IrdaMessage identifier check as it was observed receiving a 0x03 or a 0x04 in this field.
/// </remarks> /// </remarks>
/// <remarks date="2022-Jul-15" author="T.Wiedebusch">
/// - Wakeup message detection reported to log-file.
/// </remarks>
public override List<Byte> DecodeDataForLogicLayer(List<Byte> irdaRecord) public override List<Byte> DecodeDataForLogicLayer(List<Byte> irdaRecord)
{ {
Logger.Info($"DecodeDataForPhysicalLayer Cordonel->PC({BitConverter.ToString(irdaRecord.ToArray())})"); Logger.Info($"DecodeDataForPhysicalLayer Cordonel->PC({BitConverter.ToString(irdaRecord.ToArray())})");
@@ -92,11 +99,27 @@ namespace Xylem.Common.Hardware.Interfaces.Protocols.TransmitProtocol
if (irdaRecord.Count < IrdaProtocolFrameLength + irdaRecord[IrdaPayLoadLengthIndex] if (irdaRecord.Count < IrdaProtocolFrameLength + irdaRecord[IrdaPayLoadLengthIndex]
|| irdaRecord[IrdaSyncByteIndex] != IrdaSyncByte || irdaRecord[IrdaSyncByteIndex] != IrdaSyncByte
|| (irdaRecord[IrdaHeaderIndex] & IrdaReceiveHeaderMask) != (IrdaReceiveHeader & IrdaReceiveHeaderMask) || (irdaRecord[IrdaHeaderIndex] & IrdaReceiveHeaderMask) != (IrdaReceiveHeader & IrdaReceiveHeaderMask)
|| irdaRecord[IrdaMessageIndex] != IrdaMessage ) || irdaRecord[IrdaMessageIndex] != IrdaMessage)
{ {
var error = new ApplicationException("Reply format from IrDA is invalid. Decoding of transmit layer failed."); var wakeUp = true;
for (var i = 0; i < IrdaWakeupMessage.Length; i++)
{
if (irdaRecord[i] != IrdaWakeupMessage[i])
wakeUp = false;
}
if (wakeUp)
{
var error = new ApplicationException(
"Wakeup message from IrDA received. Retry of last message required.");
Logger.Error(error.Message, error);
}
else
{
var error = new ApplicationException(
"Reply format from IrDA is invalid. Decoding of transmit layer failed.");
Logger.Error(error.Message, error);
}
Logger.Error(error.Message, error);
return new List<Byte>(); return new List<Byte>();
} }
@@ -2158,7 +2158,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
while (retryLeft > 0 && !done) while (retryLeft > 0 && !done)
{ {
Thread.Sleep(100); Thread.Sleep(50);
var result = WriteRegister(a.Key.GetIdent(), 1); var result = WriteRegister(a.Key.GetIdent(), 1);
if (!result) if (!result)
{ {
@@ -2173,7 +2173,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
} }
// Wait for storing // Wait for storing
Thread.Sleep(500); Thread.Sleep(400);
if (a.Key.AppName == "SENSUSRADIO") if (a.Key.AppName == "SENSUSRADIO")
{ {
done = true; done = true;
@@ -330,6 +330,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
/// <remarks date="2019-Jan-22" author="T.Wiedebusch"> /// <remarks date="2019-Jan-22" author="T.Wiedebusch">
/// - Avoid activation of wakeup retry if record is meanwhile acknowledged. /// - Avoid activation of wakeup retry if record is meanwhile acknowledged.
/// </remarks> /// </remarks>
/// <remarks date="2022-Jul-15" author="T.Wiedebusch">
/// - Additional delay before retry.
/// </remarks>
public override void DecodeRecord(IPortDataEventArgs data) public override void DecodeRecord(IPortDataEventArgs data)
{ {
//the request response record covers the entire request protocol //the request response record covers the entire request protocol
@@ -348,6 +351,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol
_logger.Debug($"{_ident} WakeupMessageRetry(1)"); _logger.Debug($"{_ident} WakeupMessageRetry(1)");
_recordInProcess.WakeupMessageRetryCtr = 1; _recordInProcess.WakeupMessageRetryCtr = 1;
_recordInProcess.RetryCtr--; _recordInProcess.RetryCtr--;
Thread.Sleep(10);
} }
} }
@@ -1 +1 @@
46bd00889699f5a20a4981a22f62b66368323855 1a3d4919c9c702245832d925951f2b7cb72fc333
@@ -1 +1 @@
a50e8e35fe346dde3daa1dd9af1217ba2785aa48 f64d563def603c89cafafa61a3219ba97e1e344c