summaryrefslogtreecommitdiff
path: root/ebus-scala/Main.scala
diff options
context:
space:
mode:
Diffstat (limited to 'ebus-scala/Main.scala')
-rw-r--r--ebus-scala/Main.scala165
1 files changed, 121 insertions, 44 deletions
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)
}
}
}