-- Auto generated MAVLink parsing script local mavlink_msgs = {} ---Lookup the message id for a given message name ---@param msgname string ---@return integer -- message id function mavlink_msgs.get_msgid(msgname) local message_map = require("MAVLink/mavlink_msg_" .. msgname) if not message_map then error("Unknown MAVLink message " .. msgname) end return message_map.id end ---Return a object containing everything that is not the payload ---@param message any -- encoded message ---@return table function mavlink_msgs.decode_header(message) -- build up a map of the result local result = {} result.checksum = string.unpack("> 8) ~ (tmp << 8) ~ (tmp << 3) ~ (tmp >> 4) crc = crc & 0xFFFF end return crc end -- Note that this does not parse the serial data, it parses the MAVLink 2 C structure `mavlink_message_t` -- This structure is passed in by the ArduPilot bindings as a string ---@param message any -- encoded message ---@param msg_map table -- table containing message objects with keys of the message ID ---@return table|nil -- a table representing the contents of the message, or nill if decode failed function mavlink_msgs.decode(message, msg_map) local result = mavlink_msgs.decode_header(message) local message_map = require("MAVLink/mavlink_msg_" .. msg_map[result.msgid]) if not message_map then -- we don't know how to decode this message, bail on it return nil end -- If we have a crc extra for this message then check it -- This ensures compatibility with message definitions generated before the crc check was added if message_map.crc_extra then -- crc of payload and header values local crc_buffer if result.protocol_version == 2 then crc_buffer = string.sub(message, 4, 12 + result.payload_length) else -- V1 does not include all fields on the wire crc_buffer = string.char(result.payload_length) crc_buffer = crc_buffer .. string.char(result.seq) crc_buffer = crc_buffer .. string.char(result.sysid) crc_buffer = crc_buffer .. string.char(result.compid) crc_buffer = crc_buffer .. string.char(result.msgid) if result.payload_length > 0 then crc_buffer = crc_buffer .. string.sub(message, 13, 12 + result.payload_length) end end local crc = mavlink_msgs.generateCRC(crc_buffer .. string.char(message_map.crc_extra)) if crc ~= result.checksum then -- crc failed return nil end end -- map all the fields out local offset = 13 for _,v in ipairs(message_map.fields) do if v[3] then result[v[1]] = {} for j=1,v[3] do result[v[1]][j], offset = string.unpack(v[2], message, offset) end else result[v[1]], offset = string.unpack(v[2], message, offset) if string.sub(v[2],2,2) == 'c' then -- Got string, unpack includes 0 values to the set length -- this is annoying, so remove them result[v[1]] = string.gsub(result[v[1]], string.char(0), "") end end end return result end ---Encode the payload section of a given message ---@param msgname string -- name of message to encode ---@param message table -- table containing key value pairs representing the data fields in the message ---@return integer -- message id ---@return string -- encoded payload function mavlink_msgs.encode(msgname, message) local message_map = require("MAVLink/mavlink_msg_" .. msgname) if not message_map then -- we don't know how to encode this message, bail on it error("Unknown MAVLink message " .. msgname) end local packString = "<" local packedTable = {} local packedIndex = 1 for i,v in ipairs(message_map.fields) do if v[3] then packString = (packString .. string.rep(string.sub(v[2], 2), v[3])) for j = 1, v[3] do packedTable[packedIndex] = message[message_map.fields[i][1]][j] if packedTable[packedIndex] == nil then packedTable[packedIndex] = 0 end packedIndex = packedIndex + 1 end else packString = (packString .. string.sub(v[2], 2)) packedTable[packedIndex] = message[message_map.fields[i][1]] packedIndex = packedIndex + 1 end end return message_map.id, string.pack(packString, table.unpack(packedTable)) end return mavlink_msgs