+ All Categories
Home > Documents > Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use...

Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use...

Date post: 28-Jul-2020
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
29
Developing a device adapter and agent for the WebSphere RFID solution, Part 2: Building the transport component Skill Level: Intermediate Karl Freburger ([email protected]) IT Architect IBM Allen Smith ([email protected] ) Senior Software Engineer IBM 31 Jan 2007 In Part 2 of this series, you'll learn how to begin implementing an adapter with the IBM® WebSphere® RFID Device Kit component of the WebSphere RFID Device Infrastructure, starting with the transport layer and using the Sirit™ INfinity 510 reader as an example. Introduction This article continues our look at how to build adapters and agents to integrate RFID readers into the IBM Websphere RFID solution. Part 1 described the IBM WebSphere RFID solution and the WebSphere RFID Device Infrastructure. In Part 2, you'll learn how to begin implementing an adapter, starting with the bottom layer of the Device Kit, the transport, and use the Sirit INfinity 510 reader as an example. Transports in Device Kit As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement an adapter for a reader. The Device Kit consists of several layers, as shown in Figure 1. We'll begin implementing the adapter by constructing a transport. Figure 1. Device Kit adapter Building the transport component © Copyright IBM Corporation 1994, 2006. All rights reserved. Page 1 of 29
Transcript
Page 1: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Developing a device adapter and agent for theWebSphere RFID solution, Part 2: Building thetransport componentSkill Level: Intermediate

Karl Freburger ([email protected])IT ArchitectIBM

Allen Smith ([email protected] )Senior Software EngineerIBM

31 Jan 2007

In Part 2 of this series, you'll learn how to begin implementing an adapter with theIBM® WebSphere® RFID Device Kit component of the WebSphere RFID DeviceInfrastructure, starting with the transport layer and using the Sirit™ INfinity 510reader as an example.

Introduction

This article continues our look at how to build adapters and agents to integrate RFIDreaders into the IBM Websphere RFID solution. Part 1 described the IBMWebSphere RFID solution and the WebSphere RFID Device Infrastructure. In Part2, you'll learn how to begin implementing an adapter, starting with the bottom layerof the Device Kit, the transport, and use the Sirit INfinity 510 reader as an example.

Transports in Device Kit

As described in Part 1, we use the Device Kit component of the WebSphere RFIDDevice Infrastructure to implement an adapter for a reader. The Device Kit consistsof several layers, as shown in Figure 1. We'll begin implementing the adapter byconstructing a transport.

Figure 1. Device Kit adapter

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 1 of 29

Page 2: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

In Device Kit, the transport is responsible for converting bytes to more meaningfulobjects called messages. Bytes received from a device (reader) are parsed intomessages and delivered to listeners. Messages passed by an application to thetransport are converted into the appropriate bytes and sent to the device.

Transports are also responsible for initiating the connection to the hardware deviceusing the appropriate connection class, and for controlling any start-up conversationrequired by the device. Start-up conversations may include setting parameters onthe reader, logging into the reader, making connections to alternate messagechannels, and so on.

A transport is responsible for sending heartbeat messages to keep the connection toa hardware device alive.

A transport does not understand the messages it receives and sends; it is concernedwith syntax, not semantics. It understands the hardware device protocol enough toparse messages from the input bytes and to ensure that output bytes have thenecessary checksums, and so on. The only messages that a transport should reallyknow about are those that are used in start-up conversations and heartbeats.

When integrating a new hardware device into WebSphere RFID DeviceInfrastructure, you'll create an initial definition of a transport using the Device KitTransport Creation wizard, and modify certain attributes of the transport by editing aCommand Markup Language (CML) file, but you'll also have to write Java™ code toimplement a transport specific to that device. Implementing the transport is often themost work when implementing an adapter for a new reader.

Transports and their collaborators

developerWorks® ibm.com/developerWorks

Building the transport componentPage 2 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 3: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Transports collaborate with several other objects to get their job done. Figure 2shows the major collaborators.

• One transport (an instance of a subtype ofcom.ibm.esc.transport.service.TransportService).

• One connection (an instance of a subtype ofcom.ibm.esc.connection.service.ConnectionService) thathandles the communication to and from the RFID reader.

• One controller (an instance ofcom.ibm.esc.transport.Controller) that handles forwardingmessages, errors, and state changes to transport's listeners, restarts thetransport if there is an error, and notifies the transport when to send aheartbeat message.

• Zero or more applications that are sources of bytes to write to the device.Applications can be any type.

• Zero or more listeners that are the receivers of messages parsed by thetransport. Listeners are instances of subtypes ofcom.ibm.esc.transport.service.TransportListener. Mostoften the application and the listener are the same object (an instance ofa subclass of com.ibm.esc.device.TransportDevice).

Figure 2. Transport collaborators

To illustrate the collaboration between the transport and the other objects, take alook at what happens when an application asks a transport to send a message to adevice:

1. The application invokes send(Messageservice message) on thetransport.

2. The transport formats the message and invokes write(byte[]

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 3 of 29

Page 4: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

bytes, int offset, int count) on a connection.

3. The connection writes the bytes to the device.

When a transport receives a message from a device, the flow is considerably morecomplex, as shown in Figure 3:

1. The transport runs a Thread doing processInput() on itself.

2. processInput() invokes read(byte[], int, int) on theconnection (step 1 in the diagram).

