/** * Parse a MAVLink xml messages descriptor file. * * @param mavlink MAVLink data used and to fill * @param file Parsed file * @param path Path to file * @param target Path for generation * @param inInclude True if we are in an include file * @return implementation code for readers and writers. * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ public Map<String, String> parseFile( MAVLinkData mavlink, String file, String path, String target, boolean inInclude) throws ParserConfigurationException, SAXException, IOException { Map<String, String> implementations = new HashMap<String, String>(); SAXParserFactory fabrique = SAXParserFactory.newInstance(); SAXParser parseur = fabrique.newSAXParser(); if (!inInclude) { mavlink.setFile(file.substring(0, file.indexOf('.'))); System.out.println("MAVLinkData : " + mavlink.getFile()); } else { System.out.println("MAVLinkData INCLUDE : " + file.substring(0, file.indexOf('.'))); } MAVLinkHandler gestionnaire = new MAVLinkHandler(this, mavlink, path, target); parseur.parse(new File(path + File.separator + file), gestionnaire); mavlink = gestionnaire.getMavlink(); generateMessageClass(mavlink, target); mavlink.getEnums().putAll(mavlink.getEnums()); mavlink.getMessages().putAll(mavlink.getMessages()); generateEnumClass(mavlink, target, implementations); return implementations; }
/** * Generate Interface with all MAVLink messages ID * * @param mavlink * @param targetPath */ protected void generateIMavlinkId(MAVLinkData mavlink, String targetPath) { String packageRootName = "org.mavlink.messages"; String packageName = packageRootName; String directory = targetPath + "/org/mavlink/messages/"; OutputStream output = null; PrintWriter writer = null; String className = "IMAVLinkMessageID"; String filename = directory + className + ".java"; try { File file = new File(directory); file.mkdirs(); output = new FileOutputStream(filename, false); writer = new PrintWriter(output); // Write Header writer.print("/**\n * Generated class : " + className + "\n * DO NOT MODIFY!\n **/\n"); writer.print("package " + packageName + ";\n"); writer.print( "/**\n * Interface IMAVLinkMessageId\n * Generate al MAVLink message Id in an interface\n **/\n"); writer.print("public interface IMAVLinkMessageID {\n"); for (MAVLinkMessage message : mavlink.getMessages().values()) { String id = MAVLINK_MSG + "_ID_" + message.getName(); writer.print(" public static int " + id + " = " + message.getId() + ";\n"); } writer.print("}\n"); } catch (Exception e) { System.err.println("ERROR : " + e); e.printStackTrace(); } finally { try { writer.close(); output.close(); } catch (Exception ex) { System.err.println("ERROR : " + ex); ex.printStackTrace(); } } }
/** * Generate a factory classe which generate MAVLink messages from byte array * * @param mavlink * @param targetPath */ protected void generateFactoryClass(MAVLinkData mavlink, String targetPath) { String packageRootName = "org.mavlink.messages"; String packageName = packageRootName; String directory = targetPath + "/org/mavlink/messages/"; OutputStream output = null; PrintWriter writer = null; String className = "MAVLinkMessageFactory"; String filename = directory + className + ".java"; try { File file = new File(directory); file.mkdirs(); output = new FileOutputStream(filename, false); writer = new PrintWriter(output); // Write Header writer.print("/**\n * Generated class : " + className + "\n * DO NOT MODIFY!\n **/\n"); writer.print("package " + packageName + ";\n"); writer.print("import " + packageRootName + ".MAVLinkMessage;\n"); writer.print("import org.mavlink.IMAVLinkMessage;\n"); writer.print("import java.io.IOException;\n"); if (forEmbeddedJava) { if (isLittleEndian) { writer.print("import org.mavlink.io.LittleEndianDataInputStream;\n"); writer.print("import java.io.ByteArrayInputStream;\n"); } else { writer.print("import java.io.DataInputStream;\n"); writer.print("import java.io.ByteArrayInputStream;\n"); } } else { writer.print("import java.nio.ByteBuffer;\n"); writer.print("import java.nio.ByteOrder;\n"); } writer.print(imports); writer.print( "/**\n * Class MAVLinkMessageFactory\n * Generate MAVLink message classes from byte array\n **/\n"); writer.print( "public class MAVLinkMessageFactory implements IMAVLinkMessage, IMAVLinkMessageID {\n"); writer.print( "public static MAVLinkMessage getMessage(int msgid, int sysId, int componentId, byte[] rawData) throws IOException {\n"); writer.print(" MAVLinkMessage msg=null;\n"); if (forEmbeddedJava) { if (isLittleEndian) { writer.print( " LittleEndianDataInputStream dis = new LittleEndianDataInputStream(new ByteArrayInputStream(rawData));\n"); } else { writer.print( " DataInputStream dis = new DataInputStream(new ByteArrayInputStream(rawData));\n"); } } else { if (isLittleEndian) { writer.print( " ByteBuffer dis = ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN);\n"); } else { writer.print( " ByteBuffer dis = ByteBuffer.wrap(rawData).order(ByteOrder.BIG_ENDIAN);\n"); } } writer.print(" switch(msgid) {\n"); for (MAVLinkMessage message : mavlink.getMessages().values()) { String msgClassName = "msg_" + message.getName().toLowerCase(); String id = MAVLINK_MSG + "_ID_" + message.getName(); writer.print(" case " + id + ":\n"); writer.print(" msg = new " + msgClassName + "(sysId, componentId);\n"); writer.print(" msg.decode(dis);\n"); writer.print(" break;\n"); } writer.print(" default:\n"); writer.print( " System.out.println(\"Mavlink Factory Error : unknown MsgId : \" + msgid);\n"); writer.print(" }\n"); writer.print(" return msg;\n"); writer.print(" }\n"); writer.print("}\n"); } catch (Exception e) { System.err.println("ERROR : " + e); e.printStackTrace(); } finally { try { writer.close(); output.close(); } catch (Exception ex) { System.err.println("ERROR : " + ex); ex.printStackTrace(); } } }
/** * Generate MAVLink messages Java classes * * @param mavlink * @param targetPath */ protected void generateMessageClass(MAVLinkData mavlink, String targetPath) { StringBuffer sbRead, sbWrite, fieldWrite; String packageRootName = "org.mavlink.messages"; String xmlFilename = mavlink.getFile(); String packageName = packageRootName + "." + xmlFilename; String directory = targetPath + "/org/mavlink/messages/" + xmlFilename + "/"; OutputStream output = null; PrintWriter writer = null; String forToString = ""; for (MAVLinkMessage message : mavlink.getMessages().values()) { String className = "msg_" + message.getName().toLowerCase(); String filename = directory + className + ".java"; imports = imports + "import " + packageName + "." + className + ";\n"; try { File file = new File(directory); file.mkdirs(); output = new FileOutputStream(filename, false); writer = new PrintWriter(output); sbRead = new StringBuffer(); sbWrite = new StringBuffer(); fieldWrite = new StringBuffer(); if (forEmbeddedJava) { sbWrite.append(" dos.writeByte((byte)0xFE);\n"); sbWrite.append(" dos.writeByte(length & 0x00FF);\n"); sbWrite.append(" dos.writeByte(sequence & 0x00FF);\n"); sbWrite.append(" dos.writeByte(sysId & 0x00FF);\n"); sbWrite.append(" dos.writeByte(componentId & 0x00FF);\n"); sbWrite.append(" dos.writeByte(messageType & 0x00FF);\n"); } else { sbWrite.append(" dos.put((byte)0xFE);\n"); sbWrite.append(" dos.put((byte)(length & 0x00FF));\n"); sbWrite.append(" dos.put((byte)(sequence & 0x00FF));\n"); sbWrite.append(" dos.put((byte)(sysId & 0x00FF));\n"); sbWrite.append(" dos.put((byte)(componentId & 0x00FF));\n"); sbWrite.append(" dos.put((byte)(messageType & 0x00FF));\n"); } // Write Header writer.print("/**\n * Generated class : " + className + "\n * DO NOT MODIFY!\n **/\n"); writer.print("package " + packageName + ";\n"); writer.print("import " + packageRootName + ".MAVLinkMessage;\n"); writer.print("import org.mavlink.IMAVLinkCRC;\n"); writer.print("import org.mavlink.MAVLinkCRC;\n"); writer.print("import java.io.ByteArrayOutputStream;\n"); writer.print("import java.io.IOException;\n"); if (forEmbeddedJava) { if (isLittleEndian) { writer.print("import org.mavlink.io.LittleEndianDataInputStream;\n"); writer.print("import org.mavlink.io.LittleEndianDataOutputStream;\n"); } else { writer.print("import java.io.DataInputStream;\n"); writer.print("import java.io.DataOutputStream;\n"); } } else { writer.print("import java.nio.ByteBuffer;\n"); writer.print("import java.nio.ByteOrder;\n"); } String description = message.getDescription(); writer.print( "/**\n * Class " + className + "\n * " + (description == null ? "" : message.getDescription().trim()) + "\n **/\n"); writer.print("public class " + className + " extends MAVLinkMessage {\n"); String id = MAVLINK_MSG + "_ID_" + message.getName(); writer.print(" public static final int " + id + " = " + message.getId() + ";\n"); writer.print(" private static final long serialVersionUID = " + id + ";\n"); writer.print( " public " + className + "(int sysId, int componentId) {\n messageType = " + id + ";\n this.sysId = sysId;\n this.componentId = componentId;\n"); // Calculate extra_crc for Mavlinl 1.0 String extraCrcBuffer = message.getName() + " "; // Write Fields int fieldLen = 0; Collections.sort(message.getFields(), new FieldCompare()); for (int j = 0; j < message.getFields().size(); j++) { MAVLinkField field = message.getFields().get(j); fieldWrite.append(" /**\n * " + field.getDescription().trim() + "\n */\n"); MAVLinkDataType type = field.getType(); fieldWrite.append(" public " + type.getJavaType(field.getName()) + "\n"); sbRead.append(type.getReadType(field.getName(), forEmbeddedJava)); sbWrite.append(type.getWriteType(field.getName(), forEmbeddedJava)); String attr = field.getName(); if (type.isArray && type.type == MAVLinkDataType.CHAR) { String first = "" + attr.charAt(0); attr = first.toUpperCase() + field.getName().substring(1); fieldWrite.append(" public void set" + attr + "(String tmp) {\n"); fieldWrite.append(" int len = Math.min(tmp.length(), " + type.arrayLenth + ");\n"); fieldWrite.append( " for (int i=0; i<len; i++) {\n " + field.getName() + "[i] = tmp.charAt(i);\n }\n"); fieldWrite.append( " for (int i=len; i<" + type.arrayLenth + "; i++) {\n " + field.getName() + "[i] = 0;\n }\n }\n"); fieldWrite.append(" public String get" + attr + "() {\n"); fieldWrite.append(" String result=\"\";\n"); fieldWrite.append( " for (int i=0; i<" + type.arrayLenth + "; i++) {\n if (" + field.getName() + "[i] != 0) result=result+" + field.getName() + "[i]; else break;\n }\n return result;\n }\n"); } fieldLen += type.getLengthType(); forToString = forToString + (j != 0 ? "+" : "") + " \" " + field.getName() + "=\"+" + (field.getType().isArray && field.getType().type == MAVLinkDataType.CHAR ? "get" + attr + "()" : field.getName()); extraCrcBuffer = extraCrcBuffer + type.getCType() + " " + field.getName() + " "; if (type.isArray) { extraCrcBuffer = extraCrcBuffer + (char) type.arrayLenth; } } writer.print(" length = " + fieldLen + ";\n}\n\n"); writer.print(fieldWrite.toString()); int extra_crc = MAVLinkCRC.crc_calculate(MAVLinkCRC.stringToByte(extraCrcBuffer)); int magicNumber = (extra_crc & 0x00FF) ^ ((extra_crc >> 8 & 0x00FF)); MAVLINK_MESSAGE_CRCS[message.getId()] = magicNumber; writer.print("/**\n"); writer.print(" * Decode message with raw data\n"); writer.print(" */\n"); if (forEmbeddedJava) { if (isLittleEndian) { writer.print( "public void decode(LittleEndianDataInputStream dis) throws IOException {\n"); } else { writer.print("public void decode(DataInputStream dis) throws IOException {\n"); } } else { writer.print("public void decode(ByteBuffer dis) throws IOException {\n"); } writer.print(sbRead.toString()); writer.print("}\n"); writer.print("/**\n"); writer.print(" * Encode message with raw data and other informations\n"); writer.print(" */\n"); writer.print("public byte[] encode() throws IOException {\n"); writer.print(" byte[] buffer = new byte[8+" + fieldLen + "];\n"); if (forEmbeddedJava) { if (isLittleEndian) { writer.print( " LittleEndianDataOutputStream dos = new LittleEndianDataOutputStream(new ByteArrayOutputStream());\n"); } else { writer.print(" ByteArrayOutputStream baos = new ByteArrayOutputStream();\n"); writer.print(" DataOutputStream dos = new DataOutputStream(baos);\n"); } } else { if (isLittleEndian) { writer.print( " ByteBuffer dos = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);\n"); } else { writer.print( " ByteBuffer dos = ByteBuffer.wrap(buffer).order(ByteOrder.BIG_ENDIAN);\n"); } } writer.print(sbWrite.toString()); if (forEmbeddedJava) { if (isLittleEndian) { writer.print(" dos.flush();\n byte[] tmp = dos.toByteArray();\n"); } else { writer.print(" dos.flush();\n byte[] tmp = baos.toByteArray();\n"); } writer.print(" for (int b=0; b<tmp.length; b++) buffer[b]=tmp[b];\n"); } else { // nothing } writer.print(" int crc = MAVLinkCRC.crc_calculate_encode(buffer, " + fieldLen + ");\n"); writer.print( " crc = MAVLinkCRC.crc_accumulate((byte) IMAVLinkCRC.MAVLINK_MESSAGE_CRCS[messageType], crc);\n"); writer.print(" byte crcl = (byte) (crc & 0x00FF);\n"); writer.print(" byte crch = (byte) ((crc >> 8) & 0x00FF);\n"); writer.print(" buffer[" + (fieldLen + 6) + "] = crcl;\n"); writer.print(" buffer[" + (fieldLen + 7) + "] = crch;\n"); writer.print(" return buffer;\n}\n"); if (debug) { writer.print("public String toString() {\n"); writer.print("return \"" + id + " : \" + " + forToString + ";"); writer.print("}\n"); } writer.print("}\n"); forToString = ""; } catch (Exception e) { System.err.println("ERROR : " + e); e.printStackTrace(); } finally { try { writer.close(); output.close(); } catch (Exception ex) { System.err.println("ERROR : " + ex); ex.printStackTrace(); } } } }