Skip to main content

skip to main content

developerWorks  >  WebSphere  >

Developing a device adapter and agent for the WebSphere RFID solution, Part 4: Building the reader agent

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


My developerWorks needs you!

Connect to your technical community


Rate this page

Help us improve this content


Level: Intermediate

Allen Smith (allens@us.ibm.com ), Senior Software Engineer, IBM, Intel, Microsoft,HP
Karl Freburger (karlf@us.ibm.com), IT Architect, IBM, Intel, Microsoft,HP

14 Feb 2007

In Part 4 of this series, you'll learn how to create a new reader agent to read RFID tags using a Sirit™ INfinity 510 RFID reader.

Introduction

This article continues our series on how to build adapters and agents to integrate RFID readers into the IBM Websphere RFID solution. Part 1 described the overall solution and the WebSphere RFID Device Infrastructure. Part 2 showed you how to implement the transport layer. Part 3 showed you how to build the device layer. In this article, you'll learn how to implement the reader agent. A reader agent interacts with the Device Kit components to control a reader, as shown in Figure 1. Once again, we'll use the Sirit INfinity 510 reader as an example.


Figure 1. Agent and Device Kit adapter
Agent and Device Kit adapter


Back to top


Agents

As described in Part 1, the Websphere RFID Device Infrastructure runtime (called an edge) includes a number of Device Kit device adapters, built by IBM, that support readers and printers from leading RFID vendors, as shown in Figure 2. These adapters provide the necessary functions for communicating with and executing commands on the hardware device. Each adapter has an associated agent that contains logic specific to the WebSphere RFID solution usage scenarios. The runtime includes a number of other agents that perform various functions required by the WebSphere RFID solution usage scenarios. These functions range from filtering and aggregating tag reads to controlling I/O devices, such as light trees and motion sensors, to configuring other agents.


Figure 2. Websphere RFID Device Infrastructure runtime
Websphere RFID Device Infrastructure runtime

The Device Infrastructure runtime includes a publication and subscription engine (the MicroBroker). Agents communicate with one another via messages that flow through the MicroBroker. An agent publishes messages to and subscribes to specific topics relevant to its functionality. The topics and messages define the access to an agent.

All agents are instances of subclasses of com.ibm.witt.robe.agentmanager.AbstractAgent. Agents are packaged as OSGi bundles that run on the IBM Service Management Framework (SMF). An agent bundle provides an OSGi managed service factory that is responsible for creating and configuring agents of a particular kind, under the control of the edge configuration service. Briefly, the edge configuration service obtains from a WebSphere RFID Premises server an XML file describing the configuration of agents on an edge and asks the agent managed service factories to create (or configure) agents, usually when the edge is started.

The agents delivered with Websphere RFID Device Infrastructure are examples that implement a dock door receiving usage scenario. In that scenario, a portal has one or more readers, controlled by a portal switch and a motion detector. When the switch is pressed and the motion detector is triggered, the reader starts reading tags. Some kinds of tags (for example, pallet tags) are reported to the Premises server as they're read; other kinds of tags (for example, case tags) are reported at the end of the read cycle. A light tree is lit in various colors to indicate the status of tag reads. Each of the portal components (switch, motion detector, light tree, reader) is controlled by an agent. Some of the agents are logical agents (such as the switch and motion detector agents) in the sense that they do not control actual hardware, but translate messages from hardware agents (such as "input pin 0 on reader 1 is high") into scenario terms (such as "portal switch is pressed"). Those logical messages are used by other agents to control the scenario ("start reading tags"). To use a new kind of reader in the scenario you need to implement a new reader agent. All the other agents in the scenario remain unchanged.



Back to top


Reader agents

A reader agent is a RFID Device Infrastructure agent that implements an interface to a RFID reader. The agent is responsible for controlling the reader (start and stop tag reading), handling reader I/O events (input switches, output lights, and so on), filtering duplicate tags, and producing tag aggregation reports. A reader agent listens and publishes to a standard set of topics using a standard set of messages, so all reader agents (regardless of the actual type of reader attached) are interacted with in the same way.

To accomplish its tasks, a reader agent collaborates with a number of other objects, as shown in Figure 3:

  • The reader agent is an instance of a subclass of com.ibm.kimono.abstractreaderagent.AbstractReaderAgent. Reader agents inherit almost all of their behavior from the abstract class. A reader agent creates a corresponding reader model. A reader agent is created by a reader agent factory.
  • The reader model (an instance of a subtype of com.ibm.esc.device.service.DeviceService.IRfidReader) is responsible for implementing an interface to a specific type of reader via a Device Kit adapter. Most of the work of implementing a reader agent is done in this class.
  • The reader agent constants interface defines static fields that are used when creating and configuring reader agents.
  • The reader agent factory (an instance of a subclass of com.ibm.witt.robe.agentmanager.bundle.AbstractAgentManagedServiceFactoryActivator) is an OSGi managed service factory responsible for creating and configuring a reader agent. It does that by delegating behavior to the reader agent creation advisor and reader agent configuration advisor.
  • The reader agent creation advisor (an instance of a subclass of com.ibm.kimono.abstractreaderagent.bundle.AbstractReaderAgentFactoryCreationAdvisor) is responsible for creating a reader agent.
  • The reader agent configuration advisor (an instance of a subclass of com.ibm.kimono.abstractreaderagent.bundle.AbstractReaderAgentFactoryConfigurationAdvisor) provides configuration information to the reader agent factory for use when creating an agent.

