From 053dac10a85feea51cf6cb3435b3d3f08e4e0ddb Mon Sep 17 00:00:00 2001 From: yvesf Date: Sun, 3 Jul 2011 22:29:43 +0200 Subject: noch fehlerhaft, keine Master-Slave erkennung --- ebus-scala/Main.scala | 165 ++++++++++++++++++++++++++++++++++++-------------- ebus-scala/README | 3 + 2 files changed, 124 insertions(+), 44 deletions(-) create mode 100644 ebus-scala/README diff --git a/ebus-scala/Main.scala b/ebus-scala/Main.scala index 8202eb1..8444f37 100644 --- a/ebus-scala/Main.scala +++ b/ebus-scala/Main.scala @@ -1,39 +1,59 @@ import Stream._ import java.io.{ InputStream, EOFException } import java.net.{ InetAddress, InetSocketAddress, Socket } +import scala.xml.{XML, Node, NodeSeq} class EbusDefinition(val ebusXmlFile: String) { - import scala.xml.XML - import scala.xml.NodeSeq - val xml = XML.loadFile(ebusXmlFile) def packetFromCommandId(primaryCommand: Char, secondaryCommand: Char): NodeSeq = { val packet = (xml \ "packets" \ "packet").filter(n => n.attribute("primary").get.text.toInt == primaryCommand && - n.attribute("secondary").get.text.toInt == secondaryCommand) + n.attribute("secondary").get.text.toInt == secondaryCommand) packet } } -class EbusPacket(val source: Char, - val destination: Char, - val primaryCommand: Char, - val secondaryCommand: Char, - val payloadLength: Char, - val payload: List[Char], - val crc: Char, - val rawLength: Int) { +abstract class EbusField(val name : String, val offset : Int); +class Data2c(override val name: String, override val offset : Int) extends EbusField(name, offset) { +} + +object EbusField { + def getFields(ebusDefinition : EbusDefinition, primaryCommand: Char, secondaryCommand: Char): List[EbusField] = { + val packetDef = ebusDefinition.packetFromCommandId(primaryCommand, secondaryCommand) + for (fieldDef <- (packetDef \ "fields").head.child) { + App.println(buildField(fieldDef)) + } + null + } + def buildField(field :Node) : Option[EbusField] = { + if (field.label == "data2c") { + val name = field.attribute("name").get.text + val offset = field.attribute("offset").get.text.toInt + return Some(new Data2c(name, offset)) + } + return None + } +} + +class EbusL2Packet(val source: Char, + val destination: Char, + val primaryCommand: Char, + val secondaryCommand: Char, + val payloadLength: Char, + val payload: List[Char], + val crc: Char, + val rawLength: Int) { val length = 6 + payload.size override def toString: String = { val p = if (payload.size == 0) "" - else - payload.map(a => "%02x".format(a.toInt)). - reduceLeft((a: Any, b: String) => a + " " + b) + else + payload.map(a => "%02x".format(a.toInt)). + reduceLeft((a: Any, b: String) => a + " " + b) - "Ebus: d=%02x pC=%02x sC=%02x pL=%02x crc=%02x p=%s".format( + "L2Packet: d=%02x pC=%02x sC=%02x pL=%02x crc=%02x p=%s".format( destination.toInt, primaryCommand.toInt, secondaryCommand.toInt, payloadLength.toInt, crc.toInt, p.toString) } @@ -54,15 +74,15 @@ class EbusPacket(val source: Char, } } -object EbusPacket { +object EbusL2Packet { /** * Wird von {@link EbusReader} mit einer Streamposition aufgerufen. * Ausgehend von dieser Position wird versucht ein Paket aufzubauen, * und anschliesend die Checksumme geprüft. - * Im Erfolgsfall wird eine EbusPacket-Instanz als Option zurückgegen, + * Im Erfolgsfall wird eine EbusL2Packet-Instanz als Option zurückgegen, * sonst None */ - def apply(stream: Stream[Int]): Option[EbusPacket] = { + def apply(stream: Stream[Int]): Option[EbusL2Packet] = { try { var rawLength = 0 val source = stream.apply(0).toChar @@ -72,6 +92,11 @@ object EbusPacket { val payloadLength = stream.apply(4).toChar rawLength = 5 + // Maximale payload Grösse = 16 Byte + if (payloadLength > 16) { + println("Erkannte payload Groesse zu gross: %d".format(payloadLength.toInt)) + return None + } var payload = List[Char]() for (i <- 0 until payloadLength) { var it = stream.apply(rawLength).toChar @@ -87,22 +112,31 @@ object EbusPacket { } else if (itNext == 0x01.toChar) { it = 0xaa.toChar } else { - println("Ignore escape sequence 0xa9 0x%02x".format(itNext)) + App.println("Ignore escape sequence 0xa9 0x%02x".format(itNext)) rawLength -= 1 } } - //payload.update(i, it) payload = payload :+ it } val crc = stream.apply(5 + payloadLength).toChar - rawLength += 1 - - return Some(new EbusPacket(source, destination, - primaryCommand, secondaryCommand, - payloadLength, payload, crc, rawLength)) + val ack = stream.apply(6 + payloadLength).toChar + if (ack != 0x00.toChar) { + println("Fehlerhaftes ACK") + return None + } + rawLength += 2 + + if (stream.apply(6+payloadLength).toChar == 0xaa.toChar) { + // Broadcast oder Master-Master + return Some(new EbusL2Packet(source, destination, + primaryCommand, secondaryCommand, + payloadLength, payload, crc, rawLength)) + } else { + // Master-Slave + } } catch { case exc: IndexOutOfBoundsException => { - println(exc.toString) + App.println(exc.toString) exc.printStackTrace return None } @@ -111,22 +145,26 @@ object EbusPacket { } object EbusReader { - def apply(streamI: Stream[Int]): EbusPacket = { + def apply(streamI: Stream[Int]) : EbusL2Packet = { var stream = streamI while (true) { // Überspringe Synchronisationszeichen - stream = stream.dropWhile(v => v.toChar == 0xaa.toChar) + //stream = stream.dropWhile(v => v.toChar == 0xaa.toChar) + // Überspringe solange nicht mindestens 6 Zeichen ohne 0xaa vorkommen + while (stream.take(6).filter({v :Int => v.toChar == 0xaa.toChar}).size > 0) { +// println("skip") + stream = stream.drop(1) + } - EbusPacket(stream) match { + EbusL2Packet(stream) match { case Some(packet) => { - stream = stream.drop(packet.rawLength) return packet } case None => { // Es konnte kein Paket eingelesen werden - // verschieben die Anfangsposition um ein Byte + // verschiebe die Anfangsposition um ein Byte stream = stream.drop(1) - println("skip 1 byte") + App.println("skip 1 byte") } } } @@ -134,12 +172,39 @@ object EbusReader { } } +object EbusL7Packet { + def apply(l2packet : EbusL2Packet, ebusDefinition : EbusDefinition) + : Option[EbusL7Packet] = { + val packetDef = ebusDefinition.packetFromCommandId( + l2packet.primaryCommand, l2packet.secondaryCommand) + + if (packetDef.isEmpty) + return None + else + return Some(new EbusL7Packet(l2packet, packetDef)) + } +} + +class EbusL7Packet(val l2packet : EbusL2Packet, val packetDefinition : NodeSeq) { + def name : String = { + packetDefinition.map({p :Node => p.attributes.apply("name")}).mkString + } + + override def toString : String = { + "EbusL7: name=%s".format(name) + } +} + object App { val ebusDefinition = new EbusDefinition("/home/yvesf/vcs/ebus/ebus/ebus-xml/ebus.xml") var source: InputStream = null + + def println(msg : Any) { + Predef.println("[ebus] " + msg.toString) + } def main(args: Array[String]): Unit = { - if (args.size == 1) { + if (args.size == 1 && args(0) == "-") { println("Use stdin as source") source = System.in } else if (args.size == 2) { @@ -157,15 +222,20 @@ object App { System.err.println("Connected to %s %d".format(args(1), args(2).toInt)) while (true) { val v = s.getInputStream.read - if (v == -1) + if (v == -1) { + println("Fehler: las -1") System.exit(1) + } print(v.toChar) } } else { println("Missing Arguments") - println(" Read from stdin: -") - println(" Read from TCP: HOST PORT") - println(" Read from TCP and dump to stdout: dump HOST PORT") + println(" -") + println(" Read from stdin") + println("HOST PORT") + println(" Read from TCP Server") + println("dump HOST PORT") + println(" Dump TCP-Stream") System.exit(1) } @@ -175,18 +245,25 @@ object App { throw new EOFException("End of File reached (read returned -1)") value }) - val stream: Stream[Int] = Stream.continually(read()) + var stream: Stream[Int] = Stream.continually(read()) + while (true) { EbusReader(stream) match { - case x: EbusPacket => { - println(x) - val p = ebusDefinition.packetFromCommandId(x.primaryCommand, x.secondaryCommand) - if (p.size == 1) - println(p(0).attribute("name").get) + case l2packet : EbusL2Packet => { + EbusL7Packet(l2packet, ebusDefinition) match { + case Some(l7packet) => { + println(l7packet) + } + case _ => {} + } + println(l2packet) + // Spule den Stream zur naechstmoeglichen Paketposition + stream = stream.drop(l2packet.rawLength) } case null => { println("null") + System.exit(1) } } } diff --git a/ebus-scala/README b/ebus-scala/README new file mode 100644 index 0000000..f2e3923 --- /dev/null +++ b/ebus-scala/README @@ -0,0 +1,3 @@ +=== Start + +./run.sh 10.2.2.200 7970 -- cgit v1.2.1