예제 #1
0
        /// <inheritdoc />
        public override int Serialize(INTV.Core.Utility.BinaryWriter writer)
        {
            var protocolCommandBuffer = new byte[CommandRecordSize + ArgumentRecordSize];

            // The try/finally pattern avoids potential double-dispose issues with the memory stream.
            System.IO.MemoryStream commandWithArgsStream = null;
            try
            {
                commandWithArgsStream = new System.IO.MemoryStream(protocolCommandBuffer);
                using (var tempBinaryWriter = new INTV.Shared.Utility.ASCIIBinaryWriter(commandWithArgsStream))
                {
                    commandWithArgsStream = null;
                    tempBinaryWriter.Write(CommandRecordHeadByte);
                    tempBinaryWriter.Write((byte)Command);
                    tempBinaryWriter.Write((byte)(((int)Command) ^ 0xFF));
                    tempBinaryWriter.Write(CommandRecordTailByte);
                    tempBinaryWriter.Write(Arg0);
                    tempBinaryWriter.Write(Arg1);
                    tempBinaryWriter.Write(Arg2);
                    tempBinaryWriter.Write(Arg3);
                    tempBinaryWriter.Seek(0, SeekOrigin.Begin);
                    Crc = INTV.Core.Utility.Crc32.OfStream(tempBinaryWriter.BaseStream);
                    writer.Write(protocolCommandBuffer, 0, protocolCommandBuffer.Length);
#if LOG_COMMAND_DATA
                    var dataSent = new System.Text.StringBuilder();
                    foreach (var value in protocolCommandBuffer)
                    {
                        dataSent.AppendFormat("{0} ", value.ToString("X2"));
                    }
                    dataSent.AppendFormat("CRC: {0}", Crc.ToString("X8"));
                    _dataSent = dataSent.ToString();
#endif // LOG_COMMAND_DATA
                }
            }
            finally
            {
                if (commandWithArgsStream != null)
                {
                    commandWithArgsStream.Dispose();
                }
            }
            writer.Write(Crc);

            return(ProtocolCommandRecordSize);
        }
예제 #2
0
        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);
        }