Figure 3. Reader agent collaborators
Reader agent collaborators

The reader agent and reader model divide the work of interfacing to a reader: the reader agent handles the RFID Device Infrastructure-specific behavior (such as publishing messages), and the reader model handles the Device Kit-specific behavior (such as using device controls to start and stop tag reading).

A reader agent class implements very little by itself. All of the work of interfacing with the RFID Device Infrastructure is done in its superclasses. That work includes:

  • Subscribing to the appropriate topics on the MicroBroker.
  • Interpreting control messages and translating them into actions on the reader model.
  • Publishing messages to the appropriate topics.

The topic names to be used for publish/subscribe actions are based on the reader name. The actual topic names are unimportant; to implement a new reader agent you don't have to implement any message handling.

The reader model implements all the interaction with a Device Kit adapter. That interaction is done using device controls; the commands, signals, and measurements described in Part 3. The reader model is where you will do most of the coding to enable a new reader. The reader model is responsible for:

  • Starting and stopping tag reading.
  • Changing the state of output pins (if the reader has I/O).
  • Reporting state changes on input pins (if the reader has I/O).
  • Configuring the reader based on attributes received from a configuration service.
  • Reporting when the reader starts up and stops.

Reader models are always implemented as subclasses of com.ibm.kimono.abstractreader.AbstractRfidReader, because that class handles:

  • Connecting to the appropriate Device Kit adapter.
  • Filtering duplicate tags during a read cycle (if required).
  • Aggregating tags during a read cycle (if required).

The reader agent factory and the reader agent creation and configuration advisors cooperate to implement the OSGi managed service factory required by the edge configuration service.



Back to top


Implementing a reader agent

When you implement a new reader agent, you'll need to implement its collaborators. The following sections describe the key methods for each class.

Reader agent

Reader agents are always subclasses of com.ibm.kimono.abstractreaderagent.AbstractReaderAgent to inherit all the default behavior necessary to interact with the RFID Device Infrastructure. The only methods that need to be implemented for a new reader agent are:

  • The constructor that takes a Dictionary as an argument.
  • IRfidReader createModel(Dictionary), which creates and returns an instance of the reader model.

Reader model

As mentioned, the reader model is where you do most of the work to enable a new reader. Reader models are always subclasses of com.ibm.kimono.abstractreader.AbstractRfidReader to inherit the default tag filtering and aggregation behaviors. When creating a new reader model, you'll need to implement these methods:

  • void bind(DeviceService, int[],boolean[]) is called when the reader model is starting and provides a convenient place to get all the device controls the reader model will need to use and to register appropriate listeners with them. You must invoke the superclass implementation of the method.
  • void unbind() is called when the reader model is stopping and provides a convenient place to unregister any listeners on the device. You must invoke the superclass implementation of the method.
  • void readerCameUp() is called when the reader device is started. It is a convenient place to ensure that the reader is initialized to a known state (tag reading off and I/O output pins set to particular values) and to register for I/O events (if the reader supports I/O). It's also a good place to invoke the notifyHealthy() method to tell other agents that the reader agent and reader model are operational.
  • void readerWentDown() is called when the reader device is stopped. It is a convenient place to ensure that any tag reading cycle is stopped, to unregister for I/O events, and to invoke the notifyUnhealthy() method to tell other agents that the reader agent and reader model are not operating.
  • public void signalOccurred(SignalService, Object, Object) is a convenient place to handle signals generated by signal device controls the reader model might use to be notified of tag reads, input state changes, and so on. You may not do anything in the method if you don't use any signal controls, but this is highly unlikely.

To implement RFID tag reading, you'll need to implement the following: methods:

  • public void autonomousModeOn() is called when the reader should start reading tags. For those readers that have a "start reading until told to stop" mode, this method just adds itself as a listener for the tag report signals and sends the command to start reading. For readers that only read for a set period of time before stopping, you'll have to set up a separate Thread to continually restart reading tags when a read command ends.
  • public void autonomousModeOff() is called when the reader should stop reading tags. The method should remove the reader model as a listener on tag report signal controls and stop any polling Thread the reader model may have started.

If the reader supports I/O (usually by I/O pins), you may want to handle I/O events to allow the input switches and light tree to be attached to the reader. If so, you'll need to implement the following methods:

  • public void setOutputPin(int, boolean) is called when the reader should set a particular output pin to a specific state.
  • public void turnOffAllOutputs() should turn off all the output pins.
  • public void turnOnAllOutputs() should turn on all the output pins.
  • You'll also need to set up monitoring of the input pins on the reader. Some readers have an event-driven notification of input pins (use the signal or measurement controls to implement), while others require periodic polling of the pin states (you'll have to set up a separate Thread to do the polling). In either case, when an input pin changes state, you'll need to invoke the notifyPinChanged() method to get the new pin state published to the other agents.

