/// <summary> /// Gets the size of the incoming <see cref="Quaternion"/> array. /// </summary> /// <param name="serialPort">The communication port.</param> /// <param name="cancellationToken">Optional cancel token.</param> /// <returns>Awaitable byte future.</returns> protected virtual async Task <byte> GetQuaternionCountAsync(ICommunicationPort serialPort, CancellationToken cancellationToken) { await serialPort.ReadAsync(SingleByteBuffer, 0, 1, cancellationToken); byte quaternionCount = SingleByteBuffer[0]; return(quaternionCount); }
/// <inheritdoc /> public async Task <RecyclableArraySegment <Quaternion> > ReadMessageAsync(ICommunicationPort serialPort, CancellationToken cancellationToken = default(CancellationToken)) { byte quaternionCount = await GetQuaternionCountAsync(serialPort, cancellationToken); if (quaternionCount == 0) { return(RecyclableArraySegment <Quaternion> .Empty); } //Now we should read the quats based on the provided count var quatArray = ArrayPool <Quaternion> .Shared.Rent(quaternionCount); try { for (int i = 0; i < quaternionCount && !cancellationToken.IsCancellationRequested; i++) { await serialPort.ReadAsync(SingleQuatBuffer, 0, SingleQuatBuffer.Length, cancellationToken); //Just return whatever we have if cancelled. if (cancellationToken.IsCancellationRequested) { return(new RecyclableArraySegment <Quaternion>(quatArray, 0, quaternionCount)); } //quatArray[i] = new Quaternion(GetFloatFromQuatBuffer(1), GetFloatFromQuatBuffer(2), GetFloatFromQuatBuffer(3), GetFloatFromQuatBuffer(0)); quatArray[i] = new Quaternion(GetFloatFromQuatBuffer(0), GetFloatFromQuatBuffer(1), GetFloatFromQuatBuffer(2), GetFloatFromQuatBuffer(3)); if (GlardunioStaticConfig.DebugLogging) { Debug.Log($"Quat log: {quatArray[i].x} {quatArray[i].y} {quatArray[i].z} {quatArray[i].w}"); } } return(new RecyclableArraySegment <Quaternion>(quatArray, 0, quaternionCount)); } catch (Exception e) { throw; } finally { //If exceptions happen let's dipose of the array ArrayPool <Quaternion> .Shared.Return(quatArray); } }
/// <summary> /// Read a line from the SerialPort asynchronously /// </summary> /// <param name="serialPort">The port to read data from</param> /// <returns>A line read from the input</returns> public static async Task <string> ReadLineAsync(this ICommunicationPort serialPort) { if (!serialPort.Encoding.IsSingleByte) { throw new InvalidOperationException($"TODO: Cannot support {serialPort.Encoding.EncodingName}. Only supports 1 byte ASCII right now."); } int charSizeCount = serialPort.Encoding.IsSingleByte ? 1 : serialPort.Encoding.GetMaxByteCount(1); byte[] _singleCharBuffer = ArrayPool <byte> .Shared.Rent(charSizeCount); StringBuilder builder = new StringBuilder(); try { // Read the input one byte at a time, convert the // byte into a char, add that char to the overall // response string, once the response string ends // with the line ending then stop reading while (true) { await serialPort.ReadAsync(_singleCharBuffer, 0, 1) .ConfigureAwait(false); builder.Append((char)_singleCharBuffer[0]); if (builder[builder.Length - 1] == DefaultNewLine) { // Truncate the line ending return(builder.ToString(0, builder.Length - 1)); } } } catch (Exception e) { throw; } finally { ArrayPool <byte> .Shared.Return(_singleCharBuffer, true); } }
/// <inheritdoc /> public async Task <int> ReadMessageAsync(ICommunicationPort serialPort, CancellationToken cancellationToken = default(CancellationToken)) { await serialPort.ReadAsync(IntBuffer, 0, sizeof(int), cancellationToken); return(Unsafe.ReadUnaligned <int>(ref IntBuffer[0])); }