diff options
author | Jakob Odersky <jodersky@gmail.com> | 2015-03-20 12:07:41 +0100 |
---|---|---|
committer | Jakob Odersky <jodersky@gmail.com> | 2015-03-20 12:07:41 +0100 |
commit | 3147aba7dc79e64d2da50d7d1c705bfd0e99eeca (patch) | |
tree | 6c0babfa3e227e3407a0fe250059724f303ad08a | |
parent | 1cf6e37dc356144f3da2a2dcde75d1ced8bc5ad6 (diff) | |
download | sbt-mavlink-3147aba7dc79e64d2da50d7d1c705bfd0e99eeca.tar.gz sbt-mavlink-3147aba7dc79e64d2da50d7d1c705bfd0e99eeca.tar.bz2 sbt-mavlink-3147aba7dc79e64d2da50d7d1c705bfd0e99eeca.zip |
implement testing
-rw-r--r-- | .gitignore | 12 | ||||
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | mavlink-library/src/main/twirl/org/mavlink/Assembler.scala.txt | 2 | ||||
-rw-r--r-- | mavlink-library/src/main/twirl/org/mavlink/MavlinkBuffer.scala.txt | 2 | ||||
-rw-r--r-- | mavlink-library/src/main/twirl/org/mavlink/Packet.scala.txt | 29 | ||||
-rw-r--r-- | mavlink-library/src/main/twirl/org/mavlink/Parser.scala.txt | 2 | ||||
-rw-r--r-- | mavlink-plugin/src/main/scala/com/github/jodersky/mavlink/sbt/SbtMavlink.scala | 14 | ||||
-rw-r--r-- | mavlink-plugin/src/sbt-test/sbt-mavlink/codec/build.sbt | 11 | ||||
-rw-r--r-- | mavlink-plugin/src/sbt-test/sbt-mavlink/codec/mavlink.xml | 115 | ||||
-rw-r--r-- | mavlink-plugin/src/sbt-test/sbt-mavlink/codec/project/plugins.sbt | 1 | ||||
-rw-r--r-- | mavlink-plugin/src/sbt-test/sbt-mavlink/codec/src/main/scala/Main.scala | 53 | ||||
-rw-r--r-- | mavlink-plugin/src/sbt-test/sbt-mavlink/codec/test | 3 | ||||
-rw-r--r-- | project/Build.scala | 9 | ||||
-rw-r--r-- | project/scripted.sbt | 3 | ||||
-rw-r--r-- | project/twirl.sbt (renamed from project/plugins.sbt) | 0 |
15 files changed, 243 insertions, 25 deletions
@@ -10,12 +10,12 @@ project/boot/ project/plugins/project/ # scala-ide specific -/.settings -/.scala_dependencies -/.project -/.classpath -/.cache -/.history +.settings +.scala_dependencies +.project +.classpath +.cache +.history # ensime .ensime @@ -1,3 +1,13 @@ # SBT-MAVLink Plugin -This plugin aims to provide generation of Scala sources from MAVLink message definition files.
\ No newline at end of file +This plugin provides generation of Scala sources from MAVLink message definition files. +It translates a MAVLink dialect defined in XML to useable scala objects and provides utilities for parsing +and creating MAVLink packets. + +See an example + +## Usage +Add the following to your plugins: + + addSbtPlugin("com.github.jodersky" % "sbt-mavlink" % "0.1") + diff --git a/mavlink-library/src/main/twirl/org/mavlink/Assembler.scala.txt b/mavlink-library/src/main/twirl/org/mavlink/Assembler.scala.txt index e3571e6..fc5becf 100644 --- a/mavlink-library/src/main/twirl/org/mavlink/Assembler.scala.txt +++ b/mavlink-library/src/main/twirl/org/mavlink/Assembler.scala.txt @@ -15,5 +15,5 @@ class Assembler(systemId: Byte, componentId: Byte) { val p = Packet(seq.toByte, systemId, componentId, messageId, payload) seq += 1 p - } + } }
\ No newline at end of file diff --git a/mavlink-library/src/main/twirl/org/mavlink/MavlinkBuffer.scala.txt b/mavlink-library/src/main/twirl/org/mavlink/MavlinkBuffer.scala.txt index 9a01dbe..ebcd643 100644 --- a/mavlink-library/src/main/twirl/org/mavlink/MavlinkBuffer.scala.txt +++ b/mavlink-library/src/main/twirl/org/mavlink/MavlinkBuffer.scala.txt @@ -5,7 +5,7 @@ import java.nio.ByteBuffer import java.nio.ByteOrder /** Utility functions for using ByteBuffers. */ -class MavlinkBuffer { +object MavlinkBuffer { /** * Allocates a ByteBuffer for using in MAVLink message processing. diff --git a/mavlink-library/src/main/twirl/org/mavlink/Packet.scala.txt b/mavlink-library/src/main/twirl/org/mavlink/Packet.scala.txt index a0d11a5..6802a0a 100644 --- a/mavlink-library/src/main/twirl/org/mavlink/Packet.scala.txt +++ b/mavlink-library/src/main/twirl/org/mavlink/Packet.scala.txt @@ -20,21 +20,33 @@ case class Packet( payload: ByteBuffer ) { - /* - def crc = { + lazy val crc = { var c = new Crc() - c = c.accumulate(payload.length.toByte) + c = c.accumulate(payload.remaining.toByte) c = c.accumulate(seq) c = c.accumulate(systemId) c = c.accumulate(componentId) c = c.accumulate(messageId) - while (payload.) - for (p <- payload) { - c = c.accumulate(p) + while (payload.hasRemaining) { + c = c.accumulate(payload.get()) } c = c.accumulate(Packet.extraCrc(messageId)) c - }*/ + } + + def writeTo(out: Array[Byte], offset: Int = 0): Unit = { + out(offset) = Packet.Stx + out(offset+1) = payload.remaining.toByte + out(offset+2) = seq + out(offset+3) = systemId + out(offset+4) = componentId + out(offset+5) = messageId + val r = payload.remaining() + payload.get(out, 0, out.length) + out(offset + r) = crc.lsb + out(offset + r + 1) = crc.msb + } + } object Packet { @@ -45,6 +57,9 @@ object Packet { /** Maximum length of a payload contained in a packet. */ final val MaxPayloadLength: Int = @__maxPayloadLength + /** Maximum over-the-wire size of a packet, i.e. the maximum payload length plus header and footer data. */ + final val MaxPacketLength: Int = MaxPayloadLength + 8 + /** Additional CRCs indexed by message ID (see MAVLink specification). */ final val ExtraCrcs: Seq[Byte] = Array[Byte]( @__extraCrcs.map(_ formatted "%3d").grouped(10).map(_.mkString(",")).mkString(",\n ") diff --git a/mavlink-library/src/main/twirl/org/mavlink/Parser.scala.txt b/mavlink-library/src/main/twirl/org/mavlink/Parser.scala.txt index ca04ae1..81affc5 100644 --- a/mavlink-library/src/main/twirl/org/mavlink/Parser.scala.txt +++ b/mavlink-library/src/main/twirl/org/mavlink/Parser.scala.txt @@ -40,7 +40,7 @@ object Parser { * @@param receiver called when a valid packet has been received * @@param error called when invalid data was received */ -class Parser(payload: ByteBuffer, receiver: Packet => Unit, error: Parser.Errors.Error => Unit = _ => ()) { +class Parser(payload: ByteBuffer)(receiver: Packet => Unit, error: Parser.Errors.Error => Unit = _ => ()) { import Parser._ private var state: States.State = States.Idle diff --git a/mavlink-plugin/src/main/scala/com/github/jodersky/mavlink/sbt/SbtMavlink.scala b/mavlink-plugin/src/main/scala/com/github/jodersky/mavlink/sbt/SbtMavlink.scala index 41a6bcf..d04ea43 100644 --- a/mavlink-plugin/src/main/scala/com/github/jodersky/mavlink/sbt/SbtMavlink.scala +++ b/mavlink-plugin/src/main/scala/com/github/jodersky/mavlink/sbt/SbtMavlink.scala @@ -16,14 +16,14 @@ object SbtMavlink extends AutoPlugin { override def requires = JvmPlugin //this is required as sourceGenerators are otherwise reset override lazy val projectSettings: Seq[Setting[_]] = Seq( - mavlinkDialect in Compile := (baseDirectory in Compile).value / "conf" / "mavlink.xml", - mavlinkTarget in Compile := (sourceManaged in Compile).value, - mavlinkGenerate in Compile := generationTask.value, - sourceGenerators in Compile += (mavlinkGenerate in Compile).taskValue + mavlinkDialect := baseDirectory.value / "conf" / "mavlink.xml", + mavlinkTarget := sourceManaged.value, + mavlinkGenerate := generationTask.value, + sourceGenerators in Compile += mavlinkGenerate.taskValue ) lazy val generationTask = Def.task[Seq[File]] { - val dialectDefinitionFile = (mavlinkDialect in Compile).value + val dialectDefinitionFile = mavlinkDialect.value if (!dialectDefinitionFile.exists) sys.error( "Dialect definition " + dialectDefinitionFile.getAbsolutePath + " does not exist." @@ -33,13 +33,13 @@ object SbtMavlink extends AutoPlugin { val dialect = Parser.parseDialect(dialectDefinition) val pathToSource = (new Generator(dialect)).generate() - val outDirectory = (mavlinkTarget in Compile).value + val outDirectory = mavlinkTarget.value streams.value.log.info("Generating mavlink files...") val files = for ((path, source) <- pathToSource) yield { - streams.value.log.debug("Generating " + path) val file = outDirectory / path + streams.value.log.info("Generating " + file) IO.write(file, source) file.getAbsoluteFile } diff --git a/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/build.sbt b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/build.sbt new file mode 100644 index 0000000..d4035f2 --- /dev/null +++ b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/build.sbt @@ -0,0 +1,11 @@ +import com.github.jodersky.mavlink.sbt.MavlinkKeys._ + +mavlinkDialect := baseDirectory.value / "mavlink.xml" + +scalaVersion := "2.10.4" + +name := "test" + +organization := "test" + +version := "1.0"
\ No newline at end of file diff --git a/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/mavlink.xml b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/mavlink.xml new file mode 100644 index 0000000..fcbdc35 --- /dev/null +++ b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/mavlink.xml @@ -0,0 +1,115 @@ +<?xml version='1.0'?> +<mavlink> + <version>1</version> + <enums> + <enum name="MAV_STATE"> + <entry value="0" name="MAV_STATE_UNINIT"> + <description>Uninitialized system, state is unknown.</description> + </entry> + <entry value="1" name="MAV_STATE_BOOT"> + <description>System is booting up.</description> + </entry> + <entry value="2" name="MAV_STATE_CALIBRATING"> + <description>System is calibrating and not flight-ready.</description> + </entry> + <entry value="3" name="MAV_STATE_STANDBY"> + <description>System is grounded and on standby. It can be launched any time.</description> + </entry> + <entry value="4" name="MAV_STATE_ACTIVE"> + <description>System is active and might be already airborne. Motors are engaged.</description> + </entry> + <entry value="5" name="MAV_STATE_CRITICAL"> + <description>System is in a non-normal flight mode. It can however still navigate.</description> + </entry> + <entry value="6" name="MAV_STATE_EMERGENCY"> + <description>System is in a non-normal flight mode. It lost control over parts or over the whole airframe. It is in mayday and going down.</description> + </entry> + <entry value="7" name="MAV_STATE_POWEROFF"> + <description>System just initialized its power-down sequence, will shut down now.</description> + </entry> + + </enum> + </enums> + <messages> + <message id="0" name="HEARTBEAT"> + <description>The heartbeat message shows that a system is present and responding.</description> + <field type="uint8_t" name="system_state" enum="MAV_STATE">Global state of system.</field> + </message> + <message id="1" name="POWER"> + <description>Information about the main power source.</description> + <field type="uint16_t" name="voltage">Voltage of the source (mV)</field> + </message> + <message id="2" name="IMU"> + <description>The IMU readings in a NED body frame</description> + <field type="int32_t" name="xacc">X acceleration (mm/s^2)</field> + <field type="int32_t" name="yacc">Y acceleration (mm/s^2)</field> + <field type="int32_t" name="zacc">Z acceleration (mm/s^2)</field> + <field type="int32_t" name="xgyro">Angular speed around X axis (mrad / sec)</field> + <field type="int32_t" name="ygyro">Angular speed around Y axis (mrad / sec)</field> + <field type="int32_t" name="zgyro">Angular speed around Z axis (mrad / sec)</field> + <field type="int32_t" name="xmag">X Magnetic field (uT)</field> + <field type="int32_t" name="ymag">Y Magnetic field (uT)</field> + <field type="int32_t" name="zmag">Z Magnetic field (uT)</field> + <field type="int32_t" name="alt">Altitude to mean sea level (mm)</field> + <field type="uint32_t" name="temperature">Ambient temperature (mK)</field> + </message> + <message id="3" name="DISTANCE"> + <description>Information on distance sensors</description> + <field type="int16_t" name="relative_alt">Relative altitude to ground (mm)</field> + </message> + <message name="PING" id="4"> + <description>Ping a target system, usually used to determine latency.</description> + <field type="uint8_t" name="target_system">System ID</field> + <field type="uint8_t" name="target_component">Component ID</field> + </message> + <message name="ACK" id="5"> + <description>Acknowledgement packet</description> + <field type="uint8_t" name="target_system">System ID</field> + <field type="uint8_t" name="target_component">Component ID</field> + </message> + <message name="MOTOR" id="6"> + <description>Status of motors</description> + <field type="uint8_t" name="m0">m0</field> + <field type="uint8_t" name="m1">m1</field> + <field type="uint8_t" name="m2">m2</field> + <field type="uint8_t" name="m3">m3</field> + </message> + <message id="30" name="ATTITUDE"> + <description>The attitude in the aeronautical frame (right-handed, Z-down, X-front, Y-right).</description> + <field type="int16_t" name="roll">Roll angle</field> + <field type="int16_t" name="pitch">Pitch angle</field> + <field type="uint16_t" name="yaw">Yaw angle</field> + </message> + <message id="70" name="RC_CHANNELS_OVERRIDE"> + <description>The RAW values of the RC channels sent to the MAV to override info received from the RC radio. A value of UINT16_MAX means no change to that channel. A value of 0 means control of that channel should be released back to the RC radio. The standard PPM modulation is as follows: 1000 microseconds: 0%, 2000 microseconds: 100%. Individual receivers/transmitters might violate this specification.</description> + <field type="uint8_t" name="target_system">System ID</field> + <field type="uint8_t" name="target_component">Component ID</field> + <field type="uint16_t" name="chan1_raw">RC channel 1 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan2_raw">RC channel 2 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan3_raw">RC channel 3 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan4_raw">RC channel 4 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan5_raw">RC channel 5 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan6_raw">RC channel 6 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan7_raw">RC channel 7 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + <field type="uint16_t" name="chan8_raw">RC channel 8 value, in microseconds. A value of UINT16_MAX means to ignore this field.</field> + </message> + <message name="RADIO_STATUS" id="109"> + <description>Status generated by radio</description> + <field type="uint8_t" name="rssi">local signal strength</field> + <field type="uint8_t" name="remrssi">remote signal strength</field> + <field type="uint8_t" name="txbuf">how full the tx buffer is as a percentage</field> + <field type="uint8_t" name="noise">background noise level</field> + <field type="uint8_t" name="remnoise">remote background noise level</field> + <field type="uint16_t" name="rxerrors">receive errors</field> + <field type="uint16_t" name="fixed">count of error corrected packets</field> + </message> + <message name="TEST_MESSAGE" id="110"> + <description>Test</description> + <field type="uint8_t[2]" name="bytearray">a byte array</field> + <field type="float[20]" name="floatarray">a float array</field> + <field type="char" name="chars">a char</field> + <field type="double" name="doubles">a double</field> + <field type="char[20]" name="strings">a string</field> + </message> + </messages> +</mavlink> diff --git a/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/project/plugins.sbt b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/project/plugins.sbt new file mode 100644 index 0000000..c2bb2a1 --- /dev/null +++ b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.github.jodersky" % "sbt-mavlink" % sys.props("plugin.version"))
\ No newline at end of file diff --git a/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/src/main/scala/Main.scala b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/src/main/scala/Main.scala new file mode 100644 index 0000000..6c84968 --- /dev/null +++ b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/src/main/scala/Main.scala @@ -0,0 +1,53 @@ +import org.mavlink._ +import org.mavlink.messages._ + +object Main { + + val SenderSystemId = 0: Byte + val SenderComponentId = 0: Byte + val ReceiverSystemId = 1: Byte + val ReceiverComponentId = 0: Byte + + def main(args: Array[String]): Unit = { + echoTest() + } + + def echoTest() = { + //represents the line buffer, i.e. all data going in and out + val line = new Array[Byte](Packet.MaxPacketLength) + + //payload of incoming messages + val in = MavlinkBuffer.allocate() + + //parser to transform an incoming byte stream into packets + val parser = new Parser(in)( + pckt => { + val msg = Message.unpack(pckt.messageId, pckt.payload) + println("received message: " + msg) + }, + err => { + sys.error("parse error: " + err) + } + ) + + //payload buffer of outgoing messages + val out = MavlinkBuffer.allocate() + + //assembles messages into pakets from a specific sender + val assembler = new Assembler(SenderSystemId, SenderComponentId) + + //create an explicit message + val message = Heartbeat(0) + + //pack the message into a payload + val id = Message.pack(message, out) + + //assemble into packet + val packet = assembler.assemble(id, out) + + //simulate wire transfer + packet.writeTo(line) + parser.push(line) + } + +}
\ No newline at end of file diff --git a/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/test b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/test new file mode 100644 index 0000000..c009de9 --- /dev/null +++ b/mavlink-plugin/src/sbt-test/sbt-mavlink/codec/test @@ -0,0 +1,3 @@ +# check if the files get created +> run +$ exists target/scala-2.10/src_managed/org/mavlink
\ No newline at end of file diff --git a/project/Build.scala b/project/Build.scala index ddf108e..c0c4f4e 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -2,6 +2,7 @@ import sbt._ import sbt.Keys._ import play.twirl.sbt.SbtTwirl import play.twirl.sbt.Import._ +import sbt.ScriptedPlugin._ object ApplicationBuild extends Build { @@ -31,9 +32,15 @@ object ApplicationBuild extends Build { lazy val plugin = ( Project("mavlink-plugin", file("mavlink-plugin")) settings(common: _*) + settings(ScriptedPlugin.scriptedSettings: _*) settings( sbtPlugin := true, - name := "sbt-mavlink" + name := "sbt-mavlink", + scriptedLaunchOpts := { scriptedLaunchOpts.value ++ + Seq("-Xmx1024M", "-XX:MaxPermSize=256M", "-Dplugin.version=" + version.value) + }, + scriptedBufferLog := false, + publishLocal <<= publishLocal.dependsOn(publishLocal in library) ) dependsOn(library) ) diff --git a/project/scripted.sbt b/project/scripted.sbt new file mode 100644 index 0000000..c3b4f97 --- /dev/null +++ b/project/scripted.sbt @@ -0,0 +1,3 @@ +libraryDependencies <+= (sbtVersion) { sv => + "org.scala-sbt" % "scripted-plugin" % sv +}
\ No newline at end of file diff --git a/project/plugins.sbt b/project/twirl.sbt index 7b458b6..7b458b6 100644 --- a/project/plugins.sbt +++ b/project/twirl.sbt |