If you decide not to implement I/O for the reader you can use the default implementations of these methods.

Reader agent factory

Reader agent factories are always subclasses of com.ibm.witt.robe.agentmanager.bundle.AbstractAgentManagedServiceFactoryActivator to inherit the implementation of the interaction with the OSGi framework. When creating a new reader agent, you'll only need to implement the methods that create the reader agent creation advisor and reader agent configuration advisor:

  • IManagedServiceFactoryAdvisor createAdvisor() creates and returns the reader agent creation advisor.
  • FactoryConfigurationAdvisor createConfigurationAdvisor() creates and returns the reader agent configuration advisor.

Reader agent creation advisor

A reader agent creation advisor is used by the reader agent factory to create an instance of the reader agent class, and to provide the name of the Device Kit device service to which the reader model will be connected. Reader agent creation advisors are always subclasses of com.ibm.kimono.abstractreaderagent.bundle.AbstractReaderAgentFactoryCreationAdvisor. The only methods you'll have to implement for a new reader are:

  • String getDeviceServiceName() returns the Device Kit device service name (defined in the Device Kit device component) to be used. That service name is defined as the static field SERVICE_NAME of the device service interface.
  • AbstractReaderAgent createReaderAgent(Dictionary) creates and returns an instance of the reader agent class using the constructor with a Dictionary argument.

Reader agent configuration advisor

A reader agent configuration advisor is used by the reader agent factory and OSGi configuration service to tie together OSGi-managed configuration information and configuration attributes provided by a Premises server. Reader agent configuration advisors are always subclasses of com.ibm.kimono.abstractreaderagent.bundle.AbstractReaderAgentFactoryConfigurationAdvisor. The only methods you'll have to implement for a new reader are:

  • String getDeviceFactoryPid() returns the factory service name defined by the Device Kit device component. It is defined as the static field FACTORY_SERVICE_NAME on the device service interface.
  • String getTransportFactoryPid() returns the factory service name defined by the Device Kit transport component. It is defined as the static field FACTORY_SERVICE_NAME on the transport service interface.
  • String getAgentType() returns the reader agent's property set name. The property set name is used in the edge XML configuration file to identify which properties belong to a specific reader agent. It is defined as a static field on the reader constants interface.
  • String getFactoryPid() returns the reader agent factory class name.
  • void handleReaderSpecificProperties(Properties) converts properties as defined in the edge XML configuration into the form required to set device component properties. For example, it may convert the String form of an XML property into the byte[] form required by the device component. This method does not always have to be implemented.

Reader agent constants interface

A reader agent constants interface is simply a Java™ interface that defines a static field used by the reader agent configuration advisor's getAgentType() method:

public static final String DeviceMakerName_READER_AGENT_PROPERTY_SET_NAME defines the name of the reader agent's property set.



Back to top


Building a reader agent for the Sirit INFinity 510 reader

In this part of the article, we'll create a reader agent for the Sirit INfinity 510 RFID reader that you can plug into the WebSphere RFID Solution. You'll build the reader agent in two phases. First you'll build a skeleton reader agent that you can install and start in a Websphere RFID Device Infrastructure edge runtime. Once you get the skeleton reader agent working, you'll add functionality to it to control the tag reading process.

Required materials

You'll need the following items to complete this exercise:

  1. WebSphere Studio Device Developer Version 5.1.7 installed with the WebSphere RFID Tracking Kit Version 1.1.1
  2. Sirit INfinity 510 reader
  3. The SiritTransport project you created in Part 2.
  4. The SiritDevice project created in Part 3.
  5. The SiritReaderDevelopment project, provided in the Downloads section of this article.
  6. The completed code example, provided in the Downloads section.


Back to top


Building the skeleton reader agent

In this section we'll go through the steps to build the skeleton reader agent.

Create the Java project

