public static async Task <FrameHeader> ReadHeader(this IDuplexStream stream, CancellationToken cancellationToken = default) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } return((FrameHeader)(await stream.Read(1, cancellationToken)).Single()); }
private async Task <DataFrame> ReadDataFrame(CancellationToken cancellationToken = default) { // INS12350-Serial-API-Host-Appl.-Prg.-Guide | 6.2.1 Data frame reception timeout // A receiving host or Z-Wave chip MUST abort reception of a Data frame if the reception has lasted for // more than 1500ms after the reception of the SOF byte. using (var timeoutCancelation = new CancellationTokenSource(ProtocolSettings.DataFrameWaitTime)) { // combine the passed and the timeout cancelationtokens using (var linkedCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCancelation.Token)) { // read the length var length = await Stream.ReadByte(linkedCancellation.Token); // read data (payload and checksum) var data = await Stream.Read(length, linkedCancellation.Token); // payload (data without checksum) var payload = data.Take(data.Length - 1).ToArray(); // checksum var actualChecksum = data.Last(); // calculate required checksum (include length) var expectedChecksum = new byte[] { length }.Concat(payload).CalculateLrc8Checksum(); // validate checksum if (actualChecksum != expectedChecksum) { throw new ChecksumException("Checksum failure"); } // return dataframe return(new DataFrame((DataFrameType)payload[0], new Payload(payload.Skip(1)))); } } }