public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObj = JObject.Load(reader);

        // Validate the required fields
        var system_id    = jObj.GetValue("system_id");
        var component_id = jObj.GetValue("component_id");
        var message_name = jObj.GetValue("message_name");
        var payload      = jObj.GetValue("payload");

        if (system_id == null)
        {
            throw new JsonSerializationException("system_id is a required message field");
        }

        if (component_id == null)
        {
            throw new JsonSerializationException("component_id is a required message field");
        }

        if (message_name == null)
        {
            throw new JsonSerializationException("message_name is a required message field");
        }

        if (payload == null)
        {
            throw new JsonSerializationException("payload is a required message field");
        }


        MavnetMessage msg = new MavnetMessage();

        msg.system_id    = system_id.Value <byte>();
        msg.component_id = component_id.Value <byte>();
        msg.message_name = message_name.Value <string>();

        // Lookup the Mavlink info object by name
        var messageInfo = MAVLink.MAVLINK_MESSAGE_INFOS.FirstOrDefault(m => m.name.Equals(msg.message_name));

        if (messageInfo.type == null)
        {
            throw new JsonSerializationException("unrecognized message_name: " + msg.message_name);
        }

        // Deserialize the payload
        msg.message_id = messageInfo.msgid;
        msg.payload    = Activator.CreateInstance(messageInfo.type);
        serializer.Populate(payload.CreateReader(), msg.payload);

        return(msg);
    }
Beispiel #2
0
        static void Main(string[] args)
        {
            const string DATA_FILE     = "/Users/thadthompson/dev/uvdl/thirdparty/genwork/test_packets_v2.bin";
            const string TEST_OUT_FILE = "/Users/thadthompson/dev/uvdl/thirdparty/genwork/test_output_packets_v2.bin";

            Console.WriteLine("Starting MAVLink test");
            var data = System.IO.File.ReadAllBytes(DATA_FILE);

            // Create a parser with logging output to Console.WriteLine
            MavnetParser parser = new MavnetParser(Console.WriteLine);

            parser.PacketReceived += (sender, e) =>
            {
                Console.WriteLine("Received Packet: " + e);
            };

            var messages = parser.ParseBytes(data);

            using (var fout = System.IO.File.OpenWrite(TEST_OUT_FILE))
            {
                foreach (var msg in messages)
                {
                    // Round trip through JSON
                    string        js    = msg.toJson();
                    MavnetMessage jsmsg = Newtonsoft.Json.JsonConvert.DeserializeObject <MavnetMessage>(js);
                    fout.Write(jsmsg.toBytes());
                }
            }

            Console.WriteLine("Testing incremental message parsing");
            for (int i = 0; i < data.Length; i++)
            {
                var messages2 = parser.ParseBytes(new byte[] { data[i] });
                if (messages2.Count > 0)
                {
                    Console.WriteLine("Parsed message at {0} bytes: {1}", i, messages2[0].toJson());
                }
            }


            //    string TEST_MESSAGE = "{\"system_id\":123,\"component_id\":212,\"message_name\":\"HEARTBEAT\",\"payload\":{\"custom_mode\":4,\"type\":1,\"autopilot\":2,\"base_mode\":3,\"system_status\":5,\"mavlink_version\":1}}";
            //    //MavnetMessage jsmsg = Newtonsoft.Json.JsonConvert.DeserializeObject<MavnetMessage>(TEST_MESSAGE);
            //    Console.WriteLine(jsmsg.toJson());
        }
