//========================================================================== // Last stop before transmitting information private void EncodeAndSendPacket(byte[] messageBytes, int messageOffset, int messageSize) { try { // For testing calculate the crc including the sequence number _packetCrc32 = CrcTools.Crc32part(messageBytes, messageSize, 0, _packetCrc32); byte[] encodedBytes = new byte[MeadowDeviceManager.MaxSizeOfXmitPacket]; int encodedToSend = CobsTools.CobsEncoding(messageBytes, messageOffset, messageSize, ref encodedBytes); // Verify COBS - any delimiters left? for (int i = 0; i < encodedToSend; i++) { if (encodedBytes[i] == 0x00) { throw new InvalidProgramException("All zeros should have been removed. " + $"There's one at {i}"); } } // Terminate packet with delimiter so packet boundaries can be found encodedBytes[encodedToSend] = 0; encodedToSend++; try { if (_device.Socket != null) { _device.Socket.Send(encodedBytes, encodedToSend, System.Net.Sockets.SocketFlags.None); } else { if (_device.SerialPort == null) { throw new ArgumentException("SerialPort cannot be null"); } _device.SerialPort.Write(encodedBytes, 0, encodedToSend); } } catch (InvalidOperationException ioe) // Port not opened { Console.WriteLine("Write but port not opened. Exception: {0}", ioe); throw; } catch (ArgumentOutOfRangeException aore) // offset or count don't match buffer { Console.WriteLine("Write buffer, offset and count don't line up. Exception: {0}", aore); throw; } catch (ArgumentException ae) // offset plus count > buffer length { Console.WriteLine("Write offset plus count > buffer length. Exception: {0}", ae); throw; } catch (TimeoutException te) // Took too long to send { Console.WriteLine("Write took too long to send. Exception: {0}", te); throw; } } catch (Exception except) { Debug.WriteLine($"EncodeAndSendPacket threw: {except}"); throw; } }
HcomBufferReturn PullAndProcessAllPackets() { byte[] packetBuffer = new byte[MeadowDeviceManager.MaxSizeOfPacketBuffer]; byte[] decodedBuffer = new byte[MeadowDeviceManager.MaxAllowableDataBlock]; int packetLength; HcomBufferReturn result; while (true) { result = _hostCommBuffer.GetNextPacket(packetBuffer, MeadowDeviceManager.MaxAllowableDataBlock, out packetLength); if (result == HcomBufferReturn.HCOM_CIR_BUF_GET_NONE_FOUND) { break; // We've emptied buffer of all messages } if (result == HcomBufferReturn.HCOM_CIR_BUF_GET_BUF_NO_ROOM) { // The buffer to receive the message is too small! Perhaps // corrupted data in buffer. // I don't know why but without the following 2 lines the Debug.Assert will // assert eventhough the following line is not executed? Console.WriteLine($"Need a buffer with {packetLength} bytes, not {MeadowDeviceManager.MaxSizeOfPacketBuffer}"); Thread.Sleep(1); Debug.Assert(false); } // Only other possible outcome is success Debug.Assert(result == HcomBufferReturn.HCOM_CIR_BUF_GET_FOUND_MSG); // It's possible that we may find a series of 0x00 values in the buffer. // This is because when the sender is blocked (because this code isn't // running) it will attempt to send a single 0x00 before the full message. // This allows it to test for a connection. When the connection is // unblocked this 0x00 is sent and gets put into the buffer along with // any others that were queued along the usb serial pipe line. if (packetLength == 1) { //ConsoleOut("Throwing out 0x00 from buffer"); continue; } int decodedSize = CobsTools.CobsDecoding(packetBuffer, --packetLength, ref decodedBuffer); // If a message is too short it is ignored if (decodedSize < MeadowDeviceManager.ProtocolHeaderSize) { continue; } Debug.Assert(decodedSize <= MeadowDeviceManager.MaxAllowableDataBlock); // Process the received packet if (decodedSize > 0) { bool procResult = ParseAndProcessReceivedPacket(decodedBuffer, decodedSize); if (procResult) { continue; // See if there's another packet ready } } break; // processing errors exit } return(result); }