internal ArduinoResponse Send(ArduinoRequest request) { var sendRetries = 0; while (sendRetries++ < MaxSendRetries - 1) { try { // First try to get sync (send FF FE FD FC and require FC FD FE FF as a response). bool hasSync; var syncRetries = 0; while (!(hasSync = GetSync()) && syncRetries++ < MaxSyncRetries - 1) { logger.Debug("Unable to get sync ... trying again ({0}/{1}).", syncRetries, MaxSyncRetries); } if (!hasSync) { var errorMessage = string.Format("Unable to get sync after {0} tries!", MaxSyncRetries); logger.Fatal(errorMessage); throw new IOException(errorMessage); } // Now send the command handshake (send FB as start of message marker + the command byte + length byte). // Expect the inverse (length byte followed by command byte followed by FB) as a command ACK. var requestBytes = request.Bytes.ToArray(); var requestBytesLength = requestBytes.Length; if (!ExecuteCommandHandShake(request.Command, (byte)requestBytesLength)) { var errorMessage = string.Format("Unable to configure command handshake for command {0}.", request); logger.Fatal(errorMessage); throw new IOException(errorMessage); } // Write out all packet bytes, followed by a Fletcher 16 checksum! // Packet bytes consist of: // 1. Command byte repeated // 2. Request length repeated // 3. The actual request bytes // 4. Two fletcher-16 checksum bytes calculated over (1 + 2 + 3) var packetBytes = new byte[requestBytesLength + 4]; packetBytes[0] = request.Command; packetBytes[1] = (byte)requestBytesLength; Buffer.BlockCopy(requestBytes, 0, packetBytes, 2, requestBytesLength); var fletcher16CheckSum = CalculateFletcher16Checksum(packetBytes, requestBytesLength + 2); var f0 = (byte)(fletcher16CheckSum & 0xff); var f1 = (byte)((fletcher16CheckSum >> 8) & 0xff); var c0 = (byte)(0xff - (f0 + f1) % 0xff); var c1 = (byte)(0xff - (f0 + c0) % 0xff); packetBytes[requestBytesLength + 2] = c0; packetBytes[requestBytesLength + 3] = c1; Write(packetBytes, 0, requestBytesLength + 4); // Write out all bytes written marker (FA) Write(new[] { CommandConstants.AllBytesWritten }, 0, 1); // Expect response message to drop to be received in the following form: // F9 (start of response marker) followed by response length numberOfBytesToRead = 2; WaitForBytes(numberOfBytesToRead); var responseBytes = ReadCurrentReceiveBuffer(numberOfBytesToRead); var startOfResponseMarker = responseBytes[0]; var responseLength = responseBytes[1]; if (startOfResponseMarker != CommandConstants.StartOfResponseMarker) { var errorMessage = string.Format("Did not receive start of response marker but {0}!", startOfResponseMarker); logger.Fatal(errorMessage); throw new IOException(errorMessage); } // Read x responsebytes numberOfBytesToRead = responseLength; if (BytesToRead < numberOfBytesToRead) { WaitForBytes(numberOfBytesToRead); } responseBytes = ReadCurrentReceiveBuffer(numberOfBytesToRead); return(ArduinoResponse.Create(responseBytes)); } catch (TimeoutException ex) { logger.Debug(ex, "TimeoutException in Send occurred, retrying ({0}/{1})!", sendRetries, MaxSendRetries); } catch (Exception ex) { logger.Debug(ex, "General exception in Send occurred, retrying ({0}/{1})!", sendRetries, MaxSendRetries); } } return(null); }
internal ArduinoResponse Send(ArduinoRequest request, int maximumSendRetries = maxSendRetries) { var sendRetries = 0; while (sendRetries++ < maximumSendRetries) { try { // First try to get sync (send FF FE FD FC and require FC FD FE FF as a response). bool hasSync; var syncRetries = 0; while (!(hasSync = GetSync()) && syncRetries++ < maxSyncRetries) { } if (!hasSync) { string errorMessage = $"Unable to get sync after {maxSyncRetries} tries!"; throw new IOException(errorMessage); } // Now send the command handshake (send FB as start of message marker + the command byte + length byte). // Expect the inverse (length byte followed by command byte followed by FB) as a command ACK. byte[] requestBytes = request.Bytes.ToArray(); int requestBytesLength = requestBytes.Length; if (!ExecuteCommandHandShake(request.Command, (byte)requestBytesLength)) { string errorMessage = $"Unable to configure command handshake for command {request}."; throw new IOException(errorMessage); } // Write out all packet bytes, followed by a Fletcher 16 checksum! // Packet bytes consist of: // 1. Command byte repeated // 2. Request length repeated // 3. The actual request bytes // 4. Two fletcher-16 checksum bytes calculated over (1 + 2 + 3) var packetBytes = new byte[requestBytesLength + 4]; packetBytes[0] = request.Command; packetBytes[1] = (byte)requestBytesLength; Buffer.BlockCopy(requestBytes, 0, packetBytes, 2, requestBytesLength); ushort fletcher16CheckSum = CalculateFletcher16Checksum(packetBytes, requestBytesLength + 2); var f0 = (byte)(fletcher16CheckSum & 0xff); var f1 = (byte)((fletcher16CheckSum >> 8) & 0xff); var c0 = (byte)(0xff - (f0 + f1) % 0xff); var c1 = (byte)(0xff - (f0 + c0) % 0xff); packetBytes[requestBytesLength + 2] = c0; packetBytes[requestBytesLength + 3] = c1; serialPort.Write(packetBytes, 0, requestBytesLength + 4); // Write out all bytes written marker (FA) serialPort.Write(new[] { CommandConstants.AllBytesWritten }, 0, 1); // Expect response message to drop to be received in the following form: // F9 (start of response marker) followed by response length byte[] responseBytes = ReadCurrentReceiveBuffer(2); byte startOfResponseMarker = responseBytes[0]; byte responseLength = responseBytes[1]; if (startOfResponseMarker != CommandConstants.StartOfResponseMarker) { string errorMessage = $"Did not receive start of response marker but {startOfResponseMarker}!"; throw new IOException(errorMessage); } // Read x responsebytes responseBytes = ReadCurrentReceiveBuffer(responseLength); return(ArduinoResponse.Create(responseBytes)); } catch (Exception) { // ignored } } return(null); }