/// <summary> /// This is used to initialize the last sequence number accepted by /// the Arduino. /// </summary> /// <param name="candidate">The candidate <c>Arduino</c> object to /// perform the initialization.</param> private static void InitializeLastSeqNr(Arduino candidate) { // So we start with a Read in contrast to the Run() method. This // is because we can always expect the Arduino to be sending. If // the program restarts, it will continue to send an ack for its // last received message, or an identify for its last detected // identify. int seqNrAttemptsLeft = NUM_SEQ_NR_ATTEMPTS; bool identifiedSeqNr = false; while (seqNrAttemptsLeft > 0 && !identifiedSeqNr) { try { RxMessage receivedMessage = null; // Read it, until it finds a complete message, or it times out. while (receivedMessage == null) { receivedMessage = candidate.Read(); } // Set the last sent sequence number according to what the // Arduino is sending. candidate.LastSentSeqNr = receivedMessage.Sequence > 0; identifiedSeqNr = true; } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } seqNrAttemptsLeft--; } }
/// <summary> /// Tries to identify the arduino. /// </summary> /// <param name="candidate">The candidate to determine if it is an /// Arduino.</param> /// <returns>Whether or not the candidate was identified as an Arduino. /// </returns> private static bool TryIdentify(Arduino candidate) { // Setup the random numbers we will be sending. var identifyRequest = new APS.Data.Messages.Tx.Identify(); identifyRequest.Random0 = (byte)candidate.Rand.Next(); identifyRequest.Random1 = (byte)candidate.Rand.Next(); // Sets the sequence, so it matches LastSentSeqNr. The // LastSentSeqNr should already be set, so it is correct after a // Write(). identifyRequest.Sequence = (byte)(candidate.LastSentSeqNr ? 1 : 0); // Position the identify request for sending. candidate.NextMessageToSend = identifyRequest; // Set the number of attempts we will allow to write. var numIdAttemptsLeft = NUM_ID_ATTEMPTS; var sent = false; var received = false; candidate.Port.ReadExisting(); // Do this until we run out of attempts, or until both are sent // and received. while (numIdAttemptsLeft > 0 && !(sent && received)) { try { if (numIdAttemptsLeft == NUM_ID_ATTEMPTS) { candidate.Write(); } else { candidate.ReWrite(); // Write it. } sent = true; // Mark that we wrote it. } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } // Set the number of attempts we will allow to read for this // write. var numIdReadAttemptsLeft = NUM_ID_READS_PER_SEND; // Read X times or until we have identified. while (numIdReadAttemptsLeft > 0 && !received) { try { RxMessage receivedMessage = null; while (receivedMessage == null) // Read it, until it finds a complete message. { receivedMessage = candidate.Read(); } // Check to make sure we got the correct sequence number back. var seqNrMatch = receivedMessage.Sequence == 0 && !candidate.LastSentSeqNr || receivedMessage.Sequence == 1 && candidate.LastSentSeqNr; // Make sure the sequence numbers match, and the received // is message matches what is expected. if (seqNrMatch && IsExpected(identifyRequest, receivedMessage)) { received = true; // Mark that we successfully identified. // Changes the last sequence number, so that it // will represent what was last sent after the next Write(). candidate.LastSentSeqNr = !candidate.LastSentSeqNr; } } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } numIdReadAttemptsLeft--; } numIdAttemptsLeft--; } return(sent && received); }