The first step when implementing a new reader agent is to create a Java project in WebSphere Studio Device Developer (Device Developer) to hold the agent code. To create a Java project:

  1. Select File => New => Project.
  2. Select Java and Java Project in the New Project window, then click Next.
  3. Specify SiritReaderAgent as the Project name, and click Next.
  4. Add a source folder called SiritReaderAgent. This folder that will contain the bundle source code for the agent. To create the source folder, do the following as shown in Figure 4:
    1. Click Add Folder.
    2. Make sure the SiritReaderAgent project is selected and click Create New Folder.
    3. Specify SiritReaderAgent as the Folder name.

      Figure 4. Create a source folder
      Create a source folder

    4. Click OK in the New Folder window.
    5. Click OK on the Source Folder Selection window.
    6. Click Yes when prompted whether you want to remove the project as a source folder.
  5. Reader agents require the RM Java Runtime Environment (JRE) system library. For most Device Developer installations, this is not the default JRE. To change the JRE used for the SiritReaderAgent project:
    1. Click the Libraries tab.
    2. Select JRE System Library [ive-2.2] and click Remove.
    3. Now that you've removed the reference to the default JRE system library from the project, you'll need to add the RM JRE. To add a new JRE system library, click Add Library.
    4. Select JRE System Library and click Next.
    5. Select RM from the JRE list, as shown in Figure 5, and click Finish.

      Figure 5. Add a new JRE
      Add a new JRE

    6. Your project should now have JRE System Library [RM] in the build path as shown in Figure 6.
  6. Now you need to add some Device Developer projects to the Java build path. Click the Projects tab and select the following projects:
    • KimonoAbstractReaderAgent
    • RobeAbstractAgentManager
    • RobeCore
    • RobeEdgeConfiguration
    • SiritDevice (created in Part 3)
    • SiritTransport (created in Part 2)
  7. Click the Order and Export tab to see the build path for your project. You can order the entries in the build path using the Up and Down buttons. A best practice is to organize your build path in the following order:
    • JRE System Library
    • External libraries
    • Projects
    • Source folders.
    Using this order makes it easy to see your dependencies at a glance. After re-organizing your imports, the build path should look like that in Figure 6.

    Figure 6. Build class path order
    Build class path order

  8. Click Finish to create the SiritReaderAgent project.

Create the SiritReader class

Now that you've created the Java project to hold your reader agent code, it's time to create the reader model class. You'll add the class to your project's source folder. To create the reader model class:

  1. Expand the SiritReaderAgent project and right-click SiritReaderAgent, then select New => Class.
  2. Specify the following values in the New Java Class window, as shown in Figure 7:
    • Package: devworks.example.sirit.reader
    • Name: SiritReader
    • Superclass: AbstractRfidReader. (Click Browse and begin typing in the superclass name. Select AbstractRfidReader from the Matching types list.)
    • Check Constructors from superclass.
    • Check Inherited abstract methods.
    • Uncheck public static void main(String[], args).
    • Accept the remaining default values and click Finish to create the reader SiritReader class.

      Figure 7. Create the reader model class
      Create the reader model class

You'll notice that your class has several errors in it. One of the features of the Device Developer Java integrated development environment (IDE) is that you can hover over an error icon to find out what the error is. If you place the cursor over the first and second error icons (as shown in Figure 8), the Java editor displays text telling you that:

  • The SiritReader class indirectly references the missing type com.ibm.esc.device.service.DeviceListener.
  • The import com.ibm.esc cannot be resolved.

    Figure 8. Error messages
    Error messages

Tip: The light bulb icon displayed in the Java editor is called a Quick Fix icon. If you click on the icon, you'll see a pop-up with one or more possible fixes that can be automatically applied.

All the errors are caused by references to classes that are not in the SiritReaderAgent project's Java build path. To update the build path and correct the errors, do the following:

  1. Right-click SiritReaderAgent, and select Properties.
  2. Click the Libraries tab.
  3. Click Add Variable.
  4. Select DEVICEKIT and click Extend, as shown in Figure 9. A variable points to a folder containing one or more JAR files. The extend function allows you to select one or more JAR files from the variable folder. The DEVICEKIT variable was defined when you loaded the WebSphere RFID Device Infrastructure feature into Device Developer.

    Figure 9. Add a variable to the build path
    Add a variable to the build path

  5. Expand the bundlefiles folder in the Variable Extension window and select the following JAR files:
    • Core.jar
    • DeviceKit.jar
    • Message.jar
    • TransportKit.jar
  6. Click OK to add the JAR files to the build path.
  7. Repeat the above process for the following variables and JAR files. Note that all JAR files are located in the bundlefiles folder in the variable's directory.
    • RFID_HOME/Rfid.jar
    • MBAF_HOME/MBAF.jar
    • MICRO_BROKER_HOME/wmqtt.jar
    • OAF_HOME/OAF_Base.jar
  8. Order your build path so that it resembles Figure 10.
  9. Click OK to update the build path.

    Figure 10. Java build path
    Java build path

For now, our goal is to create a skeleton agent that you can installed into and start in a Device Infrastructure edge runtime, so there's no need to add any code to the methods of the reader model class. You'll implement the methods described in Reader model later to create a functioning reader agent.

Create the SiritReaderAgent class

To create the reader agent class:

  1. Expand the SiritReaderAgent project, right-click SiritReaderAgent, and select New => Class.
  2. Specify the following values in the New Java Class window:
    • Package: devworks.example.sirit.reader.agent
    • Name: SiritReaderAgent
    • Superclass: AbstractReaderAgent
    • Check Constructors from superclass .
    • Check Inherited abstract methods.
    • Click Finish to create the class.

In order to test that your reader agent can start successfully when the edge runtime starts, you'll need to implement the methods described in Reader agents.

After adding the code to the createModel(Dictionary) method to return an instance of the class SiritReader, you'll notice that your method now has an error. The error is caused by a missing import statement for the SiritReader class. To automatically add the necessary import statements, select Source => Organize Imports from the menu.

