Chapter 23 - Create Your Device Discovery Parameters

NOTE: This class is analogous to your driver's read parameters and write parameters classes.

Some protocols, especially those with field-gateways, have special messages that a driver can transmit to request all devices or maybe just a group of devices, depending on the size-limitation of the particular messages's response. For these types of drivers the developer driver framework will attempt to loop through all possible combinations of the driver's special request that retrieves information about the existence of multiple devices.

Other protocols, especially serial master-slave protocols, do not feature a message that can request information about whether multiple devices are online. For these types of drivers, you will need to take some special steps that will cause the developer driver framework to attempt to ping all possible combinations of the device id.

Review your driver's protocol. Try to find documentation about a message that your driver can transmit in order to receive information about the existence of more than one device.


A. If your driver's protocol features a message that can retrieve information about multiple field-devices:

  1. Determine what information the request's byte array will need.
  2. Create a class named BYourDriverDeviceDiscoverParams that extends BDdfDiscoveryParams in the package com.yourDriver.identify.

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

    package com.yourCompany.yourDriver.comm.identify;
    
    import com.tridium.ddf.identify.*;
    import javax.baja.sys.*;
    
    public class BYourDriverDeviceDiscoverParams
      extends BDdfDiscoverParams
    {
      /*-
      class BYourDriverDeviceDiscoverParams
      {
        properties
        {
        }
      }
      -*/
    }
    

    Based on your driver's protocol document, please be prepared to add properties to the slotomatic statement to help you construct the byte array in the device discovery request (you will create the device discovery request in the next chapter)


  3. Define the getFirst, getLast, getNext, and isAfter methods. These are essential and allow the developer driver auto discovery process to automatically loop through all possible combinations of your discovery parameters.

    getFirst
    The getFirst method should return an instance of BYourDriverDeviceDiscoverParams that represents the data that would be placed in the protocol request to request information about the first device or series of devices. If your protocol has no way of identifying a definite first device then you will need to be creative here and return an instance of BYourDriverDeviceDiscoverParams with all properties set to special values, that you will determine, such as Integer.MIN_VALUE for int properties.
    getLast
    The getLast method should return an instance of BYourDriverDeviceDiscoverParams that represents the data in the protocol request that would request information about the last device or series of devices. This might not be possible to accurately define for some protocols. If your protocol does not have a way of identifying the last series of devices, then you will need to be creative here and return an instance of BYourDriverDeviceDiscoverParams with all properties set to special values, that you will create, such as Integer.MAX_VALUE for int properties.
    getNext
    The getNext method should return an instance of BYourDriverDeviceDiscoverParams that represents the data in the protocol request that would request the next device or series of devices, with respect to the particular instance of BYourDriverDeviceDiscoverParams. This method should review the values of some or all of the properties that you add to BYourDriverDeviceDiscoverParams. This method should return a new instance of BYourDriverDeviceDiscoverParams whose property values are incremented in such a way that the new instance would represent the data needed in the toByteArray method of the device discovery request in order to ask the field-gateway for information about the next device or set of devices.
    isAfter
    The isAfter method will be passed an instance of BYourDriverDeviceDiscoverParams. You should review the property values of the given instance of BYourDriverDeviceDiscoverParams and return true if the current instance would request information about a device or series of devices that would be after the device or series of devices that the given instance of BYourDriverDeviceDiscoverParams would identify. If the current instance represents a device or series of devices that is before or equal to the given instance, then this method should return false.

    We understand that this can be a bit tricky, since the definitions of first, last, next, and after can be somewhat abstract in some protocols. Please feel free to skip ahead and revisit this later if you wish.

  4. Your device discover params class also needs to define the getDiscoverRequestType method and return the Niagara-AX TYPE for your device discovery request class (you will create this in the next chapter).

      /**
       * The implementing class needs to return a Type that represents
       * the discover request from the driver whose discoverId can be an
       * instance of this object's class. If the class supports more than
       * one discover request type, then this should return the type that is
       * the most appropriate for the particular instance of the implementing
       * class.
       *
       * This is fundamental to dev driver's auto-discovery features.
       *
       * @return review method description.
       */
      public Type getDiscoverRequestType()
      {
        return null; // For now! Soon we will revisit this and return
                     // BYourDriverDeviceDiscoveryRequest.TYPE after
                     // Creating it.
      }
    

  5. Update your driver's device id structure, make it implement BIDdfDiscoveryLeaf. Implement the following methods that BIDdfDiscoveryLeaf requires.

    NOTE: BIDdfDiscoveryLeaf objects appear in the "discovered list" (top half) of the device manager.

    Your driver's device id also needs to import javax.baja.registry.*;, com.tridium.ddf.discover.*;, and import com.yourCompany.yourDriver.*;

    package com.yourCompany.yourDriver;
    
    import javax.baja.sys.*;
    import javax.baja.registry.*;
    
    import com.tridium.ddf.identify.*;
    import com.tridium.ddf.comm.req.*;
    import com.tridium.ddf.discover.*;
    
    import com.yourCompany.yourDriver.*;
    
    public class BYourDriverDeviceId
      extends BDdfDeviceId
      implements BIDdfDiscoveryLeaf
    {
      ...
    
      ...
    
      ...
    
      /**
       * When a control point is added to the station from the Dev
       * Point Manager, it is given this name by default (possibly
       * with a suffix to make it unique).
       * @return
       */
      public String getDiscoveryName()
      {
        return "NewDevice";
      }
    
      /**
       * Descendants need to return an array of TypeInfo objects corresponding
       * to all valid Niagara Ax types for this discovery object. This is
       * important when the end-user clicks 'Add' from the user interface for
       * the manager.
       *
       * For this discovery object, please  return a list of the types
       * which may be used to model it as a BComponent in the station
       * database. If the discovery object represents a device in your
       * driver then method should return an array with size of
       * at least one, filled with TypeInfo's that wrap the Niagara AX
       * TYPE's for your driver's device components.
       *
       * The type at index 0 in the array should be the type which
       * provides the best mapping.  Please return an empty array if the
       * discovery cannot be mapped.
       */
      public TypeInfo[] getValidDatabaseTypes()
      {
        return new TypeInfo[]{BYourDriverDevice.TYPE.getTypeInfo()};
      }
    }
    

  6. Revisit the BYourDriverDeviceDiscoverParams from earlier in this chapter. Define the getDiscoveryLeafType method and return the Niagara-AX TYPE of your device id class.

      /**
       * The implementing class needs to return a Type that will be the
       * discovery leaves in the ddf manager. For the device discovery
       * process, the discovery leaf TYPE is the device id TYPE.
       *
       * @return BYourDriverDeviceId.TYPE
       */
      public Type getDiscoveryLeafType()
      {
        return BYourDriverDeviceId.TYPE
      }
    