Beispiel #3
0
    /// <summary>
    /// Add an array of bytes to the parser. Any newly parsed packets are returned.
    /// </summary>
    public IList <MavnetMessage> ParseBytes(byte [] buf)
    {
        var newMessages = new List <MavnetMessage>();

        // Combine any previous data we were holding with the new buffer
        byte[] parseBuf;
        if (_residual == null)
        {
            parseBuf = buf;
        }
        else
        {
            parseBuf = new byte[_residual.Length + buf.Length];
            Buffer.BlockCopy(_residual, 0, parseBuf, 0, _residual.Length);
            Buffer.BlockCopy(buf, 0, parseBuf, _residual.Length, buf.Length);
        }

        _residual = null;

        // Start parsing
        int idx = 0;

        while (idx < parseBuf.Length)
        {
            // Search for a packet header
            for (; idx < parseBuf.Length && parseBuf[idx] != MAVLink.MAVLINK_STX && parseBuf[idx] != MAVLink.MAVLINK_STX_MAVLINK1; idx++)
            {
                trashBytes++;
            }

            // Check for data left
            if (idx == parseBuf.Length)
            {
                break;
            }

            // Create a slice in the parse buffer for our potential packet
            Span <byte> pkt = new Span <byte>(parseBuf, idx, parseBuf.Length - idx);

            bool isMavlinkV2 = pkt[0] == MAVLink.MAVLINK_STX;

            // Check to see if we have the header
            int headerlength = isMavlinkV2 ? MAVLink.MAVLINK_CORE_HEADER_LEN : MAVLink.MAVLINK_CORE_HEADER_MAVLINK1_LEN;
            if (pkt.Length < headerlength)
            {
                break;
            }

            // packet length
            int packetLength = pkt[1] + headerlength + 1 + 2; // payload + protocol marker + header + checksum

            // MAVLink v2 may to add a signature block
            if (isMavlinkV2 && (pkt[2] & MAVLink.MAVLINK_IFLAG_SIGNED) > 0)
            {
                packetLength += MAVLink.MAVLINK_SIGNATURE_BLOCK_LEN;
            }

            // Check to see if we have a full packet
            if (pkt.Length < packetLength)
            {
                break;
            }

            // Slice out the packet bytes and try to parse it into a MavLink packet
            idx += packetLength;
            Span <byte> fullPacket = pkt.Slice(0, packetLength);

            MavnetMessage msg = null;

            try
            {
                msg = ParseSinglePacket(fullPacket);
            }
            catch (Exception ex)
            {
                log("Unable to parse packet: " + ex.Message);
                parseErrors++;
            }

            if (msg != null)
            {
                newMessages.Add(msg);

                // Raise event when packet is received.
                PacketReceived?.Invoke(this, msg);
            }
        }

        // Anything leftover is residual that we'll keep to try to reassmble with more data when it arrives.
        if (idx < parseBuf.Length)
        {
            _residual = new byte[parseBuf.Length - idx];
            Buffer.BlockCopy(parseBuf, idx, _residual, 0, parseBuf.Length - idx);
        }

        return(newMessages);
    }
Beispiel #4
0
    // Parse a single Mavnet message from a slice of a byte array
    private MavnetMessage ParseSinglePacket(Span <byte> pkt)
    {
        MavnetMessage msg = new MavnetMessage();

        // Parse out the header
        if (pkt[0] == MAVLink.MAVLINK_STX)
        {
            msg.is_mavlink_v2  = true;
            msg.payload_length = pkt[1];
            msg.incompat_flags = pkt[2];
            msg.compat_flags   = pkt[3];
            msg.sequence       = pkt[4];
            msg.system_id      = pkt[5];
            msg.component_id   = pkt[6];
            msg.message_id     = (uint)((pkt[9] << 16) + (pkt[8] << 8) + pkt[7]);

            if ((msg.incompat_flags & MAVLink.MAVLINK_IFLAG_SIGNED) > 0)
            {
                Span <byte> sig_block = pkt.Slice(pkt.Length - MAVLink.MAVLINK_SIGNATURE_BLOCK_LEN);
                msg.signature_link_id   = sig_block[0];
                msg.signature_timestamp = BitConverter.ToUInt64(sig_block.Slice(1, 6).ToArray(), 0);
                msg.signature           = sig_block.Slice(7).ToArray();
            }
        }
        else
        {
            msg.is_mavlink_v2  = false;
            msg.payload_length = pkt[1];
            msg.sequence       = pkt[2];
            msg.system_id      = pkt[3];
            msg.component_id   = pkt[4];
            msg.message_id     = pkt[5];
        }

        // Lookup the message type info.
        MAVLink.message_info messageInfo;
        if (!_messageInfoTable.TryGetValue(msg.message_id, out messageInfo))
        {
            log("Unknown MAVLink message ID: " + msg.message_id);
            unknownMessageTypes++;
            return(null);
        }

        msg.message_name = messageInfo.name;

        // Check the CRC
        var headerLen = msg.is_mavlink_v2 ? MAVLink.MAVLINK_CORE_HEADER_LEN : MAVLink.MAVLINK_CORE_HEADER_MAVLINK1_LEN;

        var    crc1  = headerLen + msg.payload_length + 1;
        var    crc2  = crc1 + 1;
        ushort crc16 = (ushort)((pkt[crc2] << 8) + pkt[crc1]);

        ushort calcCrc = MAVLink.MavlinkCRC.crc_calculate(pkt.ToArray(), pkt.Length - 2);

        calcCrc = MAVLink.MavlinkCRC.crc_accumulate(messageInfo.crc, calcCrc);

        if (crc16 != calcCrc)
        {
            log(string.Format("Bad message CRC for {0} message: expected: {1}, found: {2} ", msg.message_name, calcCrc, crc16));
            crcErrors++;
            return(null);
        }

        if (msg.is_mavlink_v2)
        {
            // Mavlink V2
            if (msg.payload_length == messageInfo.length)
            {
                msg.payload = messageInfo.deserializer(pkt.Slice(MAVLink.MAVLINK_NUM_HEADER_BYTES, msg.payload_length));
            }
            else
            {
                // Handle zero byte payload truncation
                // see: https://mavlink.io/en/guide/serialization.html#payload_truncation
                Span <byte> paddedPayload = stackalloc byte[messageInfo.length];
                pkt.Slice(MAVLink.MAVLINK_NUM_HEADER_BYTES, msg.payload_length).CopyTo(paddedPayload);
                msg.payload = messageInfo.deserializer(paddedPayload);
            }
        }
        else
        {
            // Mavlink V1
            msg.payload = messageInfo.deserializer(pkt.Slice(MAVLink.MAVLINK_CORE_HEADER_MAVLINK1_LEN + 1, msg.payload_length));
        }

        return(msg);
    }