The updated createModel(Dictionary) method should be:

protected IRfidReader createModel(Dictionary properties) {
      return new SiritReader(properties);
}

Create the SiritReaderAgentConstants Interface

Create the reader agent constants interface to hold the one constant required by the reader agent configuration advisor. To create the interface:

  1. Expand SiritReaderAgent, right-click SiritReaderAgent, and select New => Interface.
  2. Specify the following values in the New Java Interface window:
    • Package: devworks.example.sirit.reader.agent.constants
    • Name: SiritReaderAgentConstants
    • Click Finish to create the interface.

You'll need to update the interface to include a field definition for the reader agent's property set name (see Reader agent constants interface). The field's value should be "SiritReaderAgent". The property set field definition for the SiritReaderAgent is:

public static final String SIRIT_READER_AGENT_PROPERTY_SET_NAME = "SiritReaderAgent";

Create the SiritReaderAgentFactoryCreationAdvisor class

Create the reader agent creation advisor by doing the following:

  1. Expand SiritReaderAgent, right-click SiritReaderAgent, and select New => Class.
  2. Specify the following values in the New Java Class window:
    • Package: devworks.example.sirit.reader.agent.factory
    • Name: SiritReaderAgentCreationAdvisor
    • Superclass: AbstractReaderAgentFactoryCreationAdvisor
    • Check Constructors from superclass.
    • Check Inherited abstract methods.
    • Click Finish to create the class.

In order to test that your reader agent can start successfully when the edge runtime starts, you'll need to implement the methods described in Reader agent creation advisor. The methods are shown in Listing 1. After writing the methods, don't forget to update your imports to fix the errors.


Listing 1. Reader agent creation advisor methods

public String getDeviceServiceName() {
      return SiritDeviceService.SERVICE_NAME;
}

public AbstractReaderAgent createReaderAgent(Dictionary properties) {
      return new SiritReaderAgent(properties);
}

Create the SiritReaderAgentConfigurationAdvisor class

Create the reader agent configuration advisor by doing the following:

  1. Expand SiritReaderAgent, right-click SiritReaderAgent, and select New => Class .
  2. Specify the following values in the New Java Class window:
    • Package: devworks.example.sirit.reader.agent.factory
    • Name: SiritReaderAgentConfigurationAdvisor
    • Superclass: AbstractReaderAgentFactoryConfigurationAdvisor
    • Check Constructors from superclass.
    • Check Inherited abstract methods.
    • Click Finish to create the class.

In order to test that your reader agent can start successfully when the edge runtime starts, you'll need to implement the methods as described in Reader agent configuration advisor. The implemented methods are shown in Listing 2. Update your imports after writing the methods.


Listing 2. Reader agent configuration advisor methods

public String getDeviceFactoryPid() {
      return SiritDeviceService.FACTORY_SERVICE_NAME;
}

public String getTransportFactoryPid() {
      return SiritTransportService.FACTORY_SERVICE_NAME;
}

public String getAgentType() {
      return SiritReaderAgentConstants.SIRIT_READER_AGENT_PROPERTY_SET_NAME;
}

public String getFactoryPid() {
      return SiritReaderAgentFactory.class.getName();
}

Create the SiritReaderAgentFactory class

Create the reader agent factory by doing the following:

  1. Expand SiritReaderAgent, right-click SiritReaderAgent, and select New => Class.
  2. Specify the following values in the New Java Class window:
    • Package: devworks.example.sirit.reader.agent.factory
    • Name: SiritReaderAgentFactory
    • Superclass: AbstractAgentManagedServiceFactoryActivator
    • Check Constructors from superclass.
    • Check Inherited abstract methods .
    • Click Finish to create the class.

In order to test that your reader agent can start successfully when the edge runtime starts, you'll need to implement the methods as described in Reader agent factory. The methods are shown in Listing 3.


Listing 3. Reader agent factory methods

protected FactoryConfigurationAdvisor createConfigurationAdvisor() {
      return new SiritReaderAgentConfigurationAdvisor();
}

protected IManagedServiceFactoryAdvisor createAdvisor() {
      return new SiritReaderAgentCreationAdvisor();
}

Create the reader agent bundle

Before you can test your reader agent in a RFID Device Infrastructure edge runtime, you'll have to package your reader agent classes in a SMF bundle. To create the bundle:

  1. Expand SiritReaderAgent, right-click SiritReaderAgent, then select New => Other.
  2. Select SMF and Bundle Folder in the New window as shown in Figure 11.

    Figure 11. Create a bundle folder
    Create a bundle folder

  3. Click Next.
  4. Make sure the SiritReaderAgent source folder in the SiritReaderAgent project is selected, and uncheck the options to create the IVEATTRS.XML and IVERES.XML files, as shown in Figure 12:

    Figure 12. Select the source folder to convert to a bundle folder
    Select the source folder to convert to a bundle folder

  5. Click Finish to create the bundle folder.

