Chapter 30 - Create Your Point Discovery Response

NOTE: This class is similar to your driver's read response, write response, ping response, and device discovery response classes. Depending on whether you created a special discover request (BYourDriverPointDiscoverRequest) or whether your driver's read request (BYourDriverReadRequest) is also serving as the point discovery request, you should follow either A or B but not both.


A.  If you created a class named BYourDriverPointDiscoverRequest previously during the day's lesson:
  1. Create a class named BYourDriverPointDiscoverResponse that extends BDdfResponse and implements BIDdfDiscoverResponse. Create this class in the package com.yourCompany.yourDriver.comm.rsp.

    To do this, create a text file named BYourDriverPointDiscoverResponse.java in the jarFileName/src/com/yourCompany/yourDriver/comm/rsp folder. Inside the text file, start with the following text:

    package com.yourCompany.yourDriver.comm.rsp;
    
    import java.util.*;
    
    import javax.baja.sys.*;
    
    import com.tridium.ddf.comm.*;
    import com.tridium.ddf.comm.rsp.*;
    import com.tridium.ddf.discover.*;
    
    import com.yourCompany.yourDriver.discover.*;
    import com.yourCompany.yourDriver.identify.*;
    
    public class BYourDriverPointDiscoverResponse
      extends BDdfResponse
      implements BIDdfDiscoverResponse
    {
      /*-
      class BYourDriverPointDiscoverResponse
      {
      }
      -*/
    }
    
  2. Define the getDiscoveryChildren method. This satisfies the BIDdfDiscoverResponse interface.

      /**
       * This method parses the response byte array and returns an
       * array of BYourDriverPointDiscoveryLeaf objects describing
       * the data points that this response is able to identify.
       * This is called during the auto discovery process.
       */
      public BIDdfDiscoveryObject[] parseDiscoveryObjects(Context c)
      {
        return null;
      }
    
  3. Declare an empty constructor.

      public BYourDriverPointDiscoverResponse()
      {
      }
    
  4. Declare a constructor that takes as parameters any data that you will need to construct the return array for the parseDiscoveryObjects method.

      /**
       * This constructor does not necessarily need to take an IDdfDataFrame
       * as a parameter. It could take any parameters that you wish to pass
       * to the response from the request's processReceive method. The data
       * that is passed to this constructor will be saved on instance variables
       * and used in the parseDiscoveryObjects method to construct the return
       * array.
       */
      public BYourDriverPointDiscoverResponse(IDdfDataFrame receiveFrame)
      {
        // TODO: Make a copy of any bytes that you need from the receiveFrame
        //       since the receive frame could be part of an internal buffer
        //       of the receiver.
      }
    
  5. Revisit your driver's point discovery request and implement the processReceive method.

    The processReceive method should return an instance of BYourDriverPointDiscoverResponse. When invoking the constructor of BYourDriverPointDiscoverResponse, pass in the received data frame and/or any data that you will need to construct the return array for the parseDiscoveryObjects method of BYourDriverDiscoverResponse.

    package com.yourCompany.yourDriver.comm.req;
    
    import java.util.*;
    
    import javax.baja.sys.*;
    
    import com.tridium.ddf.identify.*;
    import com.tridium.ddf.comm.*;
    import com.tridium.ddf.comm.req.*;
    import com.tridium.ddf.comm.rsp.*;
    
    import com.yourCompany.yourDriver.identify.*;
    
    
    public class BYourDriverPointDiscoverRequest
      extends BDdfDiscoveryRequest
    {
      /*-
      class BYourDriverPointDiscoverRequest
      {
      }
      -*/
    
      public byte[] toByteArray()
      {
        BYourDriverPointDiscoverParams ptDscvParams =
          (BYourDriverPointDiscoverParams)getDiscoverParameters();
    
        return new byte[]{
          //...
          // Substitute value1 and value2 with your own properties
          // As necessary to construct the outgoing frame that your
          // Driver's protocol defines for requesting all points or
          // A series (group) of points from a field-device.
          (byte)ptDscvParams.getValue1(),
          (byte)ptDscvParams.getValue2(),
          //...
        };
      }
      
      public BIDdfResponse processReceive(IDdfDataFrame receiveFrame)
        throws DdfResponseException
      { // TODO: Pass any data to the response that it will need to
        // implement its parseDiscoveryChildren method.
        return new BYourDriverPointDiscoverResponse(receiveFrame);
      }
      
    }
    
    
  6. Finish implementing the parseDiscoveryObjects method on BYourDriverPointDiscoveryResponse.

    The parseDiscoveryObjects method should return an array of BIDdfDiscoveryObject structures that describe the data points that are identified in the response bytes. More specifically, you should return an array of BYourDriverPointDiscoveryLeaf objects. You already defined your class BYourDriverPointDiscoveryLeaf during today's lesson. BYourDriverPointDiscoveryLeaf happens to implement BIDdfDiscoveryObject.

    NOTE: Our hypothetical example is really a candidate for the other scenario being covered in this chapter. However, to illustrate this line item, please use the following implementation of the parseDiscoveryObjects method as a guide:

      /**
       * In our hypothetical protocol, the request returns a comma-
       * separated list of analog inputs, analog outputs, digital
       * inputs, or digital outputs.
       */
      public BIDdfDiscoveryObject[] parseDiscoveryObjects(Context c)
      {
        // In our hypothetical protocol, the read request asks to read
        // either analog or digital outputs or inputs. The field device
        // Has up to 30 analog or digital outputs or inputs (the exact number
        // can vary). The read response returns all of the corresponding
        // analog input, analog output, digital input, or digital output values
        // that were requested -- inside a comma delimited string. The substrings in
        // between the commas are signed integers for analog values or
        // The text "on" or "off" for digital values. The actual values are not
        // important though. The position is the most important as it provides
        // us with vital information as to how to read and/or write the individual
        // data point.
        if (rawValues==null) // Parses each of the values from the
          parseRawValues();  // receive frame into a string array.
        BYourDriverPointDiscoveryLeaf[] discoveredPoints =
          new BYourDriverPointDiscoveryLeaf[rawValues.length];
        // Loops once for each data point in the response data.
        for (int i=0; i<discoveredPoints.length; i++)
        {
          discoveredPoints[i] = new BYourDriverPointDiscoveryLeaf();
          // Sets the typeString property of the discovery leaf
          ((BYourDriverReadParams)discoveredPoints[i].getReadParameters()).
            setTypeString(readParams.getTypeString());
          // Sets the direction property of the discovery leaf
          ((BYourDriverReadParams)discoveredPoints[i].getReadParameters()).
            setDirection(readParams.getDirection());
          // We know that by returning a value for this index that the data point
          // Exists in the hypothetical device
          ((BYourDriverPointId)discoveredPoints[i].getPointId()).setOffset(i);
          // TODO: We could update the writeParameters on the discovery leaf too
          // If we had anything there to update
        }
        return discoveredPoints;
      }
    


