• D
    DolphinsGrin

    The APDU frame length of a Foreign Device Registry Answer message is six bytes long. The IncomingRequestParser.parseApdu() immediately sends all messages to the NPCI constructor, regardless of length checks, which subsequently chokes (array out of bounds) due to queue.size() being zero. I've inserted a couple changes to the source code to address this:

    First, in IpNetwork.parseFrame():

    
    			if (function != 0xa && function != 0xb && function != 0x4 && function != 0x0 && function != 0x5)
    				throw new MessageValidationAssertionException("Function is not unicast, broadcast, forward"
    						+ " or foreign device reg answer (0xa, 0xb, 0x4, 0x0, or 0x5)");
    

    "function != 0x05" is missing from the original method, and prematurely chokes the method.

    Secondly, I enclosed all of the lines in IncomingRequestParser.parseApdu() in the following if-statement:

    
    			if (queue.size() > 6)
    

    With a "return null;" to satisfy the return type.

    This is logically avoiding all exceptions I've been experiencing while doing a device discovery across sub-nets. Because I'm not wholly aware of what else uses these methods, I cannot be certain if I have not broken something else yet. Anyone with any more familiarity, please advise!

    The Dolphin's Grin

    Edit: Realized that checking queue.size() >6 was more effective than setting and referencing an "isForeignDevMsg" flag.

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    While still mostly empty, this at least provides updated method and class signatures for reference. I hope y'all find this as useful as I.

    Sincerely,

    The Dolphin's Grin

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    I am trying to perform network discovery for bacnet devices across multiple subnets without knowing what subnets are connected. Using Wireshark I am able to see that all the devices in my test environment are "chirping" on their subnets; broadcast IPs in response to my localDevice.sendGlobalBroadcast(new WhoIsRequest()), but it appears the Listener is not firing. I'm banging my head against my keyboard trying to sift through the empty JavaDoc for Bacnet4j. (Side note: is there a more fleshed-out JavaDoc relevant to vs 1.3 floating around somewhere?) Here is my code:

    
    public static void main(String[] args) throws Exception {
    		IpNetwork network = new IpNetwork("255.255.255.255");
    		Transport transport = new Transport(network);
    		transport.setTimeout(1500);
    		transport.setSegTimeout(1500);
    		
    		
    		try {
    			localDevice = new LocalDevice(1234, transport);
    			localDevice.initialize();
    			localDevice.getEventHandler().addListener(new Listener());
    			localDevice.sendGlobalBroadcast(new WhoIsRequest());
    			
    			
    			Thread.sleep(3000);
    
    			for (RemoteDevice device : localDevice.getRemoteDevices()) {
    				readVitals(device);
    			}
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			localDevice.terminate();
    		}
    
    	}
    
    

    Devices on my local subnet populate instantly. Devices on other subnets sit behind their routers chirping uselessly at their gateways.

    Please help.

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    The APDU frame length of a Foreign Device Registry Answer message is six bytes long. The IncomingRequestParser.parseApdu() immediately sends all messages to the NPCI constructor, regardless of length checks, which subsequently chokes (array out of bounds) due to queue.size() being zero. I've inserted a couple changes to the source code to address this:

    First, in IpNetwork.parseFrame():

    
    			if (function != 0xa && function != 0xb && function != 0x4 && function != 0x0 && function != 0x5)
    				throw new MessageValidationAssertionException("Function is not unicast, broadcast, forward"
    						+ " or foreign device reg answer (0xa, 0xb, 0x4, 0x0, or 0x5)");
    

    "function != 0x05" is missing from the original method, and prematurely chokes the method.

    Secondly, I enclosed all of the lines in IncomingRequestParser.parseApdu() in the following if-statement:

    
    			if (queue.size() > 6)
    

    With a "return null;" to satisfy the return type.

    This is logically avoiding all exceptions I've been experiencing while doing a device discovery across sub-nets. Because I'm not wholly aware of what else uses these methods, I cannot be certain if I have not broken something else yet. Anyone with any more familiarity, please advise!

    The Dolphin's Grin

    Edit: Realized that checking queue.size() >6 was more effective than setting and referencing an "isForeignDevMsg" flag.

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    So, I successfully fired off a "Register Foreign Device" broadcast, resulting in a fireworks-display of exceptions being thrown, but all subsequent sendGlobalRequest() return perfectly. Here is my call:

    network.sendRegisterForeignDeviceMessage(network.getLocalBroadcastAddress().getMacAddress().getInetSocketAddress(),1000);
    

    Where network is an instance of IpNetwork with all default values. The "Register-Foreign-Device" function code is 0x05, which the frame parser throws a hissy-fit about:

    com.serotonin.bacnet4j.npdu.MessageValidationAssertionException: Function is not unicast, broadcast, forward or foreign device reg anwser (0xa, 0xb, 0x4 or 0x0)
    	at com.serotonin.bacnet4j.npdu.ip.IpNetwork$IncomingMessageExecutor.parseFrame(IpNetwork.java:275)
    	at com.serotonin.bacnet4j.npdu.IncomingRequestParser.run(IncomingRequestParser.java:37)
    	at com.serotonin.bacnet4j.npdu.ip.IpNetwork.run(IpNetwork.java:242)
    	at java.lang.Thread.run(Unknown Source)
    Foreign device registration not successful! result: 48
    java.lang.ArrayIndexOutOfBoundsException: -1
    	at com.serotonin.util.queue.ByteQueue.pop(ByteQueue.java:221)
    	at com.serotonin.util.queue.ByteQueue.popU1B(ByteQueue.java:236)
    	at com.serotonin.bacnet4j.npdu.NPCI.<init>(NPCI.java:105)
    	at com.serotonin.bacnet4j.npdu.IncomingRequestParser.parseApdu(IncomingRequestParser.java:64)
    	at com.serotonin.bacnet4j.npdu.IncomingRequestParser.run(IncomingRequestParser.java:40)
    	at com.serotonin.bacnet4j.npdu.ip.IpNetwork.run(IpNetwork.java:242)
    	at java.lang.Thread.run(Unknown Source)
    Foreign device registration not successful! result: 48
    

    Any insight as to how to do this cleaner would be appreciated. I can't shake the feeling I'm breaking something when so much red floods my screen. Thanks again!

    Always Monday!

    Dolphin's Grin

    P.S. After passing this foreign device message, the foreign devices (devices on other subnets) address BOTH my machine's specific IP address, and its local subnet broadcast.

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    It appears as though I need to build a packet with the BVLCI function code of 0x09 (vice the 0x0A and 0x0B available by default in the sendGlobalBroadcast method). 0x09 directs a "Distribute-Broadcast-to-Network" and takes advantage of BBMDs present in the network to Forward NPDUs with the originating B/IP address still intact. Is there a neat, pre-packaged way of accomplishing this in BACnet4J, or am I building my own NPDU?

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    When you say you see them 'chirping' and answering to your WhoIs, are they answering to a broadcast address your machine can receive?

    For example, suppose your IP is 192.167.0.5 and your broadcast address is 192.255.255.255.
    A device situated on 192.168.0.4 might receive it, but if they answer on 192.168.255.255, you will never get it.

    You are correct. I am currently educating myself on the BVLL and BBMD mechanisms, and looking through the BACnet4J stack to see what tools are available for such fun.

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    While still mostly empty, this at least provides updated method and class signatures for reference. I hope y'all find this as useful as I.

    Sincerely,

    The Dolphin's Grin

    Attachment: download link

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    facePalm();

    While my original question stands, I have realized the presence of the ultimate JavaDoc: source code. Digging now...

    posted in BACnet4J general discussion read more
  • D
    DolphinsGrin

    I am trying to perform network discovery for bacnet devices across multiple subnets without knowing what subnets are connected. Using Wireshark I am able to see that all the devices in my test environment are "chirping" on their subnets; broadcast IPs in response to my localDevice.sendGlobalBroadcast(new WhoIsRequest()), but it appears the Listener is not firing. I'm banging my head against my keyboard trying to sift through the empty JavaDoc for Bacnet4j. (Side note: is there a more fleshed-out JavaDoc relevant to vs 1.3 floating around somewhere?) Here is my code:

    
    public static void main(String[] args) throws Exception {
    		IpNetwork network = new IpNetwork("255.255.255.255");
    		Transport transport = new Transport(network);
    		transport.setTimeout(1500);
    		transport.setSegTimeout(1500);
    		
    		
    		try {
    			localDevice = new LocalDevice(1234, transport);
    			localDevice.initialize();
    			localDevice.getEventHandler().addListener(new Listener());
    			localDevice.sendGlobalBroadcast(new WhoIsRequest());
    			
    			
    			Thread.sleep(3000);
    
    			for (RemoteDevice device : localDevice.getRemoteDevices()) {
    				readVitals(device);
    			}
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			localDevice.terminate();
    		}
    
    	}
    
    

    Devices on my local subnet populate instantly. Devices on other subnets sit behind their routers chirping uselessly at their gateways.

    Please help.

    posted in BACnet4J general discussion read more