You only need to worry about this chapter if your driver features the notion of overriding data points. Most equipment runs an internal program that updates some or all of the field-device's data values. Some protocols require a point to be placed into a special mode if and when it is controlled by an entity other than the field-device itself. In our hypothetical protocol such a mode takes effect by transmitting the ASCII string "force" in the byte array of the write request. Field-devices that have a notion of overriding points will usually need to be specially informed if and when the particular data value is no longer being controlled by the external entity. The dev driver framework makes this easy for you to implement in your driver.
To do this, you will create a point-auto request and possibly a point-auto response. Please follow these steps if this is necessary 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):
To do this, create a text file named BYourDriverPointAutoRequest.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.req; import com.tridium.ddf.comm.req.*; import javax.baja.sys.*; public class BYourDriverPointAutoRequest extends BDdfWriteRequest { /*- class BYourDriverPointAutoRequest { } -*/ }
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.
Assume that any data you need in order to construct the auto (unforce) message itself, ignoring any details about which particular data value to auto (unforce), is a frozen property on the write parameters structure (the same structure that your driver's write request uses to construct the byte array that it returns from its toByteArray method). If you need more information than your write parameters presently provides, then you will need to update your write parameters structure and add frozen properties for the required information.
In light of this discussion, please code the toByteArray method to return a byte array that matches the description that your protocol document defines for the message that you identify as the un-force or relinquish-auto 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, write requests are automatically assigned an instance // Of a Write Parameters structure when they are created, this point // auto request is an instance of BDdfWriteReqest. The dev driver // Framework calls the toByteArray method (function) after it // Creates the write request, therefore this particular request has // already been assigned a device id, and a Write parameters // structure. The deviceId will be an instance of BYourDriverDeviceId, // the writeParameters structure will be an instance of // BYourDriverWriteParameters, // That is how dev driver works! This happens automatically. BYourDriverDeviceId deviceId = (BYourDriverDeviceId)getDeviceId(); BYourDriverWriteParams writeParams = (BYourDriverWriteParams)getWriteParameters(); final byte SOH = 0x01; final byte EOT = 0x04; // In this hypothetical example, the protocol document // Indicates that all requests start with a hex 01 byte and // All requests end with a hex 04 byte. // After the hex 01, the protocol expects a number between // 0 and 255 to identify the device, followed by the ASCII // Characters "Unforce ", followed by one or more of the // following: // ao{X} // do{X} // Where: // {X} = a sequence of ASCII digits '0'-'9' to identify which // analog or digital output to change. // // If more than one of these sequences are present then they are // delimited by commas. // The message ends with a hex 04 terminator byte. // ByteArrayOuptutStream is a standard Java class in package java.io // Let's use it to help us build the byte array that we will return ByteArrayOutputStream bos = new ByteArrayOutputStream(); // Writes the hex 01 start character to bos, our Java stream of // bytes. bos.write(SOH); // Writes the unit number onto bos, our Java stream of bytes. bos.write(deviceId.getUnitNumber()); // Writes the ASCII bytes for "unforce" followed by a space to // bos, our Java stream of bytes bos.write('u'); bos.write('n'); bos.write('f'); bos.write('o'); bos.write('r'); bos.write('c'); bos.write('e'); bos.write(' '); // Loops through all control points that are to be auto 'ed (unforced) by this request. // The dev driver framework will try to coalesce all control points that need updated // Under a device that have equivalent write parameters into a single write // Request. You can get the array of these items by calling the method // named getWritableSource. It returns an array of IDdfWritable -- these // will be the proxy extensions of your driver's control points. IDdfWritable pointsToUpdate[] = getWritableSource(); for (int i=0; i<pointsToUpdate.length;i++) { // This is a good thing to check in case dev driver adds support for // Auto'ing components that are not proxy extensions if (pointsToUpdate[i] instanceof BYourDriverProxyExt) { // Casts the IDdfWritable to BYourDriverProxyExt BYourDriverProxyExt updateProxy = (BYourDriverProxyExt)pointsToUpdate[i]; // Gets the read parameters structure, it helped BYourDriverReadRequest // know whether to read analog or digital. We can make optimal use of this // property by re-using it here also. BYourDriverReadParams proxyReadParams = (BYourDriverReadParams)updateProxy.getReadParameters(); // Gets the point id structure for the particular point. We previously // defined it to contain an offset. We can make optimal use of this offset // by re-using it here also. BYourDriverPointId proxyPointId = (BYourDriverPointId)updateProxy.getPointId(); if (proxyReadParams.getTypeString().equalsIgnoreCase("analog")) { // If updating an analog output on the field-device bos.write('a'); bos.write('o'); } else if (proxyReadParams.getTypeString().equalsIgnoreCase("digital")) { // Else, if updating a digital output on the field-device bos.write('d'); bos.write('o'); } else // Sanity check throw new RuntimeException("Oops! Auto'ing type string '"+ proxyReadParams.getTypeString()+"' is not supported."); // Writes the point index as a string bos.write(Integer.toString(proxyId.getOffset()).getBytes()); if(i+1<pointsToUpdate.length) // If not the last point in the loop bos.write(','); // Then this writes a comma } // End of if instanceof etc. } // End of for loop // Writes the byte that according to our hypothetical protocol, // Indicates the end of the message on the field-bus. bos.write(EOT); // Converts the stream of bytes in our Java stream of bytes into // An actual Java byte array and returns it. return bos.toByteArray(); }
To recap part of day 1's lesson, the dev 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 using the following Java code as a guide. You may notice that this hypothetical example is nearly identical to the processReceive method that was in the example for the read request!
public BIDdfResponse processReceive(IDdfDataFrame recieveFrame) throws DdfResponseException { // We coded our hypothetical receiver such that received frames always have // at least 2 bytes. So lets not worry about checking for that String responseStatus = new String( // Constructs a string from bytes receiveFrame.getFrameBytes(), // In the receive frame buffer 2, // Starting at index 2, taking receiveFrame.getFrameSize()-3); // All chars except SOH, unitNbr, and EOT // According to our hypothetical protocol, the device responds 'OK' if the // Request succeeds. Any other string denies the write. In the event of a // Denial, the string itself describes the denial in plain English. if (responseStatus.equalsIgnoreCase("OK")) return new BYourDriverWriteResponse(); // <-In this case our auto // response has the // equivalent functionality // as BYourDriverWriteResponse // So we can re-use it. else throw new DdfResponseException("Equipment Nak During Auto - "+responseStatus); }
As a guide, please follow the instructions in the earlier chapter of today's lesson where we showed you how to create your driver's write response.
Do this by changing the class declaration on BYourDriverWriteParams to specify that it also implements the BIDdfAutoParams interface. Then define a method called getDevAutoRequestType on BYourDriverWriteRequest
Follow this example as a guide:
package com.yourCompany.yourDriver.identify; import com.tridium.ddf.identify.*; import javax.baja.sys.*; public class BYourDriverWriteParams extends BDdfIdParams implements BIDdfWriteParams, BIDdfAutoParams { /*- class BYourDriverWriteParams { properties { forceWrite : boolean -- This property has nothing to with the dev -- driver framework itself. Instead, we need -- to construct the toByteArray method of the -- driver's write request in following the -- driver's protocol to write data values. -- In this hypothetical protocol, if we do not -- forceWrite then the equipment's internal -- program could overwrite any change that -- Niagara might make to a data value. default{[true]} } } -*/ public Type getWriteRequestType(){return BYourDriverWriteRequest.TYPE;} public Type getAutoRequestType(){return BYourDriverPointAutoRequest.TYPE;} }
Copyright © 2000-2014 Tridium Inc. All rights reserved.