B.  If you decided to have your driver's read request and read parameters structure also serve as the discover request/discover parameters:
  1. Update the class declaration for BYourDriverReadResponse.

    package com.yourCompany.yourDriver.comm.rsp;
    
    import javax.baja.sys.*;
    import javax.baja.status.*;
    
    import com.tridium.ddf.comm.*;
    import com.tridium.ddf.comm.rsp.*;
    import com.tridium.ddf.comm.req.*;
    import com.tridium.ddf.discover.*;
    
    import com.yourCompany.yourDriver.identify.*;
    import com.yourCompany.yourDriver.point.*;
    import com.yourCompany.yourDriver.discover.*;
    
    public class BYourDriverReadResponse
      extends BDdfResponse
      implements BIDdfReadResponse, BIDdfDiscoverResponse
    {
      ...
    }
    

  2. Define the getDiscoveryChildren method. This satisfies the BIDdfDiscoverResponse interface.

      /**
       * This method parses the response byte array and returns an
       * array of BYourDriverPointDiscoveryLeaf objects describing
       * the data points that this response is able to identify.
       * This is called during the auto discovery process.
       */
      public BIDdfDiscoveryObject[] parseDiscoveryObjects(Context c)
      {
        return null;
      }
    

  3. The parseDiscoveryObjects method should return an array of BIDdfDiscoveryObject structures that describe the data points that can be identified in the response bytes. You should return an array of BYourDriverPointDiscoveryLeaf objects. You already defined this class (BYourDriverPointDiscoveryLeaf) and it happens to implement BIDdfDiscoveryObject.

    Please use the following implementation of the parseDiscoveryObjects method as a guide:

      /**
       * In our hypothetical protocol, the request returns a comma-
       * separated list of analog inputs, analog outputs, digital
       * inputs, or digital outputs.
       */
      public BIDdfDiscoveryObject[] parseDiscoveryObjects(Context c)
      {
        // In our hypothetical protocol, the read request asks to read
        // either analog or digital outputs or inputs. The field device
        // Has up to 30 analog or digital outputs or inputs (the exact number
        // can vary). The read response returns all of the corresponding
        // analog input, analog output, digital input, or digital output values
        // that were requested -- inside a comma delimited string. The substrings in
        // between the commas are signed integers for analog values or
        // The text "on" or "off" for digital values. The actual values are not
        // important though. The position is the most important as it provides
        // us with vital information as to how to read and/or write the individual
        // data point.
        if (rawValues==null) // Parses each of the values from the
          parseRawValues();  // receive frame into a string array.
    
        BYourDriverPointDiscoveryLeaf[] discoveredPoints =
          new BYourDriverPointDiscoveryLeaf[rawValues.length];
        // Loops once for each data point in the response data.
        for (int i=0; i<discoveredPoints.length; i++)
        {
          discoveredPoints[i] = new BYourDriverPointDiscoveryLeaf();
          // Sets the typeString property of the discovery leaf
          ((BYourDriverReadParams)discoveredPoints[i].getReadParameters()).
            setTypeString(readParams.getTypeString());
          // Sets the direction property of the discovery leaf
          ((BYourDriverReadParams)discoveredPoints[i].getReadParameters()).
            setDirection(readParams.getDirection());
          // We know that by returning a value for this index that the data point
          // Exists in the hypothetical device
          ((BYourDriverPointId)discoveredPoints[i].getPointId()).setOffset(i);
          // TODO: We could update the writeParameters on the discovery leaf too
          // If we had anything there to update
        }
        return discoveredPoints;
      }
    


C.  Run slotomatic and perform a full build on your driver (as described in Chapter 2).