The SMF New Bundle Folder wizard adds a META-INF folder containing the bundle manifest to the SiritReaderAgent source folder. You'll notice that the MANIFEST.MF file has a warning icon displayed next to it. To get rid of these warnings, you'll need to update the manifest to:

  • Import the packages required by your bundle.
  • Import the services required by your bundle.
  • Export bundle packages for use by other bundles.
  • Export the bundle services for use by other bundles.

To update the manifest, double-click on the MANIFEST.MF file to open the Bundle Manifest editor, and do the following:

  1. Change the Bundle-Version to 1.1.1
  2. Ensure that the Bundle-Activator is devworks.example.sirit.reader.agent.factory.SiritReaderAgentFactory
  3. Expand Import Packages and click Compute. The packages shown in Figure 13 should now be specified to be imported.

    Figure 13. Bundle package imports
    Bundle package imports

  4. Expand Import Services and click Add. Select the following services:
    • devworks.example.sirit.device.service.SiritDeviceService
    • com.ibm.witt.robe.edge.configuratio.service.EdgeConfigurationService
  5. Click OK.
  6. Expand Export Packages and click Add. Select the following packages:
    • devworks.example.sirit.reader.sirit.reader
    • devworks.example.sirit.reader.sirit.reader.agent
    • devworks.example.sirit.reader.sirit.reader.agent.constants
    • devworks.example.sirit.reader.sirit.reader.agent.factory
  7. Click OK.
  8. Expand Export Services and click Add. Select the following services:
    • com.ibm.witt.robe.agentmanager.IAgent
    • org.osgi.service.cm.ManagedServiceFactory
  9. Click OK to export the services.
  10. Close the Bundle Manifest editor.
  11. Click Yes when prompted to save the changes.

Add the METADATA.XML file

To avoid getting a runtime warning message that the META-INF/METADATA.XML resource cannot be found, you'll need to add a METADATA.XML file to the SiritReaderAgent bundle. A sample METADATA.XML file has been provided for you in the SiritReaderDevelopment project (see Downloads). Copy this file and the METADATA_en.properties file to the META-INF folder in the SiritReaderAgent project.

Test the reader agent

The Device Infrastructure RFID Tracking Kit provides a number of simulators you can use for development and testing. The simulators can take the place of the various hardware and software components used in the supported WebSphere RFID usage scenarios. You'll use the Premises Server simulator and an I/O simulator to test your reader agent. For more information on the simulators, refer to the Edge Hardware Simulation document in the TogaKimonoPremisesSimulator project.

The I/O Simulator uses the Embedded Standard Widget Toolkit (eSWT) for its user interface controls. To run an eSWT application, you must have the eSWT dynamic link library (swt-win32-3049.dll ) in your library path. This file is located in the WSDD_HOME\wsdd5.0\technologies\eswe\files\eswt\win32 directory. Copy the file to the C:\Windows\system32 directory.

The SiritReaderDevelopment project contains a loader bundle that loads the Premises Server simulator, the I/O simulator, the SiritReaderAgent, and other required agents and bundles into an SMF runtime. You'll need to import the project into your Device Developer workspace in order to test your reader agent.

Once you've imported the SiritReaderDevelopment project into your workspace, you'll need to create and start an SMF runtime and an SMF bundle server. You'll publish your reader agent bundle to the SMF bundle server where it will be available to install into an SMF runtime.

To create and start an SMF runtime:

  1. Select Run => Run.
  2. Select SMF Runtime.
  3. Click New.
  4. Switch to the Arguments tab, and add the following VM argument: -Dpremises.ip=127.0.0.1 -Dedge.id=E1
  5. Select Workspace for the working directory and specify TogaDevelopment as the workspace project.
  6. Accept all other runtime defaults.
  7. Click Apply.
  8. Click Run to start the SMF runtime.

To create and start an SMF bundle server:

  1. Select Run => Run.
  2. Select SMF Bundle Server.
  3. Click New.
  4. Accept all default options.
  5. Click Run to start the SMF bundle server.

Edit the edge-configuration-E1.xml file in the SiritReaderDevelopment project and update the value of the transport.host property with the IP address of your reader. Copy the edge-configuration-E1.xml file to the configurations folder in the TogaDevelopment project. You may want to rename the existing edge-configuration-E1.xml file before copying.

To test whether your SiritReaderAgent will install and start correctly:

  1. Submit the bundles in the following projects to the bundle server: SiritCliDevice, SiritCliTransport, SiritReaderAgentDevelopment, and SiritReaderAgent. To submit the bundles to the bundle server, select the projects and right-click, then select SMF => Submit Bundle.
  2. Install the DEVWORKS_EXAMPLE_SIRIT_DEMO_LOADER bundle into the SMF runtime. To install the loader bundle:
    1. Switch to the SMF Bundle Servers view.
    2. Expand Admin@localhost:8080/smf
    3. Expand Bundles.
    4. Right-click DEVWORKS_EXAMPLE_SIRIT_DEMO_LOADER, and select Install.