B. If your driver is a serial driver, uses a master-slave protocol, and provides no message that can retrieve information about multiple field-devices:

    You should modify your device id, ping params, ping request, and ping response to also serve in the auto-discovery procedure.
  1. Open the BYourDriverDeviceId.java file from Day 1 of this tutorial.
  2. Modify the class declaration statement and declare that BYourDriverDeviceId implements BIDdfDiscoverParams and BIDdfDiscoveryLeaf.

    public class BYourDriverDeviceId
      extends BDdfIdParams
      implements BIDdfDiscoverParams, BIDdfDiscoveryLeaf
    {
      ...
    }
    

  3. Your driver's device id structure, acting also as the device discover params structure, needs to satisfy the BIDdfDiscoverParams interface and define the getFirst, getLast, getNext, and isAfter methods in order to allow the developer driver auto discovery process to automatically loop through all possible combinations of your discovery parameters.

    For example, in the hypothetical protocol that we used in the days past, our device had a unitNbr. Let's assume that the unitNbr could range from 0 to 50. The getFirst method would return an instance of BYourDriverDeviceId with a unitNbr of 0. The getLast method would return an instance of BYourDriverDeviceId with a unitNbr of 50. The getNext method would return an instance of BYourDriverDeviceId with a unitNbr that is one more than the current instances's unitNbr: this.getUnitNumber()+1. Etc...

    Your driver's device id also needs to satisfy the BIDdfDiscoveryLeaf interface and implement the getDiscoveryName and getDatabaseTypes methods.

    Your driver's device id also needs to import javax.baja.registry.*;, com.tridium.ddf.discover.*;, import com.yourCompany.yourDriver.*;, and com.yourCompany.yourDriver.comm.req.*;.

    package com.yourCompany.yourDriver;
    
    import javax.baja.sys.*;
    import javax.baja.registry.*;
    
    import com.tridium.ddf.identify.*;
    import com.tridium.ddf.comm.req.*;
    import com.tridium.ddf.discover.*;
    
    import com.yourCompany.yourDriver.*;
    import com.yourCompany.yourDriver.comm.req.*;
    
    
    public class BYourDriverDeviceId
      extends BDdfDeviceId
      implements BIDdfDiscoverParams, BIDdfDiscoveryLeaf
    {
      /*-
      class BYourDriverDeviceId
      {
        properties
        {
          unitNumber : int
            -- This is the unitNumber in our hypothetical protocol.
            default{[0]}
        }
      }
      -*/
    
      private static final int FIRST_UNIT_NBR = 0;
      private static final int LAST_UNIT_NBR = 50;
    
      /**
       * Niagara AX requires a public, empty constructor, so that it can perform
       * Its own introspection operations.
       */
      public BYourDriverDeviceId(){}
      /**
       * This constructor is for our own convenience in the methods getFirst,
       * getNext, etc.
       */
      public BYourDriverDeviceId(int unit)
      {
        setUnitNumber(unit);
      }
      public BIDdfDiscoverParams getFirst()
      {
        return new BYourDriverDeviceId(FIRST_UNIT_NBR);
      }
    
      public BIDdfDiscoverParams getLast()
      {
        return new BYourDriverDeviceId(LAST_UNIT_NBR);
      }
    
      public BIDdfDiscoverParams getNext()
      {
        int nextUnitNumber = getUnitNumber()+1;
        if (nextUnitNumber>LAST_UNIT_NBR) // Circles back to first
          return getFirst();
        else
          return new BYourDriverDeviceId(nextUnitNumber);
      }
    
      public boolean isAfter(BIDdfDiscoverParams anotherId)
      {
        return this.getUnitNumber() >
               ((BYourDriverDeviceId)anotherId).getUnitNumber();
      }
    
      /**
       * When a control point is added to the station from the Dev
       * Point Manager, it is given this name by default (possibly
       * with a suffix to make it unique).
       * @return
       */
      public String getDiscoveryName()
      {
        return "NewDevice";
      }
    
      /**
       * Descendants need to return an array of TypeInfo objects corresponding
       * to all valid Niagara Ax types for this discovery object. This is
       * important when the end-user clicks 'Add' from the user interface for
       * the manager.
       *
       * For this discovery object, please  return a list of the types
       * which may be used to model it as a BComponent in the station
       * database. If the discovery object represents a device in your
       * driver then method should return an array with size of
       * at least one, filled with TypeInfo's that wrap the Niagara AX
       * TYPE's for your driver's device components.
       *
       * The type at index 0 in the array should be the type which
       * provides the best mapping.  Please return an empty array if the
       * discovery cannot be mapped.
       */
      public TypeInfo[] getValidDatabaseTypes()
      {
        return new TypeInfo[]{BYourDriverDevice.TYPE.getTypeInfo()};
      }
    
    }
    

  4. Your driver's device id structure, acting also as the device discover params structure, also needs to define the getDiscoverRequestType method (inherited from the interface BIDdfDiscoverParams) and return the BYourDriverPingRequest that you created in one of the previous day's lessons. This tutorial will soon show you how to update BYourDriverPingRequest to serve as the device discovery request too.

      /**
       * The implementing class needs to return a Type that represents
       * the discover request from the driver whose discoverId can be an
       * instance of this object's class. If the class supports more than
       * one discover request type, then this should return the type that is
       * the most appropriate for the particular instance of the implementing
       * class.
       *
       * This is fundamental to dev driver's auto-discovery features.
       *
       * @return review method description.
       */
      public Type getDiscoverRequestType()
      {
        return BYourDriverPingRequest.TYPE;
      }
    

  5. Your driver's device id structure, acting also as the device discover params structure, also needs to define the getDiscoverRequestTypes method (inherited from the interface BIDdfDiscoverParams) and return an array of size 1, including whatever is returned by the getDiscoverRequestType method:

      /**
       * Some drivers might require multiple, completely different requests
       * to be used to discover devices. This should not be the case here though.
       *
       * @return review method description.
       */
      public Type[] getDiscoverRequestTypes()
      {
        return new Type[]{getDiscoverRequestType()};
      }
    

  6. Your driver's device id structure, acting also as the device discover params structure, also needs to define the getDiscoveryLeafType method (inherited from the interface BIDdfDiscoverParams) and return its own type (since it is acting as both the discover params and as the discovery leaf):

      /**
       * Some drivers could hypothetically group discovery objects. This
       * method returns the Type that will ultimately form the bottom-
       * most, non-grouped discovery objects. The columns of the device
       * manager will be determined from this type.
       *
       * In this case, the discovery leaf type is also BYourDriverDeviceId.
       *
       * @return review method description.
       */
      public Type getDiscoveryLeafType()
      {
        return getType();
      }
    

NOTE:If your driver communicates directly over Tcp/Ip or Udp/Ip and not through a Tcp/Ip or Udp/Ip gateway then a discovery is probably not possible. You may be able to do a Udp/Ip multi-cast discovery, depending on your equipment. However, that is beyond the scope of this tutorial. You will probably have to skip the chapters that pertain to device discovery (today's lesson).