MangoAutomation / BACnet4J

BACnet/IP stack written in Java. Forked from http://sourceforge.net/projects/bacnet4j/
GNU General Public License v3.0
183 stars 110 forks source link

Is it possible to send an arbitrary binary packet over MS/TP? #34

Closed WhittlesJr closed 5 years ago

WhittlesJr commented 5 years ago

For my BTL automated test application, I'm currently building my packets myself and sending them over a UDP socket, without using a stack like BACnet4J. This works fine for IP, but of course isn't enough to talk over MS/TP.

I want to be able to send arbitrary binary packet data through BACnet4J's stack, without going through BACnet4J's service/packet-creation interfaces. Ideally I'd like to be able to spin up an MS/TP master node and then just call some method on it, passing the binary packet data directly, which would return the response as raw binary as well.

Last time I tried this, I dug through your code quite a bit, but couldn't find a way to do what I wanted. So I thought I'd ask if anyone here thinks it would be possible?

terrypacker commented 5 years ago

You want to be looking at the MasterNode class. You would need to use most of the stack as it relies on the Transport to manage the incoming/outgoing messages and the MstpNode to do the timing for the token passing.

You may also be interested in the RealtimeMasterNode class that was implemented to allow a kernel level driver to handle the Token passing logic, however this is sort of opposite of what it looks like you want to do.

I'm making an assumption that you are actually going to send valid MSTP messages so you could try using the MasterNode.queueFrame(...) method once you have a full Network up and running while keeping a reference to the Master node you created.

WhittlesJr commented 5 years ago

MasterNode.queueFrame looks promising! I will give it a shot and report back

WhittlesJr commented 5 years ago

It works!! Thank you so much. Now I just have to figure out how to get the responses...

WhittlesJr commented 5 years ago

I'm struggling to find any way to listen to all received frames. I want to see all received NPDUs, and I would think there would be somewhere along the flow of data that I could do this from the place that the following log message is emitted (in Network.handleIncomingData):

DEBUG   2019-02-08 13:01:53,267 276515  com.serotonin.bacnet4j.npdu.Network    [BACnet4J MS/TP node]   Received NPDU from local network. From=Address [networkNumber=0, macAddress=[1]], local=0

But I can't find anywhere to drop a listener without inserting some hacks into your code.

terrypacker commented 5 years ago

I'm assuming you are creating a transport and passing in the MstpNetwork in your code. I would just create a class that extends MstpNetwork and override the methods you want. Then pass that into the Transport when you create it.

So I think you would do something like this:

public class MyMstpNetwork extends MstpNetwork {
    ....

    //For access to NPDU do this:
   @Override
   protected NPDU handleIncomingDataImpl(ByteQueue queue, OctetString linkService) throws Exception  {
         NPDU npdu = super. handleIncomingDataImpl(queue, linkService);
         //Check out my npdu
         return npdu;
    }

    //For raw binary introspection use this:
    @Override
   public NPDU parseNpduData(final ByteQueue queue, final OctetString linkService) throws MessageValidationException {
       super. parseNpduData(queue, linkService);

      //Listen to the data in the queue via queue.peek(...)
   }

}
WhittlesJr commented 5 years ago

Yeah, that's the only path I can see working out. I'll have at it. Thank you again!