Beispiel #5
0
    // Parse a single Mavnet message from a slice of a byte array
    private MavnetMessage ParseSinglePacket(Span <byte> pkt)
    {
        MavnetMessage msg = new MavnetMessage();

        // Parse out the header
        if (pkt[0] == MAVLink.MAVLINK_STX)
        {
            msg.is_mavlink_v2  = true;
            msg.payload_length = pkt[1];
            msg.incompat_flags = pkt[2];
            msg.compat_flags   = pkt[3];
            msg.sequence       = pkt[4];
            msg.system_id      = pkt[5];
            msg.component_id   = pkt[6];
            msg.message_id     = (uint)((pkt[9] << 16) + (pkt[8] << 8) + pkt[7]);

            if ((msg.incompat_flags & MAVLink.MAVLINK_IFLAG_SIGNED) > 0)
            {
                Span <byte> sig_block = pkt.Slice(pkt.Length - MAVLink.MAVLINK_SIGNATURE_BLOCK_LEN);
                msg.signature_link_id   = sig_block[0];
                msg.signature_timestamp = BitConverter.ToUInt64(sig_block.Slice(1, 6));
                msg.signature           = sig_block.Slice(7).ToArray();
            }
        }
        else
        {
            msg.is_mavlink_v2  = false;
            msg.payload_length = pkt[1];
            msg.sequence       = pkt[2];
            msg.system_id      = pkt[3];
            msg.component_id   = pkt[4];
            msg.message_id     = pkt[5];
        }

        // Lookup the message type info.
        MAVLink.message_info messageInfo;
        if (!_messageInfoTable.TryGetValue(msg.message_id, out messageInfo))
        {
            log("Unknown MAVLink message ID: " + msg.message_id);
            unknownMessageTypes++;
            return(null);
        }

        msg.message_name = messageInfo.name;

        // Check the CRC
        var headerLen = msg.is_mavlink_v2 ? MAVLink.MAVLINK_CORE_HEADER_LEN : MAVLink.MAVLINK_CORE_HEADER_MAVLINK1_LEN;

        var    crc1  = headerLen + msg.payload_length + 1;
        var    crc2  = crc1 + 1;
        ushort crc16 = (ushort)((pkt[crc2] << 8) + pkt[crc1]);

        ushort calcCrc = MAVLink.MavlinkCRC.crc_calculate(pkt.ToArray(), pkt.Length - 2);

        calcCrc = MAVLink.MavlinkCRC.crc_accumulate(messageInfo.crc, calcCrc);

        if (crc16 != calcCrc)
        {
            log(string.Format("Bad message CRC for {0} message: expected: {1}, found: {2} ", msg.message_name, calcCrc, crc16));
            crcErrors++;
            return(null);
        }

        // Deserialize the payload
        try
        {
            object payload = Activator.CreateInstance(messageInfo.type);
            if (msg.is_mavlink_v2)
            {
                MavlinkUtil.ByteArrayToStructure(pkt.ToArray(), ref payload, MAVLink.MAVLINK_NUM_HEADER_BYTES, msg.payload_length);
            }
            else
            {
                MavlinkUtil.ByteArrayToStructure(pkt.ToArray(), ref payload, 6, msg.payload_length);
            }

            msg.payload = payload;
        }
        catch (Exception ex)
        {
            log(ex.ToString());
            return(null);
        }

        return(msg);
    }