Simple Examples
-
Hi,
I cant get the test-examples to work. I am new to bacnet - so I eventually missed something in DiscoveryTest and Test.
My problem with the sources are the IP addresses (LocalDevice 192.168.60.255) maybe use the local loopback 127.0.0.255?
The RemoteDevice uses 206.210.100.134 - use instead 127.0.0.1 as address?Or are these tests not intended to work as is in software only?
Arne
-
Hi Arne,
Are you just trying to discover your remote device? I'm not sure what problem you're having.
-
I tried it without any bacnet hardware.
The docs says one can use the software as device (maybe 1-wire to bacnet gateway on PC)?
or I misunderstand the docs?
Arne
-
Yes, the software will work in a software-only environment, but you need to be careful in choosing port numbers. BACnet4J actually works better than some commercial packages in this regard in the sense that it properly will handle broadcasts when non-standard port numbers are used, but that doesn't let the developer off the hook. :) The problem is that when you run BACnet4J on a single host, only one of them can have the standard port number 0xBAC0.
For example, I'll use the SlaveDeviceTest included in the source. It creates a device that listens on port 2068. When i want to discover this device on the same workstation (say, using DiscoveryTest), i need to make sure the LocalDevice i use there listens on a different port number, and that i send my WhoIs broadcast to port 2068.
This code should do the trick:
LocalDevice localDevice = new LocalDevice(1234, "192.168.0.255"); localDevice.initialize(); localDevice.sendBroadcast(2068, new WhoIsRequest(null, null));
... at least, when you add in the code that lists out discovered devices (also in DiscoveryTest).
-
I changedt the IP-Addresses to localhost ans set the Port of the localDevice to default +1.
running this I get an:com.serotonin.bacnet4j.exception.ErrorAPDUException: ErrorAPDU(choice=12, errorClass=Object, errorCode=Unknown object
at: localDevice.getExtendedDeviceInformation(d);
Any Idea what happend?
@SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { LocalDevice localDevice = new LocalDevice(1234, "127.0.0.255"); localDevice.setPort(LocalDevice.DEFAULT_PORT + 1); localDevice.initialize(); try { RemoteDevice rd = new RemoteDevice(105, new Address(new UnsignedInteger(LocalDevice.DEFAULT_PORT), new OctetString(new byte[]{127, 0, 0, 1})), null); rd.setSegmentationSupported(Segmentation.segmentedBoth); rd.setMaxAPDULengthAccepted(1476); localDevice.addRemoteDevice(rd); // Wait a bit for responses to come in. Thread.sleep(2000); // Get extended information for all remote devices. for (RemoteDevice d : localDevice.getRemoteDevices()) { localDevice.getExtendedDeviceInformation(d); List<ObjectIdentifier> oids = ((SequenceOf<ObjectIdentifier>) localDevice.sendReadPropertyAllowNull( d, d.getObjectIdentifier(), PropertyIdentifier.objectList)).getValues(); PropertyReferences refs = new PropertyReferences(); for (ObjectIdentifier oid : oids) { addPropertyReferences(refs, oid); } localDevice.readProperties(d, refs); System.out.println(d); } // Wait a bit for responses to come in. Thread.sleep(2000); } finally { localDevice.terminate(); } }
If you add the following constructot to OctetSting:
public OctetString(int ... intValues) { this.value = new byte[intValues.length]; for (int i = 0; i < intValues.length; i++) { this.value* = (byte)intValues*; } }
One can write ```
new OctetString(206, 210, 100, 134);Arne
-
Hi Arne,
I think i see what the problem is. The DiscoveryTest code has been modified over time to suit some different tests, and so not all of the code in there is necessary for what you want to do. In particular you do not need to declare remote devices yourself - this would defeat the purpose of discovery after all. All the code you should need is this (I have not compiled or tested this, so modify as required):
public static void main(String[] args) throws Exception { LocalDevice localDevice = new LocalDevice(1234, "192.168.0.255"); localDevice.initialize(); // Who is localDevice.sendBroadcast(2068, new WhoIsRequest(null, null)); // Wait a bit for responses to come in. Thread.sleep(1000); // Get extended information for all remote devices. for (RemoteDevice d : localDevice.getRemoteDevices()) { ... use existing code } // Wait a bit for responses to come in. Thread.sleep(2000); localDevice.terminate(); }
Change port numbers as you see fit. In this example i've assumed that some remote device is running on port 2068 - presumably the SlaveDeviceTest example.
I mentioned before an issue with commercial products not handling non-standard ports properly. If i recall correctly, this issue is as follows. Say i create a LocalDevice listening on port 8000. I use this to send a WhoIs broadcast to port 0xBAC0 (the standard port). Many commercial packages will return their IAm response over port 0xBAC0, which is incorrect. The original port 8000 is available to the remote device, but for whatever reason it is not used. Please be aware of this may happen when you are creating your BACnet network. BACnet4J handles its use of ports correctly.
-
Oh, as an explanation of why you got that error... You created the RemoteDevice yourself and added it to your list of remote devices with "localDevice.addRemoteDevice(rd);". Then, in the loop, you asked this remote device for a property that it does not have (because you didn't give the property to it). So, you got an "Unknown Object" error.
-
Thanks, step done ...
Are you Interested in the changed code?
next: How to read the Properties of the objects ai0,ai1,bi0,bi1,msg0,ao0 set by SimpleTest? - or in which testfiles are there?
Arne
-
Are you Interested in the changed code?
Sure, if you think it will help other users, post it up.next: How to read the Properties of the objects
You send some form of a "read properties" request. Below is a snippet of how Mango does it. It's contextual to Mango, but i think you should be able to figure out what is going on.private void pollDevice(RemoteDevice d, List<DataPointRT> points, long time) { // Gather the points into a list of point references. PropertyReferences refs = new PropertyReferences(); for (DataPointRT dp : points) { BACnetIPPointLocatorRT locator = (BACnetIPPointLocatorRT)dp.getPointLocator(); refs.add(locator.getOid(), locator.getPid()); } try { // Send the read request. PropertyValues values = localDevice.readProperties(d, refs); // Dereference the property values back into the points. for (DataPointRT dp : points) { BACnetIPPointLocatorRT locator = (BACnetIPPointLocatorRT)dp.getPointLocator(); Encodable encodable = values.getNoErrorCheck(locator.getOid(), locator.getPid()); if (encodable == null) fireDeviceExceptionEvent("event.bacnet.readError", dp.getVO().getName(), "no value returned"); else if (encodable instanceof BACnetError) fireDeviceExceptionEvent("event.bacnet.readError", dp.getVO().getName(), ((BACnetError)encodable).getErrorCode()); else { Object value = encodableToValue(encodable, dp.getDataTypeId()); dp.updatePointValue(new PointValueTime(value, time)); } } } catch (BACnetException e) { fireMessageExceptionEvent("event.bacnet.readDevice", d.getAddress().toIpString(), e.getMessage()); } }
-
So this two classes should work straight out of the box on any machine ;-)
DeviceTest
/* * ============================================================================ * GNU Lesser General Public License * ============================================================================ * * Copyright (C) 2006-2009 Serotonin Software Technologies Inc. http://serotoninsoftware.com * @author Matthew Lohbihler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.serotonin.bacnet4j.test; import com.serotonin.bacnet4j.RemoteObject; import com.serotonin.bacnet4j.obj.BACnetObject; import com.serotonin.bacnet4j.type.Encodable; import com.serotonin.bacnet4j.type.constructed.Choice; import com.serotonin.bacnet4j.type.constructed.PropertyValue; import com.serotonin.bacnet4j.type.constructed.TimeStamp; import com.serotonin.bacnet4j.type.enumerated.EventState; import com.serotonin.bacnet4j.type.enumerated.EventType; import com.serotonin.bacnet4j.type.enumerated.MessagePriority; import com.serotonin.bacnet4j.type.enumerated.NotifyType; import com.serotonin.bacnet4j.type.notificationParameters.NotificationParameters; import com.serotonin.bacnet4j.type.primitive.Boolean; import com.serotonin.bacnet4j.type.primitive.CharacterString; import java.io.IOException; import java.util.List; import com.serotonin.bacnet4j.LocalDevice; import com.serotonin.bacnet4j.RemoteDevice; import com.serotonin.bacnet4j.event.DeviceEventListener; import com.serotonin.bacnet4j.exception.BACnetException; import com.serotonin.bacnet4j.service.unconfirmed.WhoIsRequest; import com.serotonin.bacnet4j.type.constructed.BACnetError; import com.serotonin.bacnet4j.type.constructed.PropertyReference; import com.serotonin.bacnet4j.type.constructed.SequenceOf; import com.serotonin.bacnet4j.type.enumerated.ObjectType; import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier; import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier; import com.serotonin.bacnet4j.type.primitive.UnsignedInteger; import com.serotonin.bacnet4j.util.PropertyReferences; import com.serotonin.bacnet4j.util.PropertyValues; /** * Discovers and devices and print all properties of all objects found. * * * * @author Matthew Lohbihler * @author Arne Plöse */ public class DiscoveryTest { public static String BROADCAST_ADDRESS = "127.0.0.255"; private LoopDevice loopDevice; private LocalDevice localDevice; public DiscoveryTest(String broadcastAddress, int port) throws IOException { localDevice = new LocalDevice(1234, broadcastAddress); localDevice.setPort(port); localDevice.getEventHandler().addListener(new DeviceEventListener() { public void listenerException(Throwable e) { System.out.println("DiscoveryTest listenerException"); } public void iAmReceived(RemoteDevice d) { System.out.println("DiscoveryTest iAmReceived"); synchronized (DiscoveryTest.this) { DiscoveryTest.this.notifyAll(); } } public boolean allowPropertyWrite(BACnetObject obj, PropertyValue pv) { System.out.println("DiscoveryTest allowPropertyWrite"); return true; } public void propertyWritten(BACnetObject obj, PropertyValue pv) { System.out.println("DiscoveryTest propertyWritten"); } public void iHaveReceived(RemoteDevice d, RemoteObject o) { System.out.println("DiscoveryTest iHaveReceived"); } public void covNotificationReceived(UnsignedInteger subscriberProcessIdentifier, RemoteDevice initiatingDevice, ObjectIdentifier monitoredObjectIdentifier, UnsignedInteger timeRemaining, SequenceOf<PropertyValue> listOfValues) { System.out.println("DiscoveryTest covNotificationReceived"); } public void eventNotificationReceived(UnsignedInteger processIdentifier, RemoteDevice initiatingDevice, ObjectIdentifier eventObjectIdentifier, TimeStamp timeStamp, UnsignedInteger notificationClass, UnsignedInteger priority, EventType eventType, CharacterString messageText, NotifyType notifyType, Boolean ackRequired, EventState fromState, EventState toState, NotificationParameters eventValues) { System.out.println("DiscoveryTest eventNotificationReceived"); } public void textMessageReceived(RemoteDevice textMessageSourceDevice, Choice messageClass, MessagePriority messagePriority, CharacterString message) { System.out.println("DiscoveryTest textMessageReceived"); } public void privateTransferReceived(UnsignedInteger vendorId, UnsignedInteger serviceNumber, Encodable serviceParameters) { System.out.println("DiscoveryTest privateTransferReceived"); } }); localDevice.initialize(); } public void doDiscover() throws Exception { // Who is System.out.println("Send Broadcast WhoIsRequest() "); // Send the broadcast to the correct port of the LoopDevice !!! localDevice.sendBroadcast(loopDevice.getPort(), new WhoIsRequest(null, null)); // wait for notification in iAmReceived() Timeout 2 sec synchronized (this) { final long start = System.currentTimeMillis(); this.wait(2000); System.out.println(" waited for iAmReceived: " + (System.currentTimeMillis() - start) + " ms"); } System.out.println("Start iterating remote devices"); // Get extended information for all remote devices. for (RemoteDevice d : localDevice.getRemoteDevices()) { localDevice.getExtendedDeviceInformation(d); List<ObjectIdentifier> oids = ((SequenceOf<ObjectIdentifier>) localDevice.sendReadPropertyAllowNull( d, d.getObjectIdentifier(), PropertyIdentifier.objectList)).getValues(); PropertyReferences refs = new PropertyReferences(); for (ObjectIdentifier oid : oids) { addPropertyReferences(refs, oid); } localDevice.readProperties(d, refs); System.out.println("Values of d: " + d); try { // Send the read request. PropertyValues values = localDevice.readProperties(d, refs); // Dereference the property values back into the points. for (ObjectIdentifier oid : oids) { printObject(oid, refs, values); } } catch (BACnetException e) { System.out.println("event.bacnet.readDevice ADDRESS: " + e.getMessage()); } } System.out.println("Remote devices done..."); } /** * Note same Bropadcast address, but different ports!!! * @param args * @throws java.lang.Exception */ @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { DiscoveryTest dt = new DiscoveryTest(BROADCAST_ADDRESS, LocalDevice.DEFAULT_PORT); dt.setLoopDevice(new LoopDevice(BROADCAST_ADDRESS, LocalDevice.DEFAULT_PORT + 1)); try { dt.doDiscover(); } finally { dt.localDevice.terminate(); System.out.println("Cleanup loopDevice"); dt.getLoopDevice().doTerminate(); } } private void addPropertyReferences(PropertyReferences refs, ObjectIdentifier oid) { refs.add(oid, PropertyIdentifier.objectName); ObjectType type = oid.getObjectType(); if (ObjectType.accumulator.equals(type)) { refs.add(oid, PropertyIdentifier.units); } else if (ObjectType.analogInput.equals(type) || ObjectType.analogOutput.equals(type) || ObjectType.analogValue.equals(type) || ObjectType.pulseConverter.equals(type)) { refs.add(oid, PropertyIdentifier.units); } else if (ObjectType.binaryInput.equals(type) || ObjectType.binaryOutput.equals(type) || ObjectType.binaryValue.equals(type)) { refs.add(oid, PropertyIdentifier.inactiveText); refs.add(oid, PropertyIdentifier.activeText); } else if (ObjectType.lifeSafetyPoint.equals(type)) { refs.add(oid, PropertyIdentifier.units); } else if (ObjectType.loop.equals(type)) { refs.add(oid, PropertyIdentifier.outputUnits); } else if (ObjectType.multiStateInput.equals(type) || ObjectType.multiStateOutput.equals(type) || ObjectType.multiStateValue.equals(type)) { refs.add(oid, PropertyIdentifier.stateText); } else { return; } refs.add(oid, PropertyIdentifier.presentValue); } /** * @return the loopDevice */ public LoopDevice getLoopDevice() { return loopDevice; } /** * @param loopDevice the loopDevice to set */ public void setLoopDevice(LoopDevice loopDevice) { this.loopDevice = loopDevice; } private void printObject(ObjectIdentifier oid, PropertyReferences refs, PropertyValues values) { System.out.println("\t" + oid); // print propertie for (PropertyReference pr : refs.getProperties().get(oid)) { Encodable encodable = values.getNoErrorCheck(oid, pr); if (encodable == null) { System.out.println("event.bacnet.readError: no value returned"); } else if (encodable instanceof BACnetError) { System.out.println("event.bacnet.readError NAME: " + ((BACnetError) encodable).getErrorCode()); } else { System.out.println(String.format("\t\t %s = %s", pr.getPropertyIdentifier(), encodable.toString())); } } } }
LoopDevice
/* * ============================================================================ * GNU Lesser General Public License * ============================================================================ * * Copyright (C) 2006-2009 Serotonin Software Technologies Inc. http://serotoninsoftware.com * @author Matthew Lohbihler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.serotonin.bacnet4j.test; import com.serotonin.bacnet4j.LocalDevice; import com.serotonin.bacnet4j.RemoteDevice; import com.serotonin.bacnet4j.RemoteObject; import com.serotonin.bacnet4j.event.DeviceEventListener; import com.serotonin.bacnet4j.exception.BACnetServiceException; import com.serotonin.bacnet4j.obj.BACnetObject; import com.serotonin.bacnet4j.type.Encodable; import com.serotonin.bacnet4j.type.constructed.Choice; import com.serotonin.bacnet4j.type.constructed.PropertyValue; import com.serotonin.bacnet4j.type.constructed.SequenceOf; import com.serotonin.bacnet4j.type.constructed.TimeStamp; import com.serotonin.bacnet4j.type.enumerated.BinaryPV; import com.serotonin.bacnet4j.type.enumerated.EngineeringUnits; import com.serotonin.bacnet4j.type.enumerated.EventState; import com.serotonin.bacnet4j.type.enumerated.EventType; import com.serotonin.bacnet4j.type.enumerated.MessagePriority; import com.serotonin.bacnet4j.type.enumerated.NotifyType; import com.serotonin.bacnet4j.type.enumerated.ObjectType; import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier; import com.serotonin.bacnet4j.type.notificationParameters.NotificationParameters; import com.serotonin.bacnet4j.type.primitive.Boolean; import com.serotonin.bacnet4j.type.primitive.CharacterString; import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier; import com.serotonin.bacnet4j.type.primitive.Real; import com.serotonin.bacnet4j.type.primitive.UnsignedInteger; import java.io.IOException; /** * * software only device default local loop ;-) * * @author mlohbihler * @author aploese */ public class LoopDevice implements Runnable { public static void main(String[] args) throws Exception { LoopDevice ld = new LoopDevice("127.0.0.255", LocalDevice.DEFAULT_PORT + 1); Thread.sleep(12000); // wait 2 min ld.doTerminate(); } private boolean terminate; private LocalDevice localDevice; private BACnetObject ai0; private BACnetObject ai1; private BACnetObject bi0; private BACnetObject bi1; private BACnetObject mso0; private BACnetObject ao0; public LoopDevice(String broadcastAddress, int port) throws BACnetServiceException, IOException { localDevice = new LocalDevice(1968, broadcastAddress); localDevice.setPort(port); localDevice.getEventHandler().addListener(new DeviceEventListener() { public void listenerException(Throwable e) { System.out.println("loopDevice listenerException"); } public void iAmReceived(RemoteDevice d) { System.out.println("loopDevice iAmReceived"); } public boolean allowPropertyWrite(BACnetObject obj, PropertyValue pv) { System.out.println("loopDevice allowPropertyWrite"); return true; } public void propertyWritten(BACnetObject obj, PropertyValue pv) { System.out.println("loopDevice propertyWritten"); } public void iHaveReceived(RemoteDevice d, RemoteObject o) { System.out.println("loopDevice iHaveReceived"); } public void covNotificationReceived(UnsignedInteger subscriberProcessIdentifier, RemoteDevice initiatingDevice, ObjectIdentifier monitoredObjectIdentifier, UnsignedInteger timeRemaining, SequenceOf<PropertyValue> listOfValues) { System.out.println("loopDevice covNotificationReceived"); } public void eventNotificationReceived(UnsignedInteger processIdentifier, RemoteDevice initiatingDevice, ObjectIdentifier eventObjectIdentifier, TimeStamp timeStamp, UnsignedInteger notificationClass, UnsignedInteger priority, EventType eventType, CharacterString messageText, NotifyType notifyType, Boolean ackRequired, EventState fromState, EventState toState, NotificationParameters eventValues) { System.out.println("loopDevice eventNotificationReceived"); } public void textMessageReceived(RemoteDevice textMessageSourceDevice, Choice messageClass, MessagePriority messagePriority, CharacterString message) { System.out.println("loopDevice textMessageReceived"); } public void privateTransferReceived(UnsignedInteger vendorId, UnsignedInteger serviceNumber, Encodable serviceParameters) { System.out.println("loopDevice privateTransferReceived"); } }); // Set up a few objects. ai0 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.analogInput)); ai0.setProperty(PropertyIdentifier.units, EngineeringUnits.centimeters); localDevice.addObject(getAi0()); ai1 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.analogInput)); ai0.setProperty(PropertyIdentifier.units, EngineeringUnits.percentObscurationPerFoot); localDevice.addObject(getAi1()); bi0 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.binaryInput)); localDevice.addObject(getBi0()); bi0.setProperty(PropertyIdentifier.objectName, new CharacterString("Off and on")); bi0.setProperty(PropertyIdentifier.inactiveText, new CharacterString("Off")); bi0.setProperty(PropertyIdentifier.activeText, new CharacterString("On")); bi1 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.binaryInput)); localDevice.addObject(getBi1()); bi1.setProperty(PropertyIdentifier.objectName, new CharacterString("Good and bad")); bi1.setProperty(PropertyIdentifier.inactiveText, new CharacterString("Bad")); bi1.setProperty(PropertyIdentifier.activeText, new CharacterString("Good")); mso0 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.multiStateOutput)); mso0.setProperty(PropertyIdentifier.objectName, new CharacterString("Vegetable")); mso0.setProperty(PropertyIdentifier.numberOfStates, new UnsignedInteger(4)); mso0.setProperty(PropertyIdentifier.stateText, 1, new CharacterString("Tomato")); mso0.setProperty(PropertyIdentifier.stateText, 2, new CharacterString("Potato")); mso0.setProperty(PropertyIdentifier.stateText, 3, new CharacterString("Onion")); mso0.setProperty(PropertyIdentifier.stateText, 4, new CharacterString("Broccoli")); mso0.setProperty(PropertyIdentifier.presentValue, new UnsignedInteger(1)); localDevice.addObject(getMso0()); ao0 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.analogOutput)); ao0.setProperty(PropertyIdentifier.objectName, new CharacterString("Settable analog")); localDevice.addObject(getAo0()); // Start the local device. localDevice.initialize(); new Thread(this).start(); } public void run() { try { System.out.println("LoopDevice start changing values" + this); // Let it go... float ai0value = 0; float ai1value = 0; boolean bi0value = false; boolean bi1value = false; getMso0().setProperty(PropertyIdentifier.presentValue, new UnsignedInteger(2)); while (!isTerminate()) { System.out.print("Change values of LoopDevice " + this); // Change the values. ai0value += 0.1; ai1value += 0.7; bi0value = !bi0value; bi1value = !bi1value; // Update the values in the objects. ai0.setProperty(PropertyIdentifier.presentValue, new Real(ai0value)); ai1.setProperty(PropertyIdentifier.presentValue, new Real(ai1value)); bi0.setProperty(PropertyIdentifier.presentValue, bi0value ? BinaryPV.active : BinaryPV.inactive); bi1.setProperty(PropertyIdentifier.presentValue, bi1value ? BinaryPV.active : BinaryPV.inactive); synchronized (this) { wait(1000); // 1 second or notified (faster exit then stupid wait for 1 second) } } System.out.println("Close LoopDevive " + this); } catch (Exception ex) { } localDevice.terminate(); localDevice = null; } @Override protected void finalize() throws Throwable { if (localDevice != null) { localDevice.terminate(); localDevice = null; } } /** * @return the terminate */ public boolean isTerminate() { return terminate; } /** * @param terminate the terminate to set */ public void doTerminate() { this.terminate = true; synchronized (this) { this.notifyAll(); // we may wait for this in run() ... } } /** * @return the broadcastAddress */ public String getBroadcastAddress() { return localDevice.getBroadcastAddress(); } /** * @return the port */ public int getPort() { return localDevice.getPort(); } /** * @return the localDevice */ public LocalDevice getLocalDevice() { return localDevice; } /** * @return the ai0 */ public BACnetObject getAi0() { return ai0; } /** * @return the ai1 */ public BACnetObject getAi1() { return ai1; } /** * @return the bi0 */ public BACnetObject getBi0() { return bi0; } /** * @return the bi1 */ public BACnetObject getBi1() { return bi1; } /** * @return the mso0 */ public BACnetObject getMso0() { return mso0; } /** * @return the ao0 */ public BACnetObject getAo0() { return ao0; } }
Arne
-
This is excellent Arne. Thanks very much for sharing your work.
-
Hi,
trying to read all property values by using this changed code in :
private void addPropertyReferences(PropertyReferences refs, ObjectIdentifier oid) { for (int i = 0; i < 12; i++) { refs.add(oid, new PropertyIdentifier(75 + i)); } }
and choose values greater of 12 >> the app will fail.
Any hints?
Arne
-
Hi Matthew,
the offending PropertyId are: 8, 87, 105, which throw a java.lang.reflect.InvocationTargetException.
Should I file a bug against it in the SF bug parade?
Arne
-
Hi Arne,
I can't reproduce the problem. This code worked fine for me:
public static void main(String[] args) throws Exception { ObjectIdentifier oid = new ObjectIdentifier(ObjectType.accumulator, 0); PropertyReferences refs = new PropertyReferences(); for (int i=0; i<200; i++) refs.add(oid, new PropertyIdentifier(i)); }
A stack trace goes a long way to explaining things. Maybe you can include that if you still have this problem.
Also, can you please start a new topic when you are changing subject. This thread is getting too expansive.
-
Sorry,
I thought this belongs also to create a bunch of example that runs out of the box.
OK, here is my stack trace:
com.serotonin.bacnet4j.exception.BACnetException: java.lang.reflect.InvocationTargetException at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:168) at com.serotonin.bacnet4j.type.constructed.SequenceOf.<init>(SequenceOf.java:54) at com.serotonin.bacnet4j.type.Encodable.readSequenceOf(Encodable.java:213) at com.serotonin.bacnet4j.service.acknowledgement.ReadPropertyMultipleAck.<init>(ReadPropertyMultipleAck.java:50) at com.serotonin.bacnet4j.service.acknowledgement.AcknowledgementService.createAcknowledgementService(AcknowledgementService.java:48) at com.serotonin.bacnet4j.apdu.ComplexACK.parseServiceData(ComplexACK.java:196) at com.serotonin.bacnet4j.npdu.ip.IpMessageControl.waitForAck(IpMessageControl.java:658) at com.serotonin.bacnet4j.npdu.ip.IpMessageControl.send(IpMessageControl.java:288) at com.serotonin.bacnet4j.npdu.ip.IpMessageControl.send(IpMessageControl.java:268) at com.serotonin.bacnet4j.npdu.ip.IpMessageControl.send(IpMessageControl.java:224) at com.serotonin.bacnet4j.LocalDevice.send(LocalDevice.java:411) at com.serotonin.bacnet4j.LocalDevice.send(LocalDevice.java:399) at com.serotonin.bacnet4j.LocalDevice.send(LocalDevice.java:392) at com.serotonin.bacnet4j.LocalDevice.readProperties(LocalDevice.java:760) at com.serotonin.bacnet4j.test.DiscoveryTest.doDiscover(DiscoveryTest.java:155) at com.serotonin.bacnet4j.test.DiscoveryTest.main(DiscoveryTest.java:187) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:532) at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:165) ... 15 more Caused by: com.serotonin.bacnet4j.exception.BACnetException: java.lang.reflect.InvocationTargetException at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:168) at com.serotonin.bacnet4j.type.constructed.SequenceOf.<init>(SequenceOf.java:66) at com.serotonin.bacnet4j.type.Encodable.readSequenceOf(Encodable.java:224) at com.serotonin.bacnet4j.type.Encodable.readOptionalSequenceOf(Encodable.java:233) at com.serotonin.bacnet4j.type.constructed.ReadAccessResult.<init>(ReadAccessResult.java:64) ... 20 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedConstructorAccessor3.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:532) at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:165) ... 24 more Caused by: com.serotonin.bacnet4j.exception.BACnetException: java.lang.reflect.InvocationTargetException at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:168) at com.serotonin.bacnet4j.type.Encodable.readWrapped(Encodable.java:318) at com.serotonin.bacnet4j.type.Encodable.readEncodable(Encodable.java:263) at com.serotonin.bacnet4j.type.constructed.ReadAccessResult$Result.<init>(ReadAccessResult.java:124) ... 28 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:532) at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:165) ... 31 more Caused by: com.serotonin.bacnet4j.exception.BACnetException: java.lang.reflect.InvocationTargetException at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:168) at com.serotonin.bacnet4j.type.constructed.SequenceOf.<init>(SequenceOf.java:54) at com.serotonin.bacnet4j.type.constructed.PriorityArray.<init>(PriorityArray.java:41) ... 36 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:532) at com.serotonin.bacnet4j.type.Encodable.read(Encodable.java:165) ... 38 more Caused by: com.serotonin.bacnet4j.exception.BACnetErrorException at com.serotonin.bacnet4j.type.Encodable.popStart(Encodable.java:109) at com.serotonin.bacnet4j.type.AmbiguousValue.<init>(AmbiguousValue.java:11) at com.serotonin.bacnet4j.type.constructed.PriorityValue.<init>(PriorityValue.java:83) ... 43 more
Any Idea?
Arne
-
Hi Matthew,
this happends by ObjectType == multiStateOutput and analogOutput
Arne
-
If the goal is to provide a set of simple examples, i would think the reporting of possible errors would just clutter things up.
But in any case, i still cannot reproduce this error. It appears to be an incorrectly formatted response. I expanded my test code to the following. It won't work for you because i added some convenience methods in the PropertyValues object, but i think you'll see what i'm getting at.
LocalDevice localDevice = new LocalDevice(1234, "192.168.0.255"); localDevice.initialize(); localDevice.sendBroadcast(2068, new WhoIsRequest(null, null)); Thread.sleep(1000); RemoteDevice d = localDevice.getRemoteDevices().get(0); ObjectIdentifier oid = new ObjectIdentifier(ObjectType.analogInput, 0); PropertyReferences refs = new PropertyReferences(); for (int i=0; i<200; i++) refs.add(oid, new PropertyIdentifier(i)); PropertyValues pvs = localDevice.readProperties(d, refs); for (ObjectPropertyReference opr : pvs) System.out.println(pvs.getNoErrorCheck(opr)); Thread.sleep(2000); localDevice.terminate();
The listener that returned the response is the SlaveDeviceTest example.
-
Hi Arne,
I have a fix for the PriorityArray (87). The class was not decoding properly. I have checked the updates into the CVS repo, but did not release a new version of the library. Here are the changes:
In PriorityArray, added an int to the constructor:
public PriorityArray(ByteQueue queue, int contextId) throws BACnetException { super(queue, PriorityValue.class, contextId); }
In Encodable, added this method:
protected static <T extends Encodable> T readSequenceType(ByteQueue queue, Class<T> clazz, int contextId) throws BACnetException { popStart(queue, contextId); T result; try { result = clazz.getConstructor(new Class[] {ByteQueue.class, Integer.TYPE}).newInstance( new Object[] {queue, contextId}); } catch (Exception e) { throw new BACnetException(e); } popEnd(queue, contextId); return result; }
... and added a call to that method in this method as shown:
protected static Encodable readEncodable(ByteQueue queue, ObjectType objectType, PropertyIdentifier propertyIdentifier, UnsignedInteger propertyArrayIndex, int contextId) throws BACnetException { // A property array index of 0 indicates a request for the length of an array. if (propertyArrayIndex != null && propertyArrayIndex.intValue() == 0) return readWrapped(queue, UnsignedInteger.class, contextId); if (!matchNonEndTag(queue, contextId)) throw new BACnetErrorException(ErrorClass.property, ErrorCode.missingRequiredParameter); PropertyTypeDefinition def = ObjectProperties.getPropertyTypeDefinition(objectType, propertyIdentifier); if (def == null) return new AmbiguousValue(queue, contextId); if (propertyArrayIndex != null && !def.isSequence()) throw new BACnetErrorException(ErrorClass.property, ErrorCode.propertyIsNotAList); if (propertyArrayIndex == null && def.isSequence()) return readSequenceOf(queue, def.getClazz(), contextId); if (propertyArrayIndex == null && SequenceOf.class.isAssignableFrom(def.getClazz())) return readSequenceType(queue, def.getClazz(), contextId); return readWrapped(queue, def.getClazz(), contextId); }
Can you let me know if this has any effect on the other types you mentioned (8 and 105).
-
Thank you, iI got it from CVS.
so here is my next "streamlined" ex DiscoveryTest example
It sends a WhoIs Request, waits for the first device to answer (in doDiscover()).
And then it requests all available Properties with PropertyIdentifier.all.
Then it prints the properties sorted by ObjectId./* * ============================================================================ * GNU Lesser General Public License * ============================================================================ * * Copyright (C) 2006-2009 Serotonin Software Technologies Inc. http://serotoninsoftware.com * @author Matthew Lohbihler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package com.serotonin.bacnet4j.test; import com.serotonin.bacnet4j.RemoteObject; import com.serotonin.bacnet4j.exception.BACnetException; import com.serotonin.bacnet4j.obj.BACnetObject; import com.serotonin.bacnet4j.type.Encodable; import com.serotonin.bacnet4j.type.constructed.Choice; import com.serotonin.bacnet4j.type.constructed.PropertyValue; import com.serotonin.bacnet4j.type.constructed.TimeStamp; import com.serotonin.bacnet4j.type.enumerated.EventState; import com.serotonin.bacnet4j.type.enumerated.EventType; import com.serotonin.bacnet4j.type.enumerated.MessagePriority; import com.serotonin.bacnet4j.type.enumerated.NotifyType; import com.serotonin.bacnet4j.type.notificationParameters.NotificationParameters; import com.serotonin.bacnet4j.type.primitive.Boolean; import com.serotonin.bacnet4j.type.primitive.CharacterString; import java.io.IOException; import java.util.List; import com.serotonin.bacnet4j.LocalDevice; import com.serotonin.bacnet4j.RemoteDevice; import com.serotonin.bacnet4j.event.DeviceEventListener; import com.serotonin.bacnet4j.service.unconfirmed.WhoIsRequest; import com.serotonin.bacnet4j.type.constructed.ObjectPropertyReference; import com.serotonin.bacnet4j.type.constructed.SequenceOf; import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier; import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier; import com.serotonin.bacnet4j.type.primitive.UnsignedInteger; import com.serotonin.bacnet4j.util.PropertyReferences; import com.serotonin.bacnet4j.util.PropertyValues; import java.util.ArrayList; /** * Discovers and devices and print all properties of all objects found. * this is done by using PropertyIdentifier.all so the Device will send all propertys that are set. * if you want poll all PropertyId {@link ReadPropertyRangeTest}. * * @author Matthew Lohbihler * @author Arne Plöse */ public class ReadAllAvailabeProperties { public static String BROADCAST_ADDRESS = "127.0.0.255"; private LoopDevice loopDevice; private LocalDevice localDevice; // remote devices found private List<RemoteDevice> remoteDevices = new ArrayList<RemoteDevice>(); public ReadAllAvailabeProperties(String broadcastAddress, int port) throws IOException { localDevice = new LocalDevice(1234, broadcastAddress); localDevice.setPort(port); localDevice.getEventHandler().addListener(new DeviceEventListener() { public void listenerException(Throwable e) { System.out.println("DiscoveryTest listenerException"); } public void iAmReceived(RemoteDevice d) { System.out.println("DiscoveryTest iAmReceived"); remoteDevices.add(d); synchronized (ReadAllAvailabeProperties.this) { ReadAllAvailabeProperties.this.notifyAll(); } } public boolean allowPropertyWrite(BACnetObject obj, PropertyValue pv) { System.out.println("DiscoveryTest allowPropertyWrite"); return true; } public void propertyWritten(BACnetObject obj, PropertyValue pv) { System.out.println("DiscoveryTest propertyWritten"); } public void iHaveReceived(RemoteDevice d, RemoteObject o) { System.out.println("DiscoveryTest iHaveReceived"); } public void covNotificationReceived(UnsignedInteger subscriberProcessIdentifier, RemoteDevice initiatingDevice, ObjectIdentifier monitoredObjectIdentifier, UnsignedInteger timeRemaining, SequenceOf<PropertyValue> listOfValues) { System.out.println("DiscoveryTest covNotificationReceived"); } public void eventNotificationReceived(UnsignedInteger processIdentifier, RemoteDevice initiatingDevice, ObjectIdentifier eventObjectIdentifier, TimeStamp timeStamp, UnsignedInteger notificationClass, UnsignedInteger priority, EventType eventType, CharacterString messageText, NotifyType notifyType, Boolean ackRequired, EventState fromState, EventState toState, NotificationParameters eventValues) { System.out.println("DiscoveryTest eventNotificationReceived"); } public void textMessageReceived(RemoteDevice textMessageSourceDevice, Choice messageClass, MessagePriority messagePriority, CharacterString message) { System.out.println("DiscoveryTest textMessageReceived"); } public void privateTransferReceived(UnsignedInteger vendorId, UnsignedInteger serviceNumber, Encodable serviceParameters) { System.out.println("DiscoveryTest privateTransferReceived"); } }); localDevice.initialize(); } /** * Send a WhoIs request and wait for the first to answer * @throws java.lang.Exception */ public void doDiscover() throws Exception { // Who is System.out.println("Send Broadcast WhoIsRequest() "); // Send the broadcast to the correct port of the LoopDevice !!! localDevice.sendBroadcast(loopDevice.getPort(), new WhoIsRequest(null, null)); // wait for notification in iAmReceived() Timeout 2 sec synchronized (this) { final long start = System.currentTimeMillis(); this.wait(2000); System.out.println(" waited for iAmReceived: " + (System.currentTimeMillis() - start) + " ms"); } // An other way to get to the list of devices // return localDevice.getRemoteDevices(); } private void printDevices() throws BACnetException { for (RemoteDevice d : remoteDevices) { localDevice.getExtendedDeviceInformation(d); List<ObjectIdentifier> oids = ((SequenceOf<ObjectIdentifier>) localDevice.sendReadPropertyAllowNull( d, d.getObjectIdentifier(), PropertyIdentifier.objectList)).getValues(); PropertyReferences refs = new PropertyReferences(); // add the property references of the "device object" to the list refs.add(d.getObjectIdentifier(), PropertyIdentifier.all); // and now from all objects under the device object >> ai0, ai1,bi0,bi1... for (ObjectIdentifier oid : oids) { refs.add(oid, PropertyIdentifier.all); } System.out.println("Start read properties"); final long start = System.currentTimeMillis(); PropertyValues pvs = localDevice.readProperties(d, refs); System.out.println(String.format("Properties read done in %d ms", System.currentTimeMillis() - start)); printObject(d.getObjectIdentifier(), pvs); for (ObjectIdentifier oid : oids) { printObject(oid, pvs); } } System.out.println("Remote devices done..."); } private void printObject(ObjectIdentifier oid, PropertyValues pvs) { System.out.println(String.format("\t%s", oid)); for (ObjectPropertyReference opr : pvs) { if (oid.equals(opr.getObjectIdentifier())) { System.out.println(String.format("\t\t%s = %s", opr.getPropertyIdentifier().toString(), pvs.getNoErrorCheck(opr))); } } } /** * Note same Bropadcast address, but different ports!!! * @param args * @throws java.lang.Exception */ @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { ReadAllAvailabeProperties dt = new ReadAllAvailabeProperties(BROADCAST_ADDRESS, LocalDevice.DEFAULT_PORT); try { dt.setLoopDevice(new LoopDevice(BROADCAST_ADDRESS, LocalDevice.DEFAULT_PORT + 1)); } catch (RuntimeException e) { dt.localDevice.terminate(); throw e; } try { dt.doDiscover(); dt.printDevices(); } finally { dt.localDevice.terminate(); System.out.println("Cleanup loopDevice"); dt.getLoopDevice().doTerminate(); } } /** * @return the loopDevice */ public LoopDevice getLoopDevice() { return loopDevice; } /** * @param loopDevice the loopDevice to set */ public void setLoopDevice(LoopDevice loopDevice) { this.loopDevice = loopDevice; } }
If you find this useful, you may add this to CVS.
If you interested, I would write a read specific property the old DiscoveryTest and a writeProperty test.
Arne
-
Hi Arne,
This looks great. I will add it to the distribution, but a couple things:
-
I changed the class name from ReadAllAvailabeProperties to ReadAllAvailableProperties
-
You reference a class named LoopDevice for which i don't have the code. Can you provide it? (Is it just a RemoteObject?)
-