示例#1
0
        /// <summary>
        /// Send a command and wait for a reply
        /// </summary>
        /// <param name="sequence">The command sequence, typically starting with <see cref="FirmataCommand.START_SYSEX"/> and ending with <see cref="FirmataCommand.END_SYSEX"/></param>
        /// <param name="timeout">A non-default timeout</param>
        /// <returns>The raw sequence of sysex reply bytes. The reply does not include the START_SYSEX byte, but it does include the terminating END_SYSEX byte. The first byte is the
        /// <see cref="FirmataSysexCommand"/> command number of the corresponding request</returns>
        public List <byte> SendCommandAndWait(FirmataCommandSequence sequence, TimeSpan timeout)
        {
            if (!sequence.Validate())
            {
                throw new ArgumentException("The command sequence is invalid", nameof(sequence));
            }

            lock (_synchronisationLock)
            {
                if (_firmataStream == null)
                {
                    throw new ObjectDisposedException(nameof(FirmataDevice));
                }

                _dataReceived.Reset();
                // Use an explicit iteration, avoids a memory allocation here
                for (int i = 0; i < sequence.Sequence.Count; i++)
                {
                    _firmataStream.WriteByte(sequence.Sequence[i]);
                }

                _firmataStream.Flush();
                bool result = _dataReceived.WaitOne(timeout);
                if (result == false)
                {
                    throw new TimeoutException("Timeout waiting for command answer");
                }

                return(new List <byte>(_lastResponse));
            }
        }
示例#2
0
        /// <summary>
        /// Send a command to the device, expecting a reply.
        /// </summary>
        /// <param name="commandSequence">Command to send. This
        /// should normally be a sysex command.</param>
        /// <param name="timeout">Command timeout</param>
        /// <exception cref="TimeoutException">The timeout elapsed before a reply was received.</exception>
        /// <returns>The reply packet</returns>
        protected byte[] SendCommandAndWait(FirmataCommandSequence commandSequence, TimeSpan timeout)
        {
            if (_firmata == null)
            {
                throw new InvalidOperationException("Command handler not registered");
            }

            return(_firmata.SendCommandAndWait(commandSequence, timeout));
        }
示例#3
0
        /// <summary>
        /// Sends a command to the device, not expecting an answer.
        /// </summary>
        /// <param name="commandSequence">A command sequence. This
        /// should normally be a sysex command.</param>
        protected void SendCommand(FirmataCommandSequence commandSequence)
        {
            if (_firmata == null)
            {
                throw new InvalidOperationException("Command handler not registered");
            }

            _firmata.SendCommand(commandSequence);
        }
示例#4
0
        private (int TimeStamp, int NewTicks, bool Success) DecodeFrequencyReport(Span <byte> reply)
        {
            if (reply.Length < 13 || reply[0] != (byte)FirmataSysexCommand.FREQUENCY_COMMAND)
            {
                // Logger.LogError("Frequency sensor extension: Incorrect answer received");
                return(0, 0, false);
            }

            int timestamp = (int)FirmataCommandSequence.DecodeUInt32(reply, 3);
            int ticks     = (int)FirmataCommandSequence.DecodeUInt32(reply, 8);

            return(timestamp, ticks, true);
        }
示例#5
0
        /// <summary>
        /// Send a command that does not generate a reply.
        /// This method must only be used for commands that do not generate a reply. It must not be used if only the caller is not
        /// interested in the answer.
        /// </summary>
        /// <param name="sequence">The command sequence to send</param>
        /// <param name="timeout">A non-default timeout</param>
        public void SendCommand(FirmataCommandSequence sequence, TimeSpan timeout)
        {
            if (!sequence.Validate())
            {
                throw new ArgumentException("The command sequence is invalid", nameof(sequence));
            }

            lock (_synchronisationLock)
            {
                if (_firmataStream == null)
                {
                    throw new ObjectDisposedException(nameof(FirmataDevice));
                }

                // Use an explicit iteration, avoids a memory allocation here
                for (int i = 0; i < sequence.Sequence.Count; i++)
                {
                    _firmataStream.WriteByte(sequence.Sequence[i]);
                }

                _firmataStream.Flush();
            }
        }
