/// <summary> /// Sends the command to the specified target. The command sends additional data following the initial packet. /// </summary> /// <param name="target">The target to which to send the command.</param> /// <param name="taskData">If non-<c>null</c>, execution data to update for error reporting.</param> /// <param name="sourceDataStream">The stream containing the additional data to send to the target. If this value is null, no additional data needs to be sent.</param> /// <param name="onSuccess">Action to execute upon successful command completion.</param> /// <returns><c>true</c> if the command and its data were successfully sent, <c>false</c> otherwise.</returns> protected bool ExecuteCommandWithData(IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, System.IO.Stream sourceDataStream, Action onSuccess) { bool succeeded = false; ExecuteCore <bool>(target, taskData, sourceDataStream, null, onSuccess, out succeeded); return(succeeded); }
/// <inheritdoc /> public override object Execute(INTV.Shared.Model.IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { var errorLog = ExecuteWithResponse <ErrorLog>(target, taskData, ErrorLog.Inflate, out succeeded); var errorLogText = errorLog == null ? "<null>" : errorLog.ToString(); target.LogPortMessage("ERROR LOG: '" + (errorLog == null ? "<null>" : errorLogText) + "'"); return(errorLog); }
/// <inheritdoc /> public override object Execute(INTV.Shared.Model.IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { using (var data = FileUtilities.OpenFileStream(File.FileInfo.FullName)) { succeeded = ExecuteCommandWithData(target, taskData, data, () => taskData.Device.ConnectionState = ConnectionState.WaitForBeacon); } return(succeeded); }
/// <summary> /// Sends the command to the specified target. /// </summary> /// <typeparam name="T">The data type of the response data from the command.</typeparam> /// <param name="target">The target to which to send the command.</param> /// <param name="taskData">If non-<c>null</c>, execution data to update for error reporting.</param> /// <returns>The data returned by the command. In the case of commands that do not send additional results, this will be the same as the succeeded result.</returns> public T Execute <T>(IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData) { bool succeeded = false; var result = (T)Execute(target, taskData, out succeeded); if (!succeeded) { throw new InvalidOperationException(string.Format(Resources.Strings.DeviceCommandFailed_SimpleFormat, Command), taskData.Error); } return(result); }
/// <inheritdoc /> public override object Execute(INTV.Shared.Model.IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { using (var data = new System.IO.MemoryStream()) { Data.Serialize(new INTV.Shared.Utility.ASCIIBinaryWriter(data)); data.Seek(0, System.IO.SeekOrigin.Begin); RunningCrc24 = INTV.Core.Utility.Crc24.OfStream(data, RunningCrc24); data.Seek(0, System.IO.SeekOrigin.Begin); succeeded = ExecuteCommandWithData(target, taskData, data, null); } return(succeeded); }
/// <summary> /// Helper method to execute emulate hardware status bits changing when attached to the Locutus simulator. /// </summary> /// <param name="device">The device to send the command to.</param> /// <param name="flags">The hardware status flags to assign to the simulator.</param> internal static void SetHardwareStatus(Device device, HardwareStatusFlags flags) { if (!device.IsCommandInProgress) { var executeCommandTaskData = new ExecuteDeviceCommandAsyncTaskData(device, INTV.LtoFlash.Model.Commands.ProtocolCommandId.DebugSetHardwareStatus) { Data = flags, OnFailure = (m, e) => { INTV.Shared.View.OSMessageBox.Show(m, "Toggle Power Command", SingleInstanceApplication.SharedSettings.ShowDetailedErrors ? e : null, null); return(true); } }; executeCommandTaskData.StartTask(SetHardwareStatus); } }
/// <inheritdoc /> public override object Execute(INTV.Shared.Model.IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { return(ExecuteWithResponse(target, taskData, Inflate, out succeeded)); }
/// <inheritdoc /> public override object Execute(INTV.Shared.Model.IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { var crashLog = ExecuteWithResponse <CrashLog>(target, taskData, CrashLog.Inflate, out succeeded); return(crashLog); }
/// <inheritdoc /> public override object Execute(INTV.Shared.Model.IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { return(ExecuteWithResponse <byte[]>(target, taskData, (s) => ((System.IO.MemoryStream)s).ToArray(), out succeeded)); }
private T ExecuteCore <T>(IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, System.IO.Stream sourceDataStream, Func <System.IO.Stream, T> inflate, Action onSuccess, out bool succeeded) { succeeded = false; var errorDetail = string.Empty; var response = default(T); var timedOut = false; #if REPORT_COMMAND_PERFORMANCE var stopwatch = System.Diagnostics.Stopwatch.StartNew(); var reportSuffix = sourceDataStream == null ? "RESP" : "DATA"; try { #endif // REPORT_COMMAND_PERFORMANCE using (target.SetInUse(UpdatePortChunkSizeConfigurations)) { if (taskData != null) { taskData.CurrentlyExecutingCommand = Command; } lock (_lock) { target.LogPortMessage("EXECUTE: " + Command); Exception exception = null; var previousWriteTimeout = -1; if (target.WriteStream.CanTimeout) { previousWriteTimeout = target.WriteStream.WriteTimeout; } try { using (var writer = new INTV.Shared.Utility.ASCIIBinaryWriter(target.WriteStream)) { _dataSent = string.Empty; var commandBytesWritten = Serialize(writer); target.LogPortMessage("EXECUTE: wrote " + commandBytesWritten + " bytes for command: " + Command + ", data sent: " + _dataSent); } if (target.ReadStream.CanTimeout) { target.ReadStream.ReadTimeout = ResponseTimeout; } using (var reader = new INTV.Shared.Utility.ASCIIBinaryReader(target.ReadStream)) { using (var resultStream = new System.IO.MemoryStream()) { var ack = GetCommandAcknowledgement(reader, Command, ref errorDetail, out timedOut); if (ack == Ack) { resultStream.WriteByte(ack); byte[] responseData = null; if (sourceDataStream != null) { SendCommandPayload(target, sourceDataStream, resultStream); } else if (inflate != null) { responseData = ReceiveResponse(reader, resultStream); } var success = GetCommandSuccess(reader); resultStream.WriteByte(success); var crc = GetResponseCrc(reader); succeeded = ValidateResponse(resultStream, crc); if (succeeded && (responseData != null) && (inflate != null)) { using (var responseStream = new MemoryStream(responseData)) { response = inflate(responseStream); } } if (succeeded && (onSuccess != null)) { onSuccess(); } if (success != Success) { var errorMessage = "Command " + Command + " did not succeed: " + success.ToString("X2") + "(" + System.Convert.ToChar(success) + ")"; if (!string.IsNullOrEmpty(errorDetail)) { errorDetail += Environment.NewLine; } errorDetail += errorMessage; target.LogPortMessage(errorMessage); DebugOutput(errorMessage); timedOut = target.WaitForBeacon(WaitForBeaconTimeout); // try to drain any remaining bytes and sync back up again succeeded = false; exception = new DeviceCommandExecuteFailedException(Command, Arg0, Arg1, Arg2, Arg3, success); } } else if (ack == Nak) { var errorMessage = "Command " + Command + " returned NAK!"; target.LogPortMessage(errorMessage); DebugOutput(errorMessage); timedOut = !target.WaitForBeacon(WaitForBeaconTimeout); if (!string.IsNullOrEmpty(errorDetail)) { errorDetail += Environment.NewLine; } errorDetail += errorMessage; } } } } catch (TimeoutException e) { timedOut = true; var errorMessage = "Timed out executing command: " + Command; target.LogPortMessage(errorMessage); DebugOutput(errorMessage); if (!string.IsNullOrEmpty(errorDetail)) { errorDetail += Environment.NewLine; } errorDetail += errorMessage; exception = e; // TODO: Report specific failure message back to user. } catch (System.IO.IOException e) { var errorMessage = "IO Exception executing command: " + Command; target.LogPortMessage(errorMessage); DebugOutput(errorMessage); if (!string.IsNullOrEmpty(errorDetail)) { errorDetail += Environment.NewLine; } errorDetail += errorMessage; exception = e; // TODO: Report specific failure message back to user. // One circumstance in which this occurs, and which we do not wish to report, is when killing the simulator application. } catch (UnauthorizedAccessException e) { var errorMessage = "UnauthorizedAccess Exception executing command: " + Command; target.LogPortMessage(errorMessage); DebugOutput(errorMessage); if (!string.IsNullOrEmpty(errorDetail)) { errorDetail += Environment.NewLine; } errorDetail += errorMessage; exception = e; // TODO: Report specific failure message back to user. // One circumstance in which this occurs, was after unplugging the device, which we may not want to report. } finally { // target.WriteStream may go to null if cord is pulled during communication w/ the device. if ((target.WriteStream != null) && target.WriteStream.CanTimeout) { target.WriteStream.WriteTimeout = previousWriteTimeout; } if (!succeeded) { RecordErrorResult(Command, exception, taskData, errorDetail); if (exception != null) { throw exception; } } } } if (taskData != null) { taskData.Succeeded = succeeded; } } #if REPORT_COMMAND_PERFORMANCE } finally { stopwatch.Stop(); ReportDuration(stopwatch, reportSuffix, target.Name); } #endif // REPORT_COMMAND_PERFORMANCE return(response); }
private static void RecordErrorResult(ProtocolCommandId command, Exception exception, ExecuteDeviceCommandAsyncTaskData taskData, string errorDetail) { var errorBuilder = new System.Text.StringBuilder(); if (!string.IsNullOrEmpty(errorDetail)) { errorBuilder.AppendLine("Error Detail:").AppendLine(errorDetail); } var failureMessage = command.GetFailureString(); errorBuilder.AppendLine(failureMessage); var errorMessage = errorBuilder.ToString(); DebugOutput(errorMessage); if (taskData != null) { taskData.DeviceExceptionDetail = errorDetail; } }
/// <summary> /// Sends the command to the specified target and reads the response. The command responds with additional data. /// </summary> /// <typeparam name="T">The data type of the response data from the command.</typeparam> /// <param name="target">The target to which to send the command.</param> /// <param name="taskData">If non-<c>null</c>, execution data to update for error reporting.</param> /// <param name="inflate">The function to inflate the flat byte array response to response type.</param> /// <param name="succeeded">Receives whether the command was sent, and response received, successfully.</param> /// <returns>The reply data. If the command fails, this value will be default(T).</returns> protected T ExecuteWithResponse <T>(IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, Func <System.IO.Stream, T> inflate, out bool succeeded) { var response = ExecuteCore(target, taskData, null, inflate, null, out succeeded); return(response); }
/// <summary> /// Sends the command to the specified target. /// </summary> /// <param name="target">The target to which to send the command.</param> /// <param name="taskData">If non-<c>null</c>, execution data to update for error reporting.</param> /// <param name="succeeded">Receives whether the command was sent, and response received, successfully.</param> /// <returns><c>true</c> if the command and its data were successfully sent, <c>false</c> otherwise.</returns> protected bool ExecuteCommand(IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { succeeded = ExecuteCommandWithData(target, taskData, (System.IO.Stream)null, null); return(succeeded); }
/// <summary> /// Sends the command to the specified target. /// </summary> /// <param name="target">The target to which to send the command.</param> /// <param name="taskData">If non-<c>null</c>, execution data to update for error reporting.</param> /// <param name="succeeded">Receives whether the command was sent, and response received, successfully.</param> /// <returns>The data returned by the command. In the case of commands that do not send additional results, this will be the same as the succeeded result.</returns> public virtual object Execute(IStreamConnection target, ExecuteDeviceCommandAsyncTaskData taskData, out bool succeeded) { var result = ExecuteCommand(target, taskData, out succeeded); return(result); }