private MAVLinkMessage ReadLog() { byte[] datearray = new byte[8]; bool missingtimestamp = false; if (logplaybackfile.BaseStream is FileStream) { if (!streamfncache.ContainsKey(_logplaybackfile.BaseStream)) { streamfncache[_logplaybackfile.BaseStream] = new Tuple <string, long>(((FileStream)_logplaybackfile.BaseStream).Name.ToLower(), logplaybackfile.BaseStream.Length); } if (streamfncache[_logplaybackfile.BaseStream].Item1.EndsWith(".rlog")) { missingtimestamp = true; } } else { if (!streamfncache.ContainsKey(_logplaybackfile.BaseStream)) { streamfncache[_logplaybackfile.BaseStream] = new Tuple <string, long>("", logplaybackfile.BaseStream.Length); } } if (!missingtimestamp) { int tem = logplaybackfile.BaseStream.Read(datearray, 0, datearray.Length); Array.Reverse(datearray); DateTime date1 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); UInt64 dateint = BitConverter.ToUInt64(datearray, 0); try { // array is reversed above if (datearray[7] == 254 || datearray[7] == 253) { //rewind 8bytes logplaybackfile.BaseStream.Seek(-8, SeekOrigin.Current); } else { if ((dateint / 1000 / 1000 / 60 / 60) < 9999999) { date1 = date1.AddMilliseconds(dateint / 1000); lastlogread = date1.ToLocalTime(); } } } catch { } } byte[] temp = new byte[0]; byte byte0 = 0; byte byte1 = 0; byte byte2 = 0; var filelength = streamfncache[_logplaybackfile.BaseStream].Item2; var filepos = logplaybackfile.BaseStream.Position; if (filelength == filepos) { return(MAVLinkMessage.Invalid); } int length = 5; int a = 0; while (a < length) { if (filelength == filepos) { return(MAVLinkMessage.Invalid); } var tempb = (byte)logplaybackfile.ReadByte(); filepos++; switch (a) { case 0: byte0 = tempb; if (byte0 != 'U' && byte0 != GlobalAppData.MAVLINK_STX_MAVLINK1 && byte0 != GlobalAppData.MAVLINK_STX) { // seek to next valid do { byte0 = logplaybackfile.ReadByte(); }while (byte0 != 'U' && byte0 != GlobalAppData.MAVLINK_STX_MAVLINK1 && byte0 != GlobalAppData.MAVLINK_STX); a = 1; continue; } break; case 1: byte1 = tempb; // handle length { int headerlength = byte0 == GlobalAppData.MAVLINK_STX ? 9 : 5; int headerlengthstx = headerlength + 1; length = byte1 + headerlengthstx + 2; // header + 2 checksum } break; case 2: byte2 = tempb; // handle signing and mavlink2 if (byte0 == GlobalAppData.MAVLINK_STX) { if ((byte2 & GlobalAppData.MAVLINK_IFLAG_SIGNED) > 0) { length += GlobalAppData.MAVLINK_SIGNATURE_BLOCK_LEN; } } // handle rest { temp = new byte[length]; temp[0] = byte0; temp[1] = byte1; temp[2] = byte2; var readto = a + 1; var readlength = length - (a + 1); logplaybackfile.Read(temp, readto, readlength); a = length; } break; } a++; } MAVLinkMessage tmp = new MAVLinkMessage(temp, lastlogread); //MAVlist[tmp.sysid, tmp.compid].cs.datetime = lastlogread; return(tmp); }
/// <summary> /// Print entire decoded packet to console /// </summary> /// <param name="datin">packet byte array</param> /// <returns>struct of data</returns> public object DebugPacket(MAVLinkMessage datin, ref string text, bool PrintToConsole, string delimeter = " ") { string textoutput = ""; try { if (datin.Length > 5) { textoutput = string.Format( "{0,2:X}{8}{1,2:X}{8}{2,2:X}{8}{3,2:X}{8}{4,2:X}{8}{5,2:X}{8}{6,2:X}{8}{7,6:X}{8}", datin.header, datin.payloadlength, datin.incompat_flags, datin.compat_flags, datin.seq, datin.sysid, datin.compid, datin.msgid, delimeter); object data = datin.data; Type test = data.GetType(); { textoutput = textoutput + test.Name + delimeter; foreach (var field in test.GetFields()) { // field.Name has the field's name. object fieldValue = field.GetValue(data); // Get value if (field.FieldType.IsArray) { textoutput = textoutput + field.Name + delimeter; if (fieldValue.GetType() == typeof(byte[])) { try { byte[] crap = (byte[])fieldValue; foreach (byte fiel in crap) { if (fiel == 0) { break; } else { textoutput = textoutput + (char)fiel; } } } catch { } } if (fieldValue.GetType() == typeof(short[])) { try { short[] crap = (short[])fieldValue; foreach (short fiel in crap) { if (fiel == 0) { break; } else { textoutput = textoutput + Convert.ToString(fiel, 16) + "|"; } } } catch { } } textoutput = textoutput + delimeter; } else { textoutput = textoutput + field.Name + delimeter + fieldValue.ToString() + delimeter; } } var sig = ""; if (datin.sig != null) { sig = Convert.ToBase64String(datin.sig); } textoutput = textoutput + delimeter + "sig " + sig + delimeter + "Len" + delimeter + datin.Length + "\r\n"; if (PrintToConsole) { Console.Write(textoutput); } if (text != null) { text = textoutput; } } return(data); } } catch { textoutput = textoutput + "\r\n"; } return(null); }
public MAVLinkMessage ReadPacket() { byte[] buffer = new byte[GlobalAppData.MAX_PACKET_LEN + 25]; int count = 0; int length = 0; int readcount = 0; MAVLinkMessage message = null; DateTime start = DateTime.Now; lock (readlock) { while ((BaseStream != null && BaseStream.IsOpen) || logreadmode) { try { if (readcount > 300) { break; } readcount++; if (logreadmode) { message = ReadLog(); buffer = message.buffer; if (buffer == null || buffer.Length == 0) { return(MAVLinkMessage.Invalid); } } else { if (BaseStream.ReadTimeout != 1200) { BaseStream.ReadTimeout = 1200; // 1200 ms between chars - the gps detection requires this. } DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout); while (BaseStream.IsOpen && BaseStream.BytesToRead <= 0) { if (DateTime.Now > to) { throw new TimeoutException("Timeout"); } Task.Delay(1); } if (BaseStream.IsOpen) { BaseStream.Read(buffer, count, 1); if (rawlogfile != null && rawlogfile.CanWrite) { rawlogfile.WriteByte(buffer[count]); } } } } catch (Exception ex) { break; } // check if looks like a mavlink packet and check for exclusions and write to console if (buffer[0] != 0xfe && buffer[0] != 'U' && buffer[0] != 0xfd) { if (buffer[0] >= 0x20 && buffer[0] <= 127 || buffer[0] == '\n' || buffer[0] == '\r') { // check for line termination if (buffer[0] == '\r' || buffer[0] == '\n') { // check new line is valid if (buildplaintxtline.Length > 3) { plaintxtline = buildplaintxtline; } // reset for next line buildplaintxtline = ""; } TCPConsole.Write(buffer[0]); buildplaintxtline += (char)buffer[0]; } //_bytesReceivedSubj.OnNext(1); count = 0; buffer[1] = 0; continue; } // reset count on valid packet readcount = 0; // check for a header if (buffer[0] == 0xfe || buffer[0] == 0xfd || buffer[0] == 'U') { var mavlinkv2 = buffer[0] == GlobalAppData.MAVLINK_STX ? true : false; int headerlength = mavlinkv2 ? GlobalAppData.MAVLINK_CORE_HEADER_LEN : GlobalAppData.MAVLINK_CORE_HEADER_MAVLINK1_LEN; int headerlengthstx = headerlength + 1; // if we have the header, and no other chars, get the length and packet identifiers if (count == 0 && !logreadmode) { DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout); while (BaseStream.IsOpen && BaseStream.BytesToRead < headerlength) { if (DateTime.Now > to) { throw new TimeoutException("Timeout"); } Task.Delay(1); } int read = BaseStream.Read(buffer, 1, headerlength); count = read; if (rawlogfile != null && rawlogfile.CanWrite) { rawlogfile.Write(buffer, 1, read); } } // packet length if (buffer[0] == GlobalAppData.MAVLINK_STX) { length = buffer[1] + headerlengthstx + GlobalAppData.MAVLINK_NUM_CHECKSUM_BYTES; // data + header + checksum - magic - length if ((buffer[2] & GlobalAppData.MAVLINK_IFLAG_SIGNED) > 0) { length += GlobalAppData.MAVLINK_SIGNATURE_BLOCK_LEN; } } else { length = buffer[1] + headerlengthstx + GlobalAppData.MAVLINK_NUM_CHECKSUM_BYTES; // data + header + checksum - U - length } if (count >= headerlength || logreadmode) { try { if (logreadmode) { } else { DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout); while (BaseStream.IsOpen && BaseStream.BytesToRead < (length - (headerlengthstx))) { if (DateTime.Now > to) { break; } Task.Delay(1); } if (BaseStream.IsOpen) { int read = BaseStream.Read(buffer, headerlengthstx, length - (headerlengthstx)); if (rawlogfile != null && rawlogfile.CanWrite) { // write only what we read, temp is the whole packet, so 6-end rawlogfile.Write(buffer, headerlengthstx, read); } } } count = length; } catch { break; } break; } } count++; if (count == 299) { break; } } } // end readlock // resize the packet to the correct length Array.Resize <byte>(ref buffer, count); // add byte count //_bytesReceivedSubj.OnNext(buffer.Length); // update bps statistics if (_bpstime.Second != DateTime.Now.Second) { long btr = 0; if (BaseStream != null && BaseStream.IsOpen) { btr = BaseStream.BytesToRead; } else if (logreadmode) { btr = logplaybackfile.BaseStream.Length - logplaybackfile.BaseStream.Position; } _bps2 = _bps1; // prev sec _bps1 = 0; // current sec _bpstime = DateTime.Now; _mavlink1count = 0; _mavlink2count = 0; _mavlink2signed = 0; } _bps1 += buffer.Length; if (buffer.Length == 0) { return(MAVLinkMessage.Invalid); } if (message == null) { message = new MAVLinkMessage(buffer, DateTime.UtcNow); } uint msgid = message.msgid; GlobalAppData.message_info msginfo = GlobalAppData.GetMessageInfo(msgid); // calc crc var sigsize = (message.sig != null) ? GlobalAppData.MAVLINK_SIGNATURE_BLOCK_LEN : 0; ushort crc = MavlinkCRC.crc_calculate(buffer, message.Length - sigsize - GlobalAppData.MAVLINK_NUM_CHECKSUM_BYTES); // calc extra bit of crc for mavlink 1.0/2.0 if (message.header == 0xfe || message.header == 0xfd) { crc = MavlinkCRC.crc_accumulate(msginfo.crc, crc); } // check message length size vs table (mavlink1 explicit size check | mavlink2 allow all, undersize 0 trimmed, and oversize unknown extension) if (!message.ismavlink2 && message.payloadlength != msginfo.minlength) { if (msginfo.length == 0) // pass for unknown packets { } else { return(MAVLinkMessage.Invalid); } } // check crc if ((message.crc16 >> 8) != (crc >> 8) || (message.crc16 & 0xff) != (crc & 0xff)) { return(MAVLinkMessage.Invalid); } byte sysid = message.sysid; byte compid = message.compid; byte packetSeqNo = message.seq; // stat count if (message.buffer[0] == GlobalAppData.MAVLINK_STX) { _mavlink2count++; } else if (message.buffer[0] == GlobalAppData.MAVLINK_STX_MAVLINK1) { _mavlink1count++; } // if its a gcs packet - dont process further if (buffer.Length >= 5 && (sysid == 255 || sysid == 253) && logreadmode) // gcs packet { return(message); } return(message); }