示例#6
0
 /// <summary>
 /// Send a command to the device, expecting a reply. This uses a default timeout.
 /// </summary>
 /// <param name="commandSequence">Command to send. This
 /// should normally be a sysex command.</param>
 /// <exception cref="TimeoutException">The timeout elapsed before a reply was received.</exception>
 /// <returns>The reply packet</returns>
 protected byte[] SendCommandAndWait(FirmataCommandSequence commandSequence)
 {
     return(SendCommandAndWait(commandSequence, FirmataDevice.DefaultReplyTimeout));
 }
示例#7
0
 /// <summary>
 /// Callback function that returns whether the given reply indicates an error
 /// </summary>
 /// <param name="sequence">The original sequence</param>
 /// <param name="reply">The reply. <see cref="IsMatchingAck"/> is already tested to be true for this reply</param>
 /// <returns>A command error code, in case this reply indicates a no-acknowledge</returns>
 protected virtual CommandError HasCommandError(FirmataCommandSequence sequence, byte[] reply) => CommandError.None;
示例#8
0
 /// <summary>
 /// This method is called to check whether the reply is a valid ACK/NOACK for the given command sequence.
 /// Can be used to avoid accepting something as command reply that is completely unrelated (such as an asynchronous callback).
 /// In different words, this should return false if the given reply is not something that is an answer to a synchronous command.
 /// </summary>
 /// <param name="sequence">The sequence that was sent</param>
 /// <param name="reply">The reply</param>
 /// <returns>True if this reply matches the sequence. True is the default, for backwards compatibility</returns>
 protected virtual bool IsMatchingAck(FirmataCommandSequence sequence, byte[] reply) => true;
示例#9
0
 /// <summary>
 /// Send a command to the device, expecting a reply.
 /// </summary>
 /// <param name="commandSequence">Command to send. This
 /// should normally be a sysex command.</param>
 /// <param name="timeout">Command timeout</param>
 /// <exception cref="TimeoutException">The timeout elapsed before a reply was received.</exception>
 /// <returns>The reply packet</returns>
 protected byte[] SendCommandAndWait(FirmataCommandSequence commandSequence, TimeSpan timeout)
 {
     return(SendCommandAndWait(commandSequence, timeout, out _));
 }
示例#10
0
 /// <summary>
 /// Send a command and wait for a reply
 /// </summary>
 /// <param name="sequence">The command sequence, typically starting with <see cref="FirmataCommand.START_SYSEX"/> and ending with <see cref="FirmataCommand.END_SYSEX"/></param>
 /// <returns>The raw sequence of sysex reply bytes. The reply does not include the START_SYSEX byte, but it does include the terminating END_SYSEX byte. The first byte is the
 /// <see cref="FirmataSysexCommand"/> command number of the corresponding request</returns>
 public List <byte> SendCommandAndWait(FirmataCommandSequence sequence)
 {
     return(SendCommandAndWait(sequence, DefaultReplyTimeout));
 }
示例#11
0
 /// <summary>
 /// Send a command that does not generate a reply.
 /// This method must only be used for commands that do not generate a reply. It must not be used if only the caller is not
 /// interested in the answer.
 /// </summary>
 /// <param name="sequence">The command sequence to send</param>
 public void SendCommand(FirmataCommandSequence sequence)
 {
     SendCommand(sequence, DefaultReplyTimeout);
 }
示例#12
0
 /// <summary>
 /// Send a command and wait for a reply
 /// </summary>
 /// <param name="sequence">The command sequence, typically starting with <see cref="FirmataCommand.START_SYSEX"/> and ending with <see cref="FirmataCommand.END_SYSEX"/></param>
 /// <param name="timeout">A non-default timeout</param>
 /// <returns>The raw sequence of sysex reply bytes. The reply does not include the START_SYSEX byte, but it does include the terminating END_SYSEX byte. The first byte is the
 /// <see cref="FirmataSysexCommand"/> command number of the corresponding request</returns>
 public byte[] SendCommandAndWait(FirmataCommandSequence sequence, TimeSpan timeout)
 {
     return(SendCommandAndWait(sequence, timeout, out _));
 }