3. The connection waits for bytes to come from the reader (step 2).

4. When bytes are returned, the transport invokesprocessInput(byte[], int) on itself (step 3).

5. processInput(byte[], int) parses the bytes into messages. Whenit finds one, it invokes fireMessageReceived(MessageService,Object) on the transport (step 4).

6. fireMessageReceived(MessageService, Object) notifies thecontroller that a message is available by invokingmessageReceived(TransportService, Object,MessageService) (step 5).

7. The controller inspects the arriving message and determines whether thetransport should be interested in it (using an interest mask that thetransport defines).

8. If the message is not of interest, it is discarded. Otherwise, the controllerqueues the received message.

9. A separate Thread in the controller picks up the message to process it.This has the effect of decoupling message producers from messageconsumers and prevents thread blocking issues.

10. The message is delivered to the listeners registered with the transport byinvoking messageReceived(TransportService, Object,MessageService) on them (step 6).

Fortunately, in our case, the controller is already implemented for you and you don'thave to worry about the details of interest masks, the message queue, and threads.

Figure 3. Transport receiving a message

developerWorks® ibm.com/developerWorks

Building the transport componentPage 4 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 5: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Transport classes and interfaces

All transports are instances of subtypes ofcom.ibm.esc.transport.service.TransportService. In practice, they areinstances of subclasses of com.ibm.esc.transport.Transport to inheritalready implemented behavior. There are several subclasses ofcom.ibm.esc.transport.Transport; the most common used for RFID readersis com.ibm.esc.transport.ResponseTransport because most RFID readersimplement a command/response model of interaction. A ResponseTransportblocks writes until the response to the previous write is received, or the responsetimeout expires. Messages received from a reader are classified as responses to apreviously sent message, or as non-responses. An example of a non-responsewould be an asynchronous event message.

ResponseTransport defines some useful methods, some of which you need toimplement:

• void write(MessageService message) is responsible for writingbytes to a connection. It should "preprocess" messages to computechecksums, lengths, and so on, required by the protocol. Messages areassumed to be the correct (final) number of bytes to be written. If theprotocol does not require modifying messages before writing, you can justkeep the default implementation of the method; otherwise you'll need toimplement it.

• int processInput(byte[] buffer, int length) implementsthe parsing of bytes into instances of subtypes of

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 5 of 29

Page 6: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

com.ibm.esc.message.service.MessageService. You need toreimplement this method for each type of transport since it is where theparsing work is done. The method should process up to length bytesfrom buffer into messages, and return the number of bytes processed(may be 0 if the buffer does not hold a complete message). As manymessages as possible should be processed before returning.

• MessageService noActivityProcessingMessage() returns themessage that will periodically be sent to the device as a "heartbeat" whenno other activity is taking place. We'll discuss heartbeats below. Eachtransport must reimplement this method unless there is no heartbeatmessage.

• int startup(boolean arg) implements any special start-up actionsneeded (such as sending a login command or starting an asynchronousevent handler). You may need to reimplement this method for a giventransport.

• void startupMessageReceived(TransportServicetransport, Object timestamp, MessageService message)implements the processing of messages during the start-up conversation.If the transport implements a start-up conversation, you need toimplement this method. We'll discuss start-up conversations below.

• void fireMessageReceived(Object timestamp,MessageService message) is invoked by the transport when it hasparsed a response message from the input bytes.

• void fireMessageReceivedNoResponse(Object timestamp,MessageService message) is invoked by the transport to signal that amessage it parsed is not a response to the previous output message.

• MessageService getSentMessage() returns the last message sent.It is useful when creating messages to connect a response with themessage that generated it.

• void responseReceived() is invoked by the transport to indicate thata response to the previous output message has been received. Normallyyou don't need to invoke this method, but if you have an error in parsingyou may need it.

• void handleError(Throwable error, int resourceId,Object[] objects) and its variants are used to notify the transportlisteners that an error has occurred. The int argument is a resource ID;it's easiest to use one of the IDs already defined in one of the Transportclasses.

• Object EscObject.getCurrentTimestamp() returns the currenttime as an Object and is useful for invoking those methods that requirea timestamp.

Certain methods are generated automatically from the CML file that defines thetransport:

developerWorks® ibm.com/developerWorks

Building the transport componentPage 6 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 7: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

• ConnectionService getDefaultConnection() returns aninstance of ConnectionService to connect to the reader.

• long getDefaultResponseTimeout() returns the default responsetimeout.

• void setup() initializes the transport and connection properties. We'lldiscuss configuration properties below.

• getX() methods for any custom parameters you defined in the CML.We'll discuss custom parameters below.

As you can see from the list, when you implement a new transport you will have toimplement processInput(byte[], int). You may have to implementwrite(MessageService), noActivityProcessingMessage(),startup(boolean), and startupMessageReceived(TransportService,Object, MessageService).

The processInput(byte[], int) method is the hardest of the group toimplement. Device Kit does not provide any generic parsing aids, so you'll have towrite all the code yourself. We suggest that you look at existing reader adapters witha protocol similar to your reader's for examples. When we discuss implementing thetransport for the Sirit INfinity 510 reader, we'll introduce some helper classes youcan use to reduce the work of parsing text-based message protocols.

The processInput(byte[], int) method should parse bytes from the buffer,start-to-end, and "consume" as many bytes as possible each time it is called.Consuming bytes means parsing them into message objects and invoking thefireMessageReceived(Object, MessageService) orfireMessageReceivedNoResponse(Object, MessageService) methods. Ifyour reader's protocol uses protocol decorations such as checksums or messagestart/end markers, processInput(byte[], int) should verify that they arecorrect and invoke handleError(Throwable, int, Object[]) if they are not.

The write(MessageService) method accepts messages that are the correctnumber of bytes long to write to the device, and changes bytes associated withprotocol decorations before writing. This ensures that, for example, checksums arealways correct for a message.

When a transport has not had any activity (received a message or written one) for aperiod of time, its controller instructs it to send a heartbeat message to the device.This allows the transport to discover in a timely manner when a connection or adevice has failed. It has the side effect of acting as a "keep alive" message for thoseconnections or devices that require periodic interaction. The no activity timeout is aconfiguration parameter (noactivitytimeout) that defaults to 10 seconds. Themessage to send as a heartbeat is defined by thenoActivityProcessingMessage() method. When selecting a heartbeatmessage, it's important to select a message that will "do no harm". For example, ifyour reader has a command to start reading RFID tags, and another command tostop reading, it's possible that the heartbeat message could be sent between them.The heartbeat message should not cause the tag reading to terminate. If

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 7 of 29

Page 8: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

noActivityProcessingMessage() returns null, no heartbeat message will besent.

One of the responsibilities of a transport is to engage in any start-up conversationrequired by the reader. If the device has a start-up conversation, you will need toimplement the startupMessageReceived(TransportService, Object,MessageService) method. It will be invoked whenever the transport parses amessage while the transport indicates that it is engaged in a start-up conversation.The method typically compares the message received with one or more templatemessages and, if it matches, sends another message, or ends the start-upconversation and starts processing input normally. If the transport needs to send amessage to begin the start-up conversation, you'll need to override thestartup(boolean) method to send that message.

Transport lifecycle

A transport goes through a set of states during its lifetime. Most of the statetransitions are handled automatically, but sometimes you may have to control thestate. All of the states are defined as static constants on TransportService:

• The CREATED state is when the transport has been created or stopped.The transport will not attempt to move to another state until a start requestis received.

• The ALIVE state is when the transport has been told to start.

• The CONNECTED state is when the transport is connected to the hardwaredevice.

• The ACTIVE state is when the transport is attempting to start but is notyet started. Usually this means a start-up conversation is being done withthe device.

• The STARTED state is when the transport has started and should beprocessing messages.

• The DEAD state is when the transport has exited and cannot be restarted.

The default implementation of Transport.startup(boolean) puts the transportinto the STARTED state. If you need to implement a start-up conversation in thetransport, startup(boolean) should put the transport into the ACTIVE state toindicate that a start-up conversation is underway. When the start-up conversation isdone, the transport should be put into the STARTED state usingTransport.setState(int), probably in thestartUpMessageReceived(TransportService, Object,MessageService) method.

Transport CML

When you create a new transport with the Device Kit Transport Creation wizard, atransport project is created that contains a NameTransport.cml file, where Name isderived from the name of your transport. The CML file contains the definition of

developerWorks® ibm.com/developerWorks

Building the transport componentPage 8 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 9: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

various transport parameters. The Device Kit tools allow you to regenerate theskeletal definition of your transport (without losing any code you may have added)based on the contents of the CML file.

Some of the typical subelements of the <transport> element are:

• <responsetimeout> defines the response timeout. If this element ispresent, the Device Kit tools make the transport a subclass ofResponseTransport.

• <noactivitytimeout> defines the time of no activity before a transportsends a heartbeat message.

• <tcpip> or <serial> define the configuration of the transport's defaultconnection.

• <message> elements define messages used by the transport. Definingmessages in CML is described in Part 1.

• <customparameter> defines a custom configuration property for thetransport.

For a complete description of the transport CML, refer to the Websphere StudioDevice Developer documentation (when the RFID Tracking Kit is installed).

Configuring transports

Transports have various configuration properties. Some of them are standardproperties defined by the Transport subclasses (for example, the responsetimeout). Some of them are custom properties defined in the CML for a particulartransport. In each case, the property has a default value. Properties may be givennew values by:

• Setting the property in Java code via the setX() method defined for theproperty.

• Setting the property in Java code via theputConfigurationInformation(String, Object) method.

• Setting the property in the esc.properties file.

Configuration properties are named name.propertyname, where name is derivedfrom the transport class name, and propertyname is the name of the property. Forexample, sirittransport.readtimeout is the property name used in theesc.properties file and by the putConfigurationInformation(String,Object) method for the example transport that we'll implement later in this article.The same property can be set by the setResponseTimeout(long) method andretrieved by the getResponseTimeout() method (note the difference in theproperty name).

To set properties in the esc.properties file, edit the file and use the comments as amodel (the comments include all the configuration properties that can be set, and

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 9 of 29

Page 10: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

their default values). Put the esc.properties file in the current directory of whateverJava program is executing the transport.

Transports and messages

The primary function of a transport is to convert messages and bytes and vice versa.Transports parse bytes and create messages from them, and accept messages andcreate bytes from them.

Generally, transports should not have any knowledge of the semantics of messages.However, the transport does have to know about heartbeat messages andmessages used during a start-up conversation. All messages that a transport hasdirect knowledge of should be defined in the transport CML file. The messages maybe either concrete or template messages (see Part 1 for a discussion of messages).If a start-up conversation composes messages on the fly (such as a password echothat substitutes * for the characters in the password), those messages do not needto be defined in the CML.

When a transport parses incoming bytes into a message, it may create an instanceof any subtype of MessageService. There are several subtypes available, andselecting the right one may simplify things later. If the protocol is text-based,consider creating a subclass of com.ibm.esc.message.AsciiMessage (forclarity). If the protocol uses \r\n as a message terminator, use a subclass ofcom.ibm.esc.message.AsciiCrlfMessage. That class excludes the \r\nfrom the data portion of the message. If the transport is a subclass ofResponseTransport, consider using a subtype ofcom.ibm.esc.message.service.ResponseMessageService and set the sentmessage, if possible (use the transport getSentMessage() method). That permitsconnecting a response message with the message that generated it, making devicemodeling easier later.

The messages created by a transport are used later by the Device Kit devicecomponent to interact with and interpret the results from a reader (see Part 1 for anoverview). To make device modeling easier, you may find it useful to implementaccess to the message fields. For example, if a message defines key/value pairs, it'suseful to be able to access the values by the keys. To do so, the get(Object)method needs to find the value corresponding to the field. In some cases, using"virtual" keys is useful. For example, if the reader protocol defines the responses tocommands to "get attribute X" as "OK value ", it might be useful to define key "0"to be the message up to (but not including) the space character, and key "1" to beeverything from the character after the space to the end of the data. None of theDevice Kit-provided message classes implement field accessing.

Our recommendation is for transports to define a custom message class and alwayscreate instances of it. The custom message class should subclass the appropriatemessage class (AsciiMessage, AsciiResponseMessage, and so on), and:

• Override getDataLength() to return the number of bits that define the

developerWorks® ibm.com/developerWorks

Building the transport componentPage 10 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 11: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

data portion of the message (usually excluding message terminators andtrailers, such as checksums). Only bits at the end of the message may beexcluded.

• Implement access to the message fields if possible. Overrideget(Object) to parse the message fields to find the valuecorresponding to the key argument.

Transports and connections

Transports use Device Kit connections as a communication channel to and from thehardware device. Device Kit provides several types of connections. The ones thatare most relevant to RFID readers are:

• com.ibm.esc.tcpip.connection.TcpipConnection for TCP/IPclient connections

• com.ibm.esc.serial.connection.SerialConnection for serial(RS232) port connections

• com.ibm.esc.tcpip.server.connection.TcpipServerConnectionfor cases where a device initiates a connection to a transport

It's very rare that you'd have to implement a new type of connection.

In addition to the usual command/response connection to the reader, some readerssupport an alternate message channel, over which some messages (such as tagread events) may be delivered. The alternate channel may be transport-initiated ordevice-initiated. Transport-initiated alternate channels require the transport to createanother connection to the reader (often using a TcpipConnection).Device-initiated alternate channels require that the device be configured with a hostand port to contact. In that case, the transport listens for a connection from thedevice (probably using a TcpipServerConnection).

To use an alternate message channel, a transport requires a few changes:

• The transport must start the connection at the right time (usually duringthe start-up conversation).

• The transport must parse the messages coming from the alternatechannel, and treat them appropriately (for example, they will almostalways not be response messages).

• The transport must shut down the alternate channel at the right time.

• The transport must be prepared to handle the alternate channel beingshut down prematurely.

Using an alternate message channel requires a transport to define customconfiguration parameters.

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 11 of 29

Page 12: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Testing transports

When you create a new transport using the Device Kit Transport Creation wizard,you're given an option to create a test project. If you select that option, you caneasily create test cases for your transport.

Unlike developing a transport, writing test cases does not require writing any Javacode; test cases are specified using CML. After you edit the CML file in the transporttest project, regenerate the test application using the Device Kit tools byright-clicking the test CML file and selecting Device Kit => Generate. Then run thetest application by selecting the transport test project, the selecting Run => Run As=> Java Application.

Transport tests consist of sending messages to a device. If you have tracing turnedon, you should see enough information in the logs (messages sent and received) todetermine whether the test was successful. There is no automated comparison ofexpected results with actual results.

To create a test case in CML, you need to edit the test project's CML file, and insertone or more <send> elements after the <description> element of<transporttest>. Each <send> element groups a set of <message> elementsthat define the messages to send as the test. Listing 1 shows a simple example.

Listing 1. Sample transport test CML

<send id="LoginAndStatus"><message id="ReaderWhoAmI">

<ascii>reader.who_am_i()\r\n</ascii></message><message idref="ReaderWhoAmI"></message>

<message><ascii>reader.check_status()\r\n</ascii>

</message></send>

You can modify the esc.properties file in the test project to set properties to controlthe test. The most common properties to override are those to set the host (readerto connect to) and the testcount (number of tests to run, usually 1). Thetotaltesttime property controls the maximum running time of the test; when thetime is up, the test is terminated, whether it's done or not. Set the esc.tracelevelproperty to 10 to get the maximum amount of trace information for your test.

Building a transport for the Sirit INfinity 510 reader

This example guides you through the steps to create and test a transport for a SiritINfinity 510 RFID reader, including instructions on how to develop all the necessarypieces.

Prerequisites

developerWorks® ibm.com/developerWorks

Building the transport componentPage 12 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 13: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

You'll need the following to complete this exercise:

• WebSphere Studio Device Developer Version 5.1.7 installed with theWebSphere RFID Tracking Kit 1.1.1.

• Sirit INfinity 510 reader.

• INfinity 510 Protocol Reference Guide

You can download the completed example and some helper classes that we'll referto in the Downloads section.

Understand the reader protocol

Before you implement your transport, you need to make sure you understand theprotocol conventions for your reader. The INfinity 510 Protocol Reference Guidestates:

• The reader's protocol is ASCII text based.

• You connect to port 50007 to send commands and receive responsesfrom the reader.

• You connect to port 50008 to receive asynchronous event messages(including tag reads).

• All commands end in \r\n.

• All responses and events end in \r\n\r\n.

Create the transport

We'll use the Transport Creation wizard to generate a skeleton transport for the SiritINfinity 510 reader. To generate the transport, do the following:

1. Select File => New => Other.

2. Select Device Kit, then select Transport to open the wizard.

3. Click Next.

4. Fill in the following fields, as shown in Figure 4):

• Transport Name: Sirit

• Package Base: devworks.example

• Response Timeout: 1000

• Connection: TCPIP

5. Check all of the generation options, then click Next.Figure 4. Specify transport name and options

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 13 of 29

Page 14: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

6. In the next dialog, fill in the following fields (leave any other fields empty),as shown in Figure 5:

• Host: localhost

• Remote port: 50007

7. Click Finish to generate the transport code.Figure 5. Specify host name and port

developerWorks® ibm.com/developerWorks

Building the transport componentPage 14 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 15: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

8. Take a look at what was generated in the SiritTransport andSiritTransportTest projects:Figure 6. Transport creation results

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 15 of 29

Page 16: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Test the transport connection

Test that your transport can connect to your reader by doing the following:

1. In the SiritTransportTest project, find the esc.properties file. Add thefollowing properties to the end of the file:

esc.tracelevel=10sirittransporttest.testcount=1sirittransporttest.host=ip address of reader

These properties say that we want our tests to produce maximum traceoutput, to run one time, and that we want to connect to our reader.

developerWorks® ibm.com/developerWorks

Building the transport componentPage 16 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 17: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

2. Run the SiritTransportTest application. You should see output messagesindicating that a connection was made to the reader and that the transportstarted. The key message that indicates that the transport started is:

[INFO] 2006-10-19 14:27:04.110 - TransportTest4005: Received transportstate changed to STARTED from ACTIVE.

3. Kill the test application or wait about one minute for it to stop.

Implement a custom message class

Define a new class, SiritMessage, in the same package as your transportimplementation. Since the Sirit reader uses an ASCII text based protocol and acommand/response style of interaction, you should make the superclasscom.ibm.esc.message.AsciiResponseMessage.

Redefine the getDataLength() method of your new class to exclude messageterminators from the data part of the message. The Sirit INfinity 510 uses \r\n\r\nas a message terminator, so getDataLength() should return the number of bits inthe message excluding the last 4 characters.

public int getDataLength() {// ignore the CR+LF+CR+LF at the end of the message

return (getBytes().length - 4) << 3;}

Implement the write(MessageService) method

The Sirit reader does not use any protocol decorations; messages are output exactlyas they are handed to the transport for writing, so you don't need to modify thewrite(MessageService) method.

Implement the processInput(byte[], int) method

The major work of a transport is to parse incoming bytes from a device intoinstances of MessageService that other Device Kit components can process.Although Device Kit doesn't provide any support for parsing incoming bytes, we havesome helper classes to make the job a little easier.

Load the DeveloperWorksTransportHelpers project from thetransport_helpers_project.zip file in the Downloads section

We'll use the parsing helper classes in the devworks.example.message.parserspackage:

• SimpleTerminatedMessageParser implements a simple parser thatrecognizes the end of a message by a predefined terminator (on the Sirit,that will be \r\n\r\n).

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 17 of 29

Page 18: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

• MessageParserListener defines the listener that aSimpleTerminatedMessageParser notifies when it parses amessage.

1. First, define a private field in the transport to hold the parser you'll create:

private SimpleTerminatedMessageParser parser;

2. Create the parser in the startup(boolean) method:

public int startup(boolean output) throws Exception {parser =

new SimpleTerminatedMessageParser(createParserListener(),"\r\n\r\n");

return TransportService.STARTED;}

3. The createParserListener() method creates an instance ofMessageParserListener that is notified when the parser finds amessage:

protected MessageParserListener createParserListener() {return new MessageParserListener() {

public void parsedMessage(byte[] bytes, boolean maybeResponse, Object timestamp) {MessageService m =

new SiritMessage(bytes,maybeResponse ?

SiritTransport.this.sentMessage :null);

if (maybeResponse) {SiritTransport.this.fireMessageReceived(timestamp, m);

}else {

SiritTransport.this.fireMessageReceivedNoResponsetimestamp, m);}

}};

}

Use an anonymous inner class here, instead of defining the transport toimplement the MessageParserListener interface, because when youregenerate the transport from the CML file (when you add new messagedefinitions, for example), the code generator overwrites your definitionwith its own.

4. Note that when the parser notifies the listener that it has found amessage, you create an instance of our custom message class, andconnect it to the message that generated it (if maybeResponse is true).

5. Finally, implement the processInput(byte[], int) method:

protected int processInput(byte[] bytes, int length) {

developerWorks® ibm.com/developerWorks

Building the transport componentPage 18 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 19: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

return parser.parseMessages(bytes, length, true);}

Delegate the parsing to the parser helper. The true argument tells theparser that the received message might be a response (for the Siritreader, it is a response because it came from the command/responseconnection).

Test the write(MessageService) and processInput(byte[], int) methods

To test the transport, create a test application using CML. The test application willsend various messages to the reader and you can inspect the output to determine ifthe responses were parsed correctly.

1. Edit the SiritTransportTest.cml file in the SiritTransportTest project. Insertsome <message> elements to specify what commands to send to thereader. You need to group <message> elements into logical tests usingthe <send> element.

2. Add the following after the <description> element:

<send id="LoginAndStatus"><message id="ReaderWhoAmI">

<ascii>reader.who_am_i()\r\n</ascii></message><message>

<ascii>reader.login(login = admin, pwd=readeradmin)\r\n</ascii></message><message idref="ReaderWhoAmI"></message><message>

<ascii>reader.check_status()\r\n</ascii></message><message>

<ascii>com.network.1.mac_address\r\n</ascii></message><message>

<ascii>info.time\r\n</ascii></message><message>

<ascii>setup.protocols\r\n</ascii></send><send id="ReaderVersion">

<message><ascii>version.hw\r\n</ascii>

</message><message>

<ascii>version.sw\r\n</ascii></message>

</send><send id="ErrorMessages">

<message><ascii>foo.bar\r\n</ascii>

</message></send>

This gives a variety of commands to check the output of.

3. Save the CML file and regenerate the test application by right-clicking onthe file, and selecting Device Kit => Generate. If you get errors after

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 19 of 29

Page 20: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

regenerating the transport, first check to make sure that there aren'tsyntax errors in the Java code. If so, fix them. If you still get errors,right-click SiritTransportTest, and select SMF => Re-Cache All,then SMF => Validate All.

4. Run the test application. You should see many messages on the console.Look through them to ensure that the commands sent and the responsesparsed look correct. Be sure that the responses include the terminatorcharacters (\r\n\r\n) like this:

[DEBUG] 2006-10-19 17:19:04.260 - Transport2023: Message receivednotification.

transport: SiritTransport@34e234e2=STARTEDmessage: "ok

0.4.4265\r\n\r\n" <- "version.sw\r\n"

You should see the command output and response messages "paired up"in log messages like this:

[DEBUG] 2006-10-19 15:55:06.476 - Transport2023: Message received notification.transport: RfidSiritCliTransport@34a034a0=STARTEDmessage: "ok isoc\r\n\r\n" <- "setup.protocols\r\n"

Define the heartbeat message

All of the heartbeat ("no activity processing") machinery is implemented insuperclasses of your transport. All you have to do is define what message to send.Think carefully when selecting a message; it should have no side effects, be easy forthe reader to execute, and have a small amount of output. For this example, use theversion.sw message.

Once you've selected the message you want to use, you need to override thenoActivityProcessingMessage() method in your transport to return thatmessage. All messages used by a transport are defined in the transport CML file.

1. Edit the SiritTransport.cml file in the SiritTransportDevelopment folder ofthe SiritTransport project.

2. Add the following message definition between the <description> and<responsetimeout> elements:

<message id="VersionSwGetMessage"><ascii>version.sw\r\n</ascii>

</message>

3. Regenerate the transport definition from the CML by right-clicking theCML file, then selecting Device Kit => Generate.

4. Look in the SiritTransportMessages class. You should see a

developerWorks® ibm.com/developerWorks

Building the transport componentPage 20 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 21: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

definition for the message. Return that message from thenoActivityProcessingMessage() method:

public MessageService noActivityProcessingMessage() {return SiritTransportMessages.getVersionSwGetMessage();

}

5. If you want to define a different default time during which no activityoccurs before sending the no activity message, edit your transport CMLand add the following to the <transport> element:

<noactivitytimeout>value</noactivitytimeout>

6. You can also configure the no activity timeout by editing theesc.properties file in the transport test project and adding a property(timeout in milliseconds) to the end of the file:

sirittransporttest.noactivitytimeout=8000

Test the heartbeat message

Rerun the previous test. At the end of the test output, you should see theversion.sw message being sent, and a response received, approximately every10 seconds (or whatever timeout you configured).

Create an event channel connection

The Sirit INfinity 510 requires your transport to connect to a second port, 50008, toreceive asynchronous notification of events. In addition, the reader uses a way ofregistering for events you're interested in receiving that requires the transport tosubmit a token that the reader handed out when the connection to port 50008 wasfirst made.

Device Kit doesn't support creating alternate message channels, so we'veimplemented some helper classes to make the job a little easier. You can find thesein the devworks.example.alternate.channel.handler package of theDeveloperWorksTransportHelpers project.

The alternate message channel helpers are:

• AlternateChannelMessageHandler handles connecting to andreceiving bytes from an alternate connection.

• AlternateChannelMessageListener defines the listener that aAlternateChannelMessageHandler notifies when it has input toprocess.

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 21 of 29

Page 22: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

1. The event channel port number to connect to, 50008, is fixed on the Sirit,but to follow conventions, you should make it a configurable property ofyour transport. To do that, edit the transport CML file to add a customproperty after the <description> element:

<customparameter name="eventport"type="int"defaultvalue="50008"access="true"/>

2. Also add other configuration properties needed by theAlternateChannelMessageHandler:

<customparameter name="eventChannelRetryTime"type="int"defaultvalue="2000"access="true"/>

<customparameter name="eventChannelRetryAttempts"type="int"defaultvalue="2"access="true"/>

3. Regenerate your transport as before.

4. Next, define a private field in the transport to hold the alternate channelmessage handler you'll create:

private AlternateChannelMessageHandler eventChannel = null;

5. Define the start-up conversation to connect to the event channel andregister for events. The conversation begins by the transport connectingto the event channel:

public int startup(boolean output) throws Exception {parser =

new SimpleTerminatedMessageParser(createParserListener(), "\r\n\r\n");eventChannel =

new AlternateChannelMessageHandler(createAlternateChannelMessageListener(),"" + getEventport());

eventChannel.setNumberOfRetries(getEventChannelRetryAttempts());eventChannel.setRetryWait(getEventChannelRetryTime());eventChannel.start();return TransportService.ACTIVE;

}

Note that now startup(boolean) returns the state ACTIVE (instead ofSTARTED) to indicate that the transport is engaged in a start-upconversation.

6. Once the transport makes a connection to the event port, it will get amessage containing a token, which must then be used to register to

developerWorks® ibm.com/developerWorks

Building the transport componentPage 22 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 23: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

receive events. Define three new messages in the transport CML file:

<message id="EventConnectionReportMessage"><ascii>event.connection id = \r\n\r\n</ascii><parameter type="ascii">

<index>22</index></parameter><filter>

<bytes format="hex">ff, ff, ff, ff, ff, ff, ff, ff,ff, ff, ff, ff, ff,ff, ff, ff,ff, ff, ff, ff</bytes>

</filter></message><message id="ReaderBindMessage">

<ascii>reader.bind(id=)\r\n</ascii><parameter type="ascii">

<insert/><index>15</index>

</parameter><filter>

<bytes format="hex">ff, ff, ff, ff, ff, ff, ff,ff, ff, ff, ff, ff</bytes>

</filter></message><message id="OkReaderBindReportMessage">

<ascii>ok\r\n\r\n</ascii><sentmessage idref="ReaderBindMessage"/>

</message>

The EventConnectionReportMessage is what is received over theevent channel when the transport connects. It contains a token that isused in the ReaderBindMessage that the transport send to set as thedefault token to use when registering to receive events. Finally, theOkReaderBindReportMessage is the response. When the transportgets that message, the start-up conversation is over.

7. To implement the start-up conversation, override thestartUpMessageReceived(TransportService, Object,MessageService) method:

public void startupMessageReceived(TransportService source,Object timestamp,MessageService message) {

if (SiritTransportMessages.getEventConnectionReportMessage().matches(message) != null) {// got the event token, do the bind commandfinal Object token =

SiritTransportMessages.getEventConnectionReportMessage().decodeMessage(message);

putConfigurationInformation("event.connection.id", token);try {

final MessageService bind =(MessageService) SiritTransportMessages

.getReaderBindMessage()

.clone();write(bind.encodeMessage(bind, token));

}catch (CloneNotSupportedException cnse) {

handleError(cnse, CLONE_EXCEPTION_RESOURCE);}

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 23 of 29

Page 24: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

catch (Exception e) {handleError(e, WRITE_EXCEPTION_RESOURCE);

}return;

}if (SiritTransportMessages.getOkReaderBindReportMessage()

.matches(message) != null) {// got the OK for the reader.bind.// The transport is officially up.setState(TransportService.STARTED);

}}

8. Create the listener that the AlternateChannelMessageHandler willnotify when input is available:

protected AlternateChannelMessageListener createAlternateChannelMessageListener() {return new AlternateChannelMessageListener() {

public ConnectionService getDefaultAlternateConnection() {return SiritTransport.this.getDefaultAlternateConnection();

}public int processAlternateInput(byte[] bytes, int length)

throws Exception {return

SiritTransport.this.parser.parseMessages(bytes,length,false);

}public boolean isProcessing() {

return SiritTransport.this.isRunning()&& SiritTransport.this.getState()

>= TransportService.CONNECTED;}public void connectionFailed() {

SiritTransport.this.restart();}

};}

The processAlternateInput(byte[], int) method just delegatesto our parser to create the messages from the input. The falseargument indicates the message is not a response message.

9. Create the ConnectionService to be used by theAlternateChannelMessageHandler:

public ConnectionService getDefaultAlternateConnection() {return

new TcpipConnection(getString("sirittransport.host",SiritTransportService.DEFAULT_HOST),

getEventport(),getInt("sirittransport.localport",

SiritTransportService.DEFAULT_LOCALPORT),getInt("sirittransport.readtimeout",

SiritTransportService.DEFAULT_READTIMEOUT),getInt("sirittransport.readsize",

SiritTransportService.DEFAULT_READSIZE),getInt("sirittransport.writesize",

SiritTransportService.DEFAULT_WRITESIZE),getInt("sirittransport.linger",

SiritTransportService.DEFAULT_LINGER));}

developerWorks® ibm.com/developerWorks

Building the transport componentPage 24 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 25: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

The connection is modeled after the transport's TCP/IP connection, butuses the event channel port.

Test event handling

To finish testing your transport, add messages to the transport test CML to registerfor and generate events:

<send id="RegisterEvent"><message id="ReaderRegisterEventMessage">

<ascii>reader.register_event(name=event.debug.trace.iop)\r\n</ascii></message><message id="ReaderRegisterEventDioMessage">

<ascii>reader.register_event(name=event.dio.all)\r\n</ascii></message>

</send><send id="Dio">

<message id="DioOutput1ReadMessage"><ascii>dio.out.1\r\n</ascii>

</message><message id="DioOutput1OnMessage">

<ascii>dio.out.1 = 1\r\n</ascii></message><message idref="DioOutput1ReadMessage"></message><message id="DioOutput1OffMessage">

<ascii>dio.out.1 = 0\r\n</ascii></message><message id="DioInput1ReadMessage">

<ascii>dio.in.1\r\n</ascii></message><message id="DioInput1OnMessage">

<ascii>dio.in.1 = 0\r\n</ascii></message><message id="DioInput1OffMessage">

<ascii>dio.in.1 = 1\r\n</ascii></message>

</send>

Regenerate the transport test and run it. You should see event.dio.all eventmessages.

Implement field access in the custom message class

The device component we'll implement in the next article in this series will requireaccess to message fields by key. For this example, note that responses for thereader commands and events in which we are interested are generally of threetypes: ok value\r\n\r\n or ok name = value\r\n\r\n or event.namename1 = value1, name2 = value2\r\n\r\n. The device component willrequire two types of fields:

1. The part of the response up to the first blank (key "0") and everything else(key "1") for the first kind of message.

2. Keys based on the name part of the key/value pairs for the second andthird kinds of messages.

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 25 of 29

Page 26: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Your custom message should reimplement the get(Object key) method toprovide such access. The method returns the field value associated with the key.There are many ways to implement field parsing. We recommend the following:

1. Parse the "0" and "1" fields "on demand". In your device implementation,you'll probably never access either field more than once.

2. Parse all key/value pairs and save them as a Map, but only if a named keyis asked for. That way, for many messages, you'll never parse anything,and if you do, the parsing will only be done once to build all key/valuepairs.

3. Although get(Object) can return any Object, for a text-orientedprotocol like that of the Sirit INfinity 510 it makes the most sense to returnfields as instances of String. Keys should be instances of String.

4. Be careful when parsing that you don't include the leading or trailingblanks in the value, or the trailing comma.

5. Return null for undefined keys.

A suitable implementation for the custom message class is included in thetransport_projects.zip file in the Downloads section.

Summary

In this article we took a closer look at the transport component of a Device Kitadapter. We discussed the responsibilities of a transport and implementationconsiderations, and showed you how to create a transport for a Sirit INfinity 510RFID reader. In the next article in this series, we'll model the device component.

developerWorks® ibm.com/developerWorks

Building the transport componentPage 26 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 27: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Downloads

Description Name Size Download method

Helper classes for transports transport_helpers_project.zip8KB HTTP

Completed sample transport transport_projects.zip34KB HTTP

Information about download methods

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 27 of 29

Page 28: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

Resources

Learn

• Developing a device adapter and agent for the WebSphere RFID solution, Part1: Introduction to the WebSphere RFID Device Kit (developerWorks, 2007):Describes the functions provided by the WebSphere RFID Device Infrastructurecomponent and how to construct device adapters using the WebSphere RFIDDevice Infrastructure Device Development Kit.

• Websphere RFID Premises Server product overview: A brief overview of theWebsphere RFID solution.

• WebSphere RFID Information Center: Product documentation for theWebsphere RFID solution.

• Websphere Studio Device Developer help has information for all the RFIDTRacking Kit components (after you install the RFID Tracking Kit feature)

• The Sirit INfinity 510 Protocol Reference Guide v1.0 will soon be available athttp://www.sirit.com

• Print simple and complex RFID labels with the WebSphere RFID solution(developerWorks, Nov 2006): A guide to printing RFID labels with theWebsphere RFID solution.

• Redbook: IBM WebSphere RFID Handbook: A Solution Guide

• developerWorks Wireless with WebSphere zone

Get products and technologies

• Download a trial version of WebSphere Studio Device Developer

• Install the RFID Tracking Kit into Device Developer using the Update Managerand defining a site bookmark tohttp://www-306.ibm.com/software/pervasive/wsdd/updates/571/rfid

About the authors

Karl FreburgerKarl Freburger is an IT Architect with IBM Global Business Services. He works withIBM's Software Group to enable business partners to design solutions that use IBM'sRFID components.

Allen SmithAllen Smith is a Senior Software Engineer with the Pervasive Computing Group inResearch Triangle Park, North Carolina. He works with business partners to design

developerWorks® ibm.com/developerWorks

Building the transport componentPage 28 of 29 © Copyright IBM Corporation 1994, 2006. All rights reserved.

Page 29: Developing a device adapter and agent for the WebSphere ...€¦ · As described in Part 1, we use the Device Kit component of the WebSphere RFID Device Infrastructure to implement

solutions that use IBM's pervasive middleware. You can contact Allen [email protected].

ibm.com/developerWorks developerWorks®

Building the transport component© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 29 of 29


Recommended