Appendix 6 - Processing Unsolicited Received Data Frames

General Discussion

Being built upon the developer driver framework, when a driver places a request on its communicator, the byte array representation of the request is transmitted onto the driver's field-bus. Subsequently, all data frames that are received before the request times out will be passed to the request's processReceive method. If the request defines the getTag method and if the communicator component's receiver defines the computeTag method, then only those incoming data frames whose tag matches the tag of the recently communicated request will be passed to the request's processReceive method.

If the developer does not implement the getTag method then all received frames will be passed to the recently transmitted request until the request times out. Otherwise, only those data frames with a tag that matches the request's tag will be passed to the request. In both scenarios, all such data frames are passed to the request until the request times out, returns a completed response from its processReceive method, or throws a DdfResponseException from its processReceive method.

There are two scenarios to consider where incoming data frames could be treated as unsolicited data frames:

  1. In the case where request and receive frame tags are in use, any incoming data frame whose tag does not match the recently transmitted request (or requests, if the driver uses a multiple transaction communicator) will be passed to the communicator's unsolicited handler. Also any incoming data frame whose tag does indeed match the outstanding request(s) tag but the outstanding request(s)'s processReceive method neither returns a completed response nor throws a DdfResponseException (in other words, it returns null or throws a RuntimeException). then the incoming data frame will be passed to the unsolicited manager.
  2. In the case where the driver does not define tags for its requests or incoming data frames, then any incoming data frame whereby when passed to the outstanding request (or all outstanding requests in the event of a multiple-transaction-communicator) and no outstanding request returns a response or throws a DdfResponseException when passed the incoming data frame (in other words, if the outstanding request(s) return null from the processReceive method or throw a RuntimeException when passed the data frame), then the data frame will be passed to the communicator's unsolicited handler

That being said, if a driver needs to process unsolicited data frames then the developer needs to create a class that extends BDdfUnsolicitedMgr. The developer should override the processUnsolicitedFrame method. The processUnsolicitedFrame method is passed the unsolicited data frame as a parameter. From there the developer may perform any custom processing that he or she deems necessary.

The BDdfUnsolicitedManager implements its own queue and thread. It automatically queues up unsolicited data frames for the communicator and processes each unsolicited frame on its own thread. Therefore, the driver's unsolicited manager's processUnsolicitedFrame runs on the driver's own, dedicated, unsolicited-receive handler thread.

After creating the unsolicited manager class, the developer needs to associate the unsolicited receive handler with his or her driver's communicator. This is accomplished by redefining the unsolicitedMgr property on the driver's communicator component. In fact, the BDdfCommunicator itself defines the unsolicitedMgr in its slotomatic header as follows:


       unsolicitedMgr : BDdfUnsolicitedMgr
         -- The simplest of drivers will not need unsolicited support
         default{[new BDdfNullUnsolicitedMgr()]}

Notice that the type of the unsolicitedMgr is BDdfUnsolicitedMgr. Also notice that the default value for the unsolicitedMgr is an instance of a new BDdfNullUnsolicitedMgr.

As a side-note, the BDdfNullUnsolicitedMgr is a class that extends BDdfUnsolicitedMgr and provides an empty processUnsolicitedFrame method. Furthermore the BDdfNullUnsolicitedMgr removes the queue and the thread from the unsolicited manager, thereby serving a null version of an unsolicited manger. Since the developer will extend BDdfUnsolicitedMgr and not BDdfNullUnsolicitedMgr, his or her unsolicited manager will inherit its own queue and thread for processing unsolicited data frames.

The developer should redefine the unsolicitedMgr as follows, in his or her communicator (replacing YourDriver with the name of the developer's driver):

       unsolicitedMgr : BDdfUnsolicitedMgr
         -- Plugs in an instance of BYourDriverUnsolicitedMgr as the
         -- unsolicited handler for BYourDriverCommunicator
         default{[new BYourDriverUnsolicitedMgr()]}

Depending on the situation, there are endless possibilities that the developer may need to support in processing the unsolicited data frame. For example, if the developer needs the transmit a request onto the field-bus as a result of the unsolicited data frame, then his or her code in the unsolicited manager class may call the getDdfCommunicator method to gain a reference to the driver's communicator component. (BDdfUnsolicitedMgr provides the getDdfCommunicator method as a convenience.) With the communicator component, the developer may call the communicate method and pass it a new instance of a custom BDdfRequest for the driver.

This is just one small example out of countless scenarios. We wish you pleasant development!