Simple Examples
-
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?)
-
-
Ok,
here we go:
/* * ============================================================================ * 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.enumerated.Reliability; 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); try { 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"); } }); // for valid property values with valid datatypes see com.serotonin.bacnet4j.obj.ObjectProperties and ther look for the big static block at the end; // properties of device object localDevice.getConfiguration().setProperty(PropertyIdentifier.modelName, new CharacterString("BACnet4J LoopDevice")); // Set up a few objects. ai0 = new BACnetObject(localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.analogInput)); //mandatory properties ai0.setProperty(PropertyIdentifier.objectName, new CharacterString("G1-RLT03-TM-01")); // this is a cryptic encoded name of a temp sensor from a drawing... (ahm. actually taken from a book ;-)) ai0.setProperty(PropertyIdentifier.presentValue, new Real((float)11)); ai0.setProperty(PropertyIdentifier.outOfService, new Boolean(false)); ai0.setProperty(PropertyIdentifier.units, EngineeringUnits.degreesCelsius); //some optional properties ai0.setProperty(PropertyIdentifier.description, new CharacterString("temperature")); ai0.setProperty(PropertyIdentifier.deviceType, new CharacterString("random values")); ai0.setProperty(PropertyIdentifier.reliability, Reliability.noFaultDetected); ai0.setProperty(PropertyIdentifier.updateInterval, new UnsignedInteger(10)); ai0.setProperty(PropertyIdentifier.minPresValue, new Real(-70)); ai0.setProperty(PropertyIdentifier.maxPresValue, new Real(120)); ai0.setProperty(PropertyIdentifier.resolution, new Real((float)0.1)); ai0.setProperty(PropertyIdentifier.profileName, new CharacterString("funny reader")); localDevice.addObject(ai0); ai1 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.analogInput)); ai1.setProperty(PropertyIdentifier.units, EngineeringUnits.percentObscurationPerFoot); localDevice.addObject(ai1); bi0 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.binaryInput)); localDevice.addObject(bi0); 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(bi1); 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(mso0); ao0 = new BACnetObject( localDevice, localDevice.getNextInstanceObjectIdentifier(ObjectType.analogOutput)); ao0.setProperty(PropertyIdentifier.objectName, new CharacterString("Settable analog")); localDevice.addObject(ao0); // Start the local device. localDevice.initialize(); new Thread(this).start(); } catch (RuntimeException e) { System.out.println("Ex in LoopDevice() "); e.printStackTrace(); localDevice.terminate(); localDevice = null; throw e; } } 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); // 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; } }
the classname was a typo, thank you.
You (or probably me) can improve it to pass a broadcastaddress and timeout via main().
Arne
-
Ok, this has been added with one other change. In ReadAllAvailableProperties at line 220:
loopDevice = loopDevice;
... changed to:
this.loopDevice = loopDevice;
-
Hi,
I am also having problems running discovery test.
Here is my error message:Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The import com.serotonin.util cannot be resolved
ObjectUtils cannot be resolvedat com.serotonin.bacnet4j.LocalDevice.<init>(LocalDevice.java:96) at DiscoveryTest.main(DiscoveryTest.java:22)
I am missing the com.serotonin.util directory. Where do I get this file? I only have com.serotonin.bacnet4j.
Thanks,
-Andrew -
You should have downloaded the seroUtils.jar file as well. This needs to be included in your classpath.
-
Thanks mlohbihler. sorry for my novice question.
-andrew -
To prevent hair loss for anyone who stumbles upon this thread looking for somewhere to start with bacnet4j... I could not find this code anywhere in the bacnet4j Java package. I created ReadAllAvailabeProperties and LoopDevice classes in my own package. In order for this code to work with the newer versions of bacnet4j I had to replace all occurrences of DeviceEventListener with DefaultDeviceEventListener in both classes. This was just guess but it apparently worked.
-
Nevermind on that last post... all the test classes which compile correctly can be found in the source archive: bacnet4J-src.zip which can be found here: http://sourceforge.net/projects/bacnet4j/files/bacnet4j/1.2/
The are not in bacnet4j.jar or seroUtils.jar
I would still love to know the basic design of this package or a good description of the LocalDevice and RemoteDevice classes...