Files
DP44/DataPRO/SLICECommands/DownloadCommands/GetNextDownloadStreamDataSamples.cs
2026-04-17 14:55:32 -04:00

189 lines
8.2 KiB
C#

using System;
using System.Text;
using DTS.Common.Enums.Communication;
using DTS.Common.Enums.DASFactory;
using DTS.Common.ICommunication;
using DTS.Common.Utilities;
namespace DTS.DASLib.Command.SLICE.DownloadCommands
{
/// <summary>
/// This was ported from FirmwareTestUtility where it was written by Loc Pham
/// it is being included for
/// 10573 implement SW side of single command/streaming download
/// this command can be used to collect data that has been collecting in a buffer
/// from download streaming
/// </summary>
public class GetNextDownloadStreamDataSamples : EventDataCommands
{
protected override Commands Command => Commands.GetNextDownloadStreamDataSamples;
public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock)
: base(sock)
{
baseCommand = new CommandPacket();
LogCommands = false;
baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples");
}
public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout)
: base(sock, msTimeout)
{
baseCommand = new CommandPacket();
LogCommands = false;
baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples");
}
public DownloadByteConverter DlData { get; private set; }
private ushort _lastSequenceProcessed = ushort.MaxValue;
private const int MAX_SEQUENCE_DIFF = 1000;
public void ProcessData()
{
var bytes = baseResponse.ToBytes();
var headerCrc = response.HeaderCRC;
response.ComputeCRCs();
if (headerCrc != response.HeaderCRC)
{
DlData = null;
return;
}
DlData = new DownloadByteConverter(bytes);
if (null == DlData) { return; }
if (_lastSequenceProcessed == DlData.SeqNumber)
{
DlData = null;
return;
}
var delta = Math.Abs(DlData.SeqNumber - _lastSequenceProcessed);
if (delta > MAX_SEQUENCE_DIFF && ushort.MaxValue != _lastSequenceProcessed && 0 != DlData.SeqNumber)
{
//per loc we shouldn't get here, the old code in the FWTU would apparently unintentionally throw an exception
//I've preserved that code in comments below
throw new Exception("sequence number overflow");
//DlData = null;
//_lastSequenceProcessed = DlData.SeqNumber;
//return;
}
_lastSequenceProcessed = DlData.SeqNumber;
}
/// <summary>
/// We need to override SyncExecute because we don't want to send anything (that would tell the G5 to stop sending). Instead we just want to
/// read whatever is out there. Otherwise this is mostly cut and paste of normal SyncExecute with some streamlining for our specific case.
/// </summary>
public override void SyncExecute()
{
// this is a try/finally to handle the ExecuteIsBusy
try
{
DlData = null;
// there can be only one!
recorder.ExecuteIsBusy = true;
if (recorder.IsCanceled())
{
throw new CanceledException();
}
UserCallback = null;
UserCallbackData = null;
IsSynchronous = true;
SyncEvent.Reset();
recorder.PseudoExecute(new byte[0], ExecuteCallback, null, IO_Timeout);
var syncExecTimeout = IO_Timeout;
try
{
if (!WaitWithCondition.Wait(SyncEvent, syncExecTimeout,
recorder.CancelEvent))
{
//timeout
LogString("SyncExecute: timeout");
throw new TimeoutException(MakeLogString("SyncExecute: timeout"));
}
}
catch (WaitWithCondition.ConditionMetException)
{
throw new CanceledException();
}
// we didn't timeout, check the result
switch (ComReport.Result)
{
case CommunicationConstantsAndEnums.CommunicationResult.Canceled:
throw new CanceledException();
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveOK:
if (baseResponse == null)
{
LogString("SyncExecute: ReceiveOK but response==null!");
LogCommand(false);
}
else if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
{
// didn't go well
var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status);
LogCommand(false);
switch (baseResponse.Status)
{
case DFConstantsAndEnums.CommandStatus.StatusInvalidModeForCommand:
throw new CommandException(CommandErrorReason.InvalidMode, msg);
case DFConstantsAndEnums.CommandStatus.StatusUnimplemented:
case DFConstantsAndEnums.CommandStatus.StatusInvalidCommand:
case DFConstantsAndEnums.CommandStatus.StatusInvalidCommandType:
throw new NotImplementedException(msg);
}
var ex = new Exception(msg);
ex.Data.Add("Status", baseResponse.Status);
throw ex;
}
// everything is fine, let it exit
if (LogCommands)
{
LogCommand(false);
}
break;
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveFailed:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.ReceiveFailed, msg);
}
case CommunicationConstantsAndEnums.CommunicationResult.SendFailed:
case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout:
{
var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new CommandException(CommandErrorReason.SendFailed, msg);
}
default:
{
var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result);
LogCommand(false);
throw new Exception(msg);
}
}
}
finally
{
recorder.ExecuteIsBusy = false;
}
}
}
}