Chapter 9 - Create a Read Request For Your Driver

The developer driver framework will use your driver's read request to automatically read point values from a field-device and introduce them into the rest of the Niagara AX framework. Point values are represented virtually as a control point. Please follow these steps to create a read-request for your driver.

While following the examples in this chapter, please replace the text jarFileName, yourDriver and yourCompany as previously described in the Preparation section):

  1. Review your equipment's protocol documentation again. If you are working directly for the manufacturer of the equipment, then they should be able to provide you with one or more documents that describes the way in which the equipment communicates, plus the structure of the data that the equipment expects to see on the field-bus. If you have purchased this equipment then you will need to negotiate with the equipment's manufacturer in order to gain access to the equipment's protocol.
  2. Pick a message from your protocol that retrieves one or more data point values that you are interested in. After reviewing the equipment's protocol documentation, choose a message from the protocol that looks like the simplest message that accomplishes this task.

    Some protocols provide several messages that read point values. Some messages read point values as well as details about the point. For now, please only concern yourself with retrieving the actual value of the point, such as a single temperature value or other measurement. Please defer your concerns about retrieving extra information about the data point, such as engineering units (for example - whether it is Fahrenheit or Celsius) until later.

  3. Make a Java class that extends BDdfReadRequest. Name it BYourDriverReadRequest. Create this in the package named com.yourCompany.yourDriver.comm.req. Also add an empty slotomatic comment immediately after the opening brace for the class declaration.

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

    package com.yourCompany.yourDriver.comm.req;
    
    import javax.baja.sys.*;
    import javax.baja.io.*;
    
    import com.tridium.ddf.comm.*;
    import com.tridium.ddf.comm.req.*;
    import com.tridium.ddf.comm.rsp.*;
    
    import com.yourCompany.yourDriver.identify.*;
    import com.yourCompany.yourDriver.comm.rsp.*;
    
    public class BYourDriverReadRequest
      extends BDdfReadRequest
    {
      /*-
      class BYourDriverReadRequest
      {
      }
      -*/
    }
    

  4. Override the toByteArray method. Build the byte array following your protocol's read message.

    Inside the body of the toByteArray method, you will need to construct a Java byte array and return it. The next step will further describe how to do this.

    To add the toByteArray method, add the following lines of text after the slotomatic comment of the class:

      public byte[] toByteArray()
      {
      }
    

  5. Assume that any data you need that is unique to your protocol message for reading data points is the value in a frozen property on another class that extends BDdfReadParams. This other class is called the read parameters structure. It is very similar to the device id structure that was automatically available to the ping request during yesterday's lesson. Just like the ping request class, the read request automatically has access to a copy of the device id structure. In addition, the read request class automatically also has access to a copy of your driver's read parameters structure.

    Please do not be overwhelmed at the mention of this. Suffice it to say, you will soon create another class that we will call the read parameters structure. On this class, you will define one or more frozen properties that contains the information necessary, other than information about the device itself -- which you already placed in your device id structure, to transmit a request to read one or more data values from a field-device.

    As mentioned during the lesson for day 1, frozen properties are a special kind of Niagara AX property on a Niagara AX component that you can easily access from Java source code. In subsequent chapters, you will make the class for the read parameters structure. For now, please proceed as though you have already created it.

    In light of all this discussion, please finish updating the toByteArray method to return a byte array that matches the description that your protocol document defines for the message that you chose to be the read request. Please follow this example as a guide:

      public byte[] toByteArray()
      {
        // In the dev driver framework, all requests are automatically
        // Assigned a deviceId when they are created. In addition to the
        // DeviceId, read requests are automatically assigned an instance
        // Of a Read Parameters structure when they are created. The dev
        // Driver framework calls the toByteArray method (function) after
        // It creates the read request, therefore this particular request
        // Has already been assigned a device id and  read parameters
        // structure. The deviceId will be an instance of BYourDriverDeviceId,
        // The readParameters structure will be an instance of
        // BYourDriverReadParams.
        // That is how dev driver works! This happens automatically for
        // Your convenience!
    
        BYourDriverDeviceId deviceId =
          (BYourDriverDeviceId)getDeviceId();
    
        BYourDriverReadParams readParams =
          (BYourDriverReadParams)getReadParameters();
    
        final byte SOH = 0x01;
        final byte EOT = 0x04;
        // In this hypothetical example, the protocol document would
        // Indicate that all requests start with a hex 01 byte and
        // All requests end with a hex 04 byte.
        // So, after the hex 01, the protocol expects a number between
        // 0 and 255 to identify the device, followed by some ASCII
        // Characters ("read analog outputs", "read analog inputs".
        // "read digital outputs", or "read digital inputs" in this
        // case), followed by the hex 04 terminator byte.
    
        // ByteBuffer is a standard Niagara AX utility class in package
        // javax.baja.io
    
        // Let's use it to help us build the byte array that we will return
        ByteBuffer bbuf = new ByteBuffer();
        // Writes the hex 01 start character to bos, our byte buffer.
        bbuf.write(SOH);
        // Writes the unit number onto bbuf, our byte buffer.
        bbuf.write(deviceId.getUnitNumber());
        // Writes the ASCII bytes for the word "read" followed by a space to
        // bbuf, our byte buffer.
        bbuf.writeBytes("read ");
        // Writes the ASCII bytes for the value of the "type string" frozen
        // property that will be on our read parameters structure. Writes
        // this to bbuf, our byte buffer. For this sample driver, we
        // will create on our driver's read parameters structure a frozen
        // property called typeString. The value in this property is a
        // string. It will either be the string "analog" or "digital".
        bbuf.writeBytes(readParams.getTypeString());
        // Writes the ASCII byte for a space character. Note, we are
        // Following our hypothetical driver's protocol structure.
        bbuf.write(' ');
        // Writes the ASCII bytes for the value of the "direction" frozen
        // Property that will be on our read parameters structure. Writes
        // This to bbuf, our buffer of bytes. For this sample driver,
        // We will also create on our driver's read parameters structure
        // A frozen property called direction. The value in this property
        // Is a string. It will either be the string "outputs" or "inputs".
        bbuf.writeBytes(readParams.getDirection());
        // Writes the byte that according to our hypothetical protocol,
        // Indicates the end of the message on the field-bus.
        bbuf.write(EOT);
        // Converts the byte buffer into an actual Java byte
        // Array and returns it.
        return bbuf.toByteArray();
      }
    

  6. Override the processReceive method and return a new instance of your read response class (to be created in a subsequent chapter).

    To recap part of day 1's lesson, the developer driver framework calls the toByteArray method (function), transmits the resulting byte array onto the field-bus, looks for incoming data frames, and passes them to this method (until this method returns a response (not null), throws an exception, or times out.

    Please implement the processReceive method as follows:

      public BIDdfResponse processReceive(IDdfDataFrame receiveFrame)
        throws DdfResponseException
      {
        return new BYourDriverReadResponse(receiveFrame);
      }
    

    NOTE:When adding methods (functions) please add them to the bottom of your class file (just above the closing squiggly brace). This is to ensure that you do not add your function into the section towards the top of the class that is reserved for the source code that the slotomatic utility automatically generates. Accidentally placing code up there could result in the code being lost when you run the slot.exe program.