You should see the following messages written to the console when the SiritReaderAgent bundle starts and becomes operational:

MicroBroker Client connected: SiritReader-P1, Connection: LocalAdapter
MicroBroker Client 'SiritReader-P1' registered a durable subscription.

Kill the SMF runtime when you're done.



Back to top


Completing the reader model

In Part 3, we modeled the tag report event and the commands to set the operating mode of the reader, to register and unregister for tag read events, and to set the tag reporting fields. We added code to the device test application to use the controls generated from those definitions to tell the reader to start and stop reading and to receive tag read events. We'll use the same approach in this exercise, except that we'll add the code to the reader model as opposed to the device test application. We'll implement the methods as described in Reader model.

Follow these steps to update the SiritReader class to process tag reads:

  1. Add the following field definitions for the device controls and constant values required by the reader model:
    private static final String AUTONOMOUS = "autonomous";
    private static final String STANDBY = "standby";
    private static final String ANTENNA = "antenna";
    private static final String TAG_ID = "tag_id";
    private static final String TAG_REPORT_FIELDS = TAG_ID + " " + ANTENNA;
    private SignalService eventTagReportReportSignal;
    private CommandService eventTagReportRegisterRequestCommand;
    private CommandService eventTagReportUnregisterRequestCommand;
    private MeasurementService tagReportingReportFieldsMeasurement;
    private MeasurementService setupOperatingModeMeasurement;
    

  2. Add a method called getDeviceControls() that gets the device controls required by the reader model:
    public void getDeviceControls() {
          eventTagReportReportSignal = readerDevice.getSignal
    	                           (SiritDeviceService.EventTagReportReport);
    
          tagReportingReportFieldsMeasurement = readerDevice.getMeasurement
    	                           (SiritDeviceService.TagReportingReportFields);
    
          eventTagReportRegisterRequestCommand = readerDevice.getCommand
    	                          (SiritDeviceService.EventTagReportRegisterRequest);
    
          eventTagReportUnregisterRequestCommand = readerDevice.getCommand
                                  (SiritDeviceService.EventTagReportUnregisterRequest);
    
          setupOperatingModeMeasurement = readerDevice.getMeasurement
    	                          (SiritDeviceService.SetupOperatingMode);
    }
    

  3. Override the bind(DeviceService, int[], boolean[]) method:
    public void bind(final DeviceService readerDevice, final int[] pins,
                     final boolean[] states) {
          super.bind(readerDevice, pins, states);
          getDeviceControls();
    }
    

  4. Override the unbind() method:
    public void unbind() {
          autonomousModeOff();
          eventTagReportReportSignal = null;
          eventTagReportRegisterRequestCommand = null;
          eventTagReportUnregisterRequestCommand = null;
          setupOperatingModeMeasurement = null;
          super.unbind();
    }
    

  5. Update the readerCameUp() method to indicate that the reader is healthy and ensure the reader is not reading tags:
    protected void readerCameUp() {
          autonomousModeOff();
          notifyHealthy();
    }
    

  6. Update the readerWentDown() method to indicate that the reader is unhealthy and to ensure the reader is not reading tags:
    protected void readerWentDown() {
          autonomousModeOff();
          notifyUnhealthy();
    }
    

  7. Update the autonomousOn() method to start the read process. For the Sirit reader this method should:
    • Set the tag.reporting.report_fields variable to "tag_id antenna".
    • Add the reader model as a listener to the event.tag.report event signal.
    • Register interest in the event.tag.report event.
    • Set the setup.operating_mode variable to autonomous.
    Do these operations using the device controls we created in Part 3.
    public void autonomousModeOn() {
          tagReportingReportFieldsMeasurement.executeWrite(TAG_REPORT_FIELDS);
          eventTagReportReportSignal.addSignalListener(this);
          eventTagReportRegisterRequestCommand.execute();
          setupOperatingModeMeasurement.executeWrite(AUTONOMOUS);
    }
    

  8. Update the autonomousOff() method to stop the read process. For the Sirit reader this method should:
    • Set the setup.operating_mode variable to standby.
    • Unregister interest in the event.tag.report event.
    • Remove the reader model as a listener for the event.tag.report event signal.
    public void autonomousModeOff() {
          setupOperatingModeMeasurement.executeWrite(STANDBY);
          eventTagReportReportSignal.removeSignalListener(this);
          eventTagReportUnregisterRequestCommand.execute();
    }
    

  9. Implement the signalOccurred(SignalService, Object, Object) method to determine what signal occurred and to take the appropriate action. Specifically, you'll want to determine if the signal is for the event.tag.report event. If it is, call a new method to process the tag read.
    public void signalOccurred(SignalService source, Object timestamp, Object data) {
          if (source.equals(eventTagReportReportSignal))
                handleEventTagReport(timestamp, data);
    }
    

  10. Add a new method to handle the event.tag.report event signals. This method is called from the signalOccurred(SignalService, Object, Object) method when an event.tag.report event signal is received. You'll need to create the necessary tag read objects (RfidRead, RfidReads, and RfidMap) and call the superclass's notifyTagRead(RfidMap) method to trigger the publication of the tag read message. The data argument to the method is a hashtable containing the fields of the event.tag.report.
    private void handleEventTagReport(Object timestamp, Object data) {
          if (data != null && !((Hashtable)data).isEmpty()) {
                Hashtable event = (Hashtable) data;
                long timeMillis = ((Number)timestamp).longValue();
                int antenna = Integer.parseInt((String) event.get(ANTENNA));
                String tag = ((String) event.get(TAG_ID)).substring(2);
                RfidRead rfidRead = new RfidRead(readerId, timeMillis, antenna, 1);
                RfidReads rfidReads = new RfidReads(rfidRead);
                RfidService epcId = Rfid.createRfid(tag);
                RfidMap tagMap = new RfidMap(1);
                tagMap.put(epcId,rfidReads);
                notifyTagRead(tagMap);
          }
          else
                LogUtility.logWarning(this, "read error: ");
    }
    

  11. We won't implement the reader I/O features in this article, so you won't need to implement any other methods.
  12. After making the updates, check the bundle MANIFEST.MF to ensure your bundle is importing the necessary packages and services, and update if necessary.

Test the updated agent

To test your updated agent, you need to install the updated agent into the SMF runtime you created earlier. To install the updated agent:

  1. Start the SMF bundle server, if it's not already running.
  2. Submit the SiritReaderAgent to the bundle server.
  3. Start the SMF runtime.
  4. Uninstall the old version of the SiritReaderAgent bundle from the SMF runtime. To uninstall the bundle, right-click the bundle in the SMF runtime, and select Uninstall, as shown in Figure 14:.

    Figure 14. Uninstall an old version of a bundle from an SMF runtime
    Uninstall an old version of a bundle from an SMF runtime

  5. Install the new version of the SiritReaderAgent bundle into the SMF runtime.

Now comes the big moment! In order to test your agent, you need to activate the portal and trigger the motion sensor. Since we don't have any I/O devices attached to the reader or edge controller, you'll need to simulate these events. The DEVWORKS_EXAMPLE_SIRIT_DEMO_LOADER bundle installs an I/O simulator. The simulator displays a small window with Switch and Motion buttons as shown in Figure 15:


Figure 15. The IO simulator
The IO simulator

Place some RFID tags near your reader antenna. To activate the portal, click Switch. To trigger the motion sensor, click Motion. If successful, you should see messages similar to those shown in Listing 4 being written to the console.


Listing 4. Console output while reading tags

SiritReader-P1: Publishing: device/reader/P1/signal/tags = {30144b5a1cc375800000000e=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/light/P1/command/readoccurred = ON
SiritReader-R1: Tag(s) published by reader: {30144b5a1cc375800000000e=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/reader/P1/signal/tags = {30144b5a1cc3758000000009=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/light/P1/command/readoccurred = ON
SiritReader-R1: Tag(s) published by reader: {30144b5a1cc3758000000009=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/reader/P1/signal/tags = {30144b5a1cc375800000000d=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/light/P1/command/readoccurred = ON
SiritReader-R1: Tag(s) published by reader: {30144b5a1cc375800000000d=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/reader/P1/signal/tags = {30144b5a1cc3758000000008=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/light/P1/command/readoccurred = ON
SiritReader-R1: Tag(s) published by reader: {30144b5a1cc3758000000008=
[{R1:1169837302000:1:1}]}
SiritReader-P1: Publishing: device/reader/P1/signal/tags = {30144b5a1cc375800000000e=
[{R1:1169837302000:1:1}]}

To stop reading tags, click either the Motion or Switch buttons.



Back to top


Summary

In this article you learned all about the reader agent component of the Websphere RFID Device Infrastructure, including the responsibilities of reader agents and implementation considerations. Finally, you created a reader agent for a Sirit INfinity 510 RFID reader.

In this series, you've learned everything you need to know to add support for new RFID hardware to the IBM WebSphere RFID solution. You learned about the WebSphere RFID Infrastructure component and each of the components of a Device Kit hardware adapter, and how to use the Device Kit tools to build a new adapter. You learned about reader agents and how they use the Device Kit hardware adapters to communicate with and control RFID readers. As a concrete example, you built a new Device Kit adapter and a reader agent for the Sirit INfinity 510 reader. Using the information provided in this series and the source code for the existing WebSphere RFID adapters and reader agents as your guide, you can easily add support for new hardware devices to the WebSphere RFID solution.




Back to top


Downloads

DescriptionNameSizeDownload method
Required materialsSiritReaderDevelopment.zip12KBHTTP
Completed sample agentSiritReaderAgent.zip18KBHTTP
Information about download methods


Resources

Learn

Get products and technologies


About the authors

Allen Smith photo

Allen Smith is a Senior Software Engineer with the Pervasive Computing Group in Research Triangle Park, North Carolina. He works with business partners to design solutions that use IBM's pervasive middleware. You can contact Allen at allens@us.ibm.com.


Karl Freburg photo

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




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top