/// <summary> /// Holds the rules for determining if the Tx.Identify matches the /// Rx.Identify response. The identifyResponse needs to be a /// <c>RxType.IDENTIFY</c>. The Arduino is expected to increment both /// the Random0, and Random1 properties before sending it back. /// </summary> /// <param name="identifyRequest">The request for identification sent /// to the candidate Arduino.</param> /// <param name="identifyResponse">The response for identification sent /// to the candidate Arduino.</param> /// <returns>Whether or not the rules for determining a match are correct.</returns> private static bool IsExpected( APS.Data.Messages.Tx.Identify identifyRequest, APS.Data.RxMessage identifyResponse ) { bool result = false; if (identifyResponse.Type.Equals(RxType.IDENTIFY)) { var conv = (APS.Data.Messages.Rx.Identify)identifyResponse; var random0Match = identifyRequest.Random0.Equals((byte)((conv.Random0 - 1) % 256)); var random1Match = identifyRequest.Random1.Equals((byte)((conv.Random1 - 1) % 256)); result = random0Match && random1Match; } return(result); }
/// <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); }