diff --git a/otherdevices.xml b/otherdevices.xml index a701922..b54db6b 100644 --- a/otherdevices.xml +++ b/otherdevices.xml @@ -1,5 +1,5 @@ - 192.168.56.101 + 192.168.56.20 192.168.56.102 diff --git a/src/main/scala/tum/in/net/bacnet/MyMain.scala b/src/main/scala/tum/in/net/bacnet/MyMain.scala index 3c634ae..c60712a 100644 --- a/src/main/scala/tum/in/net/bacnet/MyMain.scala +++ b/src/main/scala/tum/in/net/bacnet/MyMain.scala @@ -1,115 +1,9 @@ package tum.in.net.bacnet +import tum.in.net.bacnet.deviceFactory.{MySlaveDevice, MyReader, MyReaderWriterActiveMasterSlaveDevice} -import com.serotonin.bacnet4j._ -import com.serotonin.bacnet4j.`type`.constructed._ -import com.serotonin.bacnet4j.`type`.primitive -import com.serotonin.bacnet4j.`type`.enumerated._ -import com.serotonin.bacnet4j.`type`.notificationParameters._ -import com.serotonin.bacnet4j.`type`.Encodable -import com.serotonin.bacnet4j.service.confirmed.ReinitializeDeviceRequest._ -import com.serotonin.bacnet4j.obj._ -class MyReader(val localDevice: MyLocalDevice = new MyLocalDevice( - broadcastAddress = "127.0.0.255", - name = "corny's reader", - deviceId=1234), abortOnNoRemotes: Boolean = true){ - - def readConfigFromXML(file: java.io.File): List[String] = { - println("reading configuration file "+file) - val knownDevicesFromConfig = scala.io.Source.fromFile(file) - val otherDevicesString: String = try { - knownDevicesFromConfig.mkString - } finally { - knownDevicesFromConfig.close() - } - import scala.xml._ - require(!otherDevicesString.isEmpty()) - - // config template - // val xmlOtherDevices = - // 192.168.56.102 - // 192.168.56.103 - // 192.168.56.104 - // - - val xmlOtherDevices = XML.loadString(otherDevicesString) - assert(xmlOtherDevices.isInstanceOf[scala.xml.Elem]) - val deviceIPs: NodeSeq = (xmlOtherDevices \\ "bacdevices") - try{ - assert(!deviceIPs.isEmpty) - } catch { - case e: java.lang.AssertionError => - println("Error: "+e) - if (abortOnNoRemotes) - throw e - else - println("continue") - } - val deviceIPsList: List[String] = (for (node <- (deviceIPs \\ "device"))yield node.text).toList - println("parsed devices from config: "+deviceIPsList) - deviceIPsList - } - - val otherDevices: List[String] = readConfigFromXML(new java.io.File("otherdevices.xml")) - - - val localReader = new SlaveDeviceReading(localDevice=localDevice, - otherDevices=otherDevices, - abortOnNoRemotes=abortOnNoRemotes) - - def start(initLocalDevice: Boolean = true) = { - if (initLocalDevice){ - localDevice.initialize() - } - localReader.start() - // TODO - // we could pass abortOnNoRemotes=true and catch the assertion error, if no remote devices are found - // retry every X seconds - // although, this is better done in the SlaveDeviceReading's act method act - } -} - -class MyReaderWriterActiveMasterSlaveDevice{ - - val hostname: String = try { - java.net.InetAddress.getLocalHost.getHostName - }catch{ - case e: java.net.UnknownHostException => - println("Error: "+e) - val hostnameguess_array = e.toString().split(' ') - if (hostnameguess_array.length < 2){ - null - } - - val hostnameguess = hostnameguess_array(hostnameguess_array.length - 1) - if (hostnameguess.length() >= 5){ - println("guessing hostname `"+hostnameguess+"'") - hostnameguess - } else { - null - } - } - - /* acts, changes values */ - val localSlaveDevice = new MySlaveDevice( - broadcastAddress = "127.0.0.255", - name=hostname, - randomValues=true) - - val localDevice = localSlaveDevice.localDevice - - val localReader = new MyReader(localDevice, abortOnNoRemotes=false) - - - def start() = { - localSlaveDevice.start() - localReader.start(initLocalDevice=false) - } - -} - object MyMain { def slave(): Unit = { diff --git a/src/main/scala/tum/in/net/bacnet/deviceFactory/MyBACnetDevices.scala b/src/main/scala/tum/in/net/bacnet/deviceFactory/MyBACnetDevices.scala new file mode 100644 index 0000000..7c4be0c --- /dev/null +++ b/src/main/scala/tum/in/net/bacnet/deviceFactory/MyBACnetDevices.scala @@ -0,0 +1,116 @@ +package tum.in.net.bacnet.deviceFactory + + +import tum.in.net.bacnet.lowlevel.device.MyLocalDevice +import tum.in.net.bacnet.lowlevel.SlaveDeviceReading + + +/** + * reads an xml file with other known BACnet devices + * queries and sets their values + * supervisory device + */ +class MyReader(val localDevice: MyLocalDevice = new MyLocalDevice( + broadcastAddress = "127.0.0.255", + name = "corny's reader", + deviceId=1234), abortOnNoRemotes: Boolean = true){ + + def readConfigFromXML(file: java.io.File): List[String] = { + println("reading configuration file "+file) + val knownDevicesFromConfig = scala.io.Source.fromFile(file) + val otherDevicesString: String = try { + knownDevicesFromConfig.mkString + } finally { + knownDevicesFromConfig.close() + } + import scala.xml._ + require(!otherDevicesString.isEmpty()) + + // config template + // val xmlOtherDevices = + // 192.168.56.102 + // 192.168.56.103 + // 192.168.56.104 + // + + val xmlOtherDevices = XML.loadString(otherDevicesString) + assert(xmlOtherDevices.isInstanceOf[scala.xml.Elem]) + val deviceIPs: NodeSeq = (xmlOtherDevices \\ "bacdevices") + try{ + assert(!deviceIPs.isEmpty) + } catch { + case e: java.lang.AssertionError => + println("Error: "+e) + if (abortOnNoRemotes) + throw e + else + println("continue") + } + val deviceIPsList: List[String] = (for (node <- (deviceIPs \\ "device"))yield node.text).toList + println("parsed devices from config: "+deviceIPsList) + deviceIPsList + } + + val otherDevices: List[String] = readConfigFromXML(new java.io.File("otherdevices.xml")) + + + val localReader = new SlaveDeviceReading(localDevice=localDevice, + otherDevices=otherDevices, + abortOnNoRemotes=abortOnNoRemotes) + + def start(initLocalDevice: Boolean = true) = { + if (initLocalDevice){ + localDevice.initialize() + } + localReader.start() + // TODO + // we could pass abortOnNoRemotes=true and catch the assertion error, if no remote devices are found + // retry every X seconds + // although, this is better done in the SlaveDeviceReading's act method act + } +} + + +/** + * reads an xml file with other known BACnet devices + * queries and sets their values + * Also is an active BACnet device with changing Input/Output values + */ +class MyReaderWriterActiveMasterSlaveDevice{ + + val hostname: String = try { + java.net.InetAddress.getLocalHost.getHostName + }catch{ + case e: java.net.UnknownHostException => + println("Error: "+e) + val hostnameguess_array = e.toString().split(' ') + if (hostnameguess_array.length < 2){ + null + } + + val hostnameguess = hostnameguess_array(hostnameguess_array.length - 1) + if (hostnameguess.length() >= 5){ + println("guessing hostname `"+hostnameguess+"'") + hostnameguess + } else { + null + } + } + + /* acts, changes values */ + val localSlaveDevice = new MySlaveDevice( + broadcastAddress = "127.0.0.255", + name=hostname, + randomValues=true) + + val localDevice = localSlaveDevice.localDevice + + val localReader = new MyReader(localDevice, abortOnNoRemotes=false) + + + def start() = { + localSlaveDevice.start() + localReader.start(initLocalDevice=false) + } + +} \ No newline at end of file diff --git a/src/main/scala/tum/in/net/bacnet/MySlaveDevice.scala b/src/main/scala/tum/in/net/bacnet/deviceFactory/MySlaveDevice.scala similarity index 90% rename from src/main/scala/tum/in/net/bacnet/MySlaveDevice.scala rename to src/main/scala/tum/in/net/bacnet/deviceFactory/MySlaveDevice.scala index 9425b75..b56cfd3 100644 --- a/src/main/scala/tum/in/net/bacnet/MySlaveDevice.scala +++ b/src/main/scala/tum/in/net/bacnet/deviceFactory/MySlaveDevice.scala @@ -1,8 +1,19 @@ -package tum.in.net.bacnet +package tum.in.net.bacnet.deviceFactory import com.serotonin.bacnet4j.`type`.enumerated._ -import com.serotonin.bacnet4j.LocalDevice +import tum.in.net.bacnet.lowlevel.device.MyLocalDevice +import tum.in.net.bacnet.lowlevel.SlaveDeviceIO +import tum.in.net.bacnet.lowlevel.IOTypeOutput +import tum.in.net.bacnet.lowlevel.IOTypeInput +import tum.in.net.bacnet.lowlevel.IOType + +/** + * Generic Class to instantiate a BACnet device + * with I/O + * @author corny + * + */ class MySlaveDevice(broadcastAddress: String, name: String = null, randomValues: Boolean = false) { val random = if (randomValues) new scala.util.Random() else null diff --git a/src/main/scala/tum/in/net/bacnet/SlaveDeviceIO.scala b/src/main/scala/tum/in/net/bacnet/lowlevel/SlaveDeviceIO.scala similarity index 97% rename from src/main/scala/tum/in/net/bacnet/SlaveDeviceIO.scala rename to src/main/scala/tum/in/net/bacnet/lowlevel/SlaveDeviceIO.scala index cb60f0e..7aff934 100644 --- a/src/main/scala/tum/in/net/bacnet/SlaveDeviceIO.scala +++ b/src/main/scala/tum/in/net/bacnet/lowlevel/SlaveDeviceIO.scala @@ -1,22 +1,26 @@ -package tum.in.net.bacnet +package tum.in.net.bacnet.lowlevel import com.serotonin.bacnet4j._ import com.serotonin.bacnet4j.`type`.constructed._ import com.serotonin.bacnet4j.`type`.primitive import com.serotonin.bacnet4j.`type`.enumerated._ import com.serotonin.bacnet4j.`type`.notificationParameters._ -import com.serotonin.bacnet4j.`type`.Encodable import com.serotonin.bacnet4j.service.confirmed.ReinitializeDeviceRequest._ import com.serotonin.bacnet4j.obj._ - import scala.actors.Actor import scala.actors.Actor._ +import tum.in.net.bacnet.lowlevel.device.MyLocalDevice abstract sealed class IOType case object IOTypeInput extends IOType case object IOTypeOutput extends IOType +/** + * Add to BACnet device `localDevice` Input/Ouput values + * @author corny + * + */ class SlaveDeviceIO( val localDevice: MyLocalDevice, ConfiguredAnalogueIO: List[(IOType, String, EngineeringUnits)], diff --git a/src/main/scala/tum/in/net/bacnet/SlaveDeviceReading.scala b/src/main/scala/tum/in/net/bacnet/lowlevel/SlaveDeviceReading.scala similarity index 96% rename from src/main/scala/tum/in/net/bacnet/SlaveDeviceReading.scala rename to src/main/scala/tum/in/net/bacnet/lowlevel/SlaveDeviceReading.scala index da775b6..c73afcc 100644 --- a/src/main/scala/tum/in/net/bacnet/SlaveDeviceReading.scala +++ b/src/main/scala/tum/in/net/bacnet/lowlevel/SlaveDeviceReading.scala @@ -1,4 +1,4 @@ -package tum.in.net.bacnet +package tum.in.net.bacnet.lowlevel import com.serotonin.bacnet4j._ import com.serotonin.bacnet4j.`type`.constructed._ @@ -11,7 +11,19 @@ import com.serotonin.bacnet4j.obj._ import scala.actors.Actor import scala.actors.Actor._ import scala.actors.TIMEOUT +import tum.in.net.bacnet.lowlevel.device.BACListeneriAmReceived +import tum.in.net.bacnet.lowlevel.device.MyLocalDevice +import scala.collection.JavaConversions.asScalaBuffer +import scala.collection.JavaConversions.iterableAsScalaIterable +import scala.collection.JavaConversions.mapAsScalaMap +import scala.collection.JavaConversions.seqAsJavaList +/** + * Add to BACnet device `localDevice` more features + * Read/write/query values from other BACnet devices + * @author corny + * + */ class SlaveDeviceReading ( val localDevice: MyLocalDevice, val otherDevices: List[String], diff --git a/src/main/scala/tum/in/net/bacnet/BACDummyListener.scala b/src/main/scala/tum/in/net/bacnet/lowlevel/device/BACDummyListener.scala similarity index 99% rename from src/main/scala/tum/in/net/bacnet/BACDummyListener.scala rename to src/main/scala/tum/in/net/bacnet/lowlevel/device/BACDummyListener.scala index bc33540..ead922d 100644 --- a/src/main/scala/tum/in/net/bacnet/BACDummyListener.scala +++ b/src/main/scala/tum/in/net/bacnet/lowlevel/device/BACDummyListener.scala @@ -1,4 +1,4 @@ -package tum.in.net.bacnet +package tum.in.net.bacnet.lowlevel.device import com.serotonin.bacnet4j._ import com.serotonin.bacnet4j.`type`.constructed._ @@ -10,7 +10,6 @@ import com.serotonin.bacnet4j.service.confirmed.ReinitializeDeviceRequest._ import com.serotonin.bacnet4j.obj._ - abstract sealed trait BACListenerMessage case class BACListeneriAmReceived(d: RemoteDevice) extends BACListenerMessage diff --git a/src/main/scala/tum/in/net/bacnet/MyLocalDevice.scala b/src/main/scala/tum/in/net/bacnet/lowlevel/device/MyLocalDevice.scala similarity index 94% rename from src/main/scala/tum/in/net/bacnet/MyLocalDevice.scala rename to src/main/scala/tum/in/net/bacnet/lowlevel/device/MyLocalDevice.scala index 142520d..e544469 100644 --- a/src/main/scala/tum/in/net/bacnet/MyLocalDevice.scala +++ b/src/main/scala/tum/in/net/bacnet/lowlevel/device/MyLocalDevice.scala @@ -1,4 +1,4 @@ -package tum.in.net.bacnet +package tum.in.net.bacnet.lowlevel.device import com.serotonin.bacnet4j._ @@ -9,7 +9,16 @@ import com.serotonin.bacnet4j.`type`.notificationParameters._ import com.serotonin.bacnet4j.`type`.Encodable import com.serotonin.bacnet4j.service.confirmed.ReinitializeDeviceRequest._ import com.serotonin.bacnet4j.obj._ +import scala.Array.canBuildFrom +import scala.collection.JavaConversions.asScalaBuffer + +/** + * My local BACnet device + * Other classes in the lowlevel package extend its functionality + * @author corny + * + */ class MyLocalDevice(val broadcastAddress: String, val name: String, val deviceId: Int, // make sure this value is unique!