User Guide Reader RP Proxy

Features

The Fosstrak Reader RP Proxy is a Java class library that supports the communication with a reader that implements the EPCglobal Reader Protocol Version 1.1.

Implemented elements of the protocol include:

  • Transport Binding: TCP and HTTP
  • Message Binding: XML and Text
  • Synchronous and Asynchronous Messaging (Notification Channels)
  • Triggers
  • Data Selectors

The reader can be configured through a method call for each command or all the settings can be written into a configuration file which is processed by an automated configurator.

Field of Application

  • Communicate with a reader via the EPCglobal Reader Protocol Version 1.1 from within your Java application.
  • Implement the NotificationChannelListener interface to receive notifications from the reader in your Java application.

Installing the Fosstrak Reader RP Proxy

The following instructions show how to install the Fosstrak Reader RP Proxy:

  • Download the Reader RP Proxy binaries with the dependencies included from the download section of the website.
  • Unzip the downloaded file.
  • Add the jar to your classpath.
  • All the dependencies should be accessible through your classpath as well. This should be the case if you use the zip with all the dependencies included.
  • Make sure you are using a Java Runtime Environment 1.5 or higher.
  • Use the proxy as outlined in the two examples below.

First Steps

Configure the reader with a series of Java method calls

This example requires that there is a reader running that supports the HTTP/XML transport message binding of the Reader Protocol available at localhost:8000. If these settings are incorrect for your setup, you will need to adjust the following variables:

  • MESSAGE_FORMAT
  • TRANSPORT_PROTOCOL
  • COMMAND_CHANNEL_HOST
  • COMMAND_CHANNEL_PORT

You might also want to consider using our existing Java implementation of a reader which includes a simulation engine.

import org.fosstrak.reader.rprm.core.EventType;
import org.fosstrak.reader.rprm.core.FieldName;
import org.fosstrak.reader.rp.proxy.DataSelector;
import org.fosstrak.reader.rp.proxy.NotificationChannel;
import org.fosstrak.reader.rp.proxy.ReaderDevice;
import org.fosstrak.reader.rp.proxy.Source;
import org.fosstrak.reader.rp.proxy.Trigger;
import org.fosstrak.reader.rp.proxy.factories.DataSelectorFactory;
import org.fosstrak.reader.rp.proxy.factories.NotificationChannelFactory;
import org.fosstrak.reader.rp.proxy.factories.ReaderDeviceFactory;
import org.fosstrak.reader.rp.proxy.factories.TriggerFactory;
import org.fosstrak.reader.rp.proxy.msg.Handshake;

public class ReaderProxyExample {

   private static int MESSAGE_FORMAT = Handshake.FORMAT_XML;
   private static int TRANSPORT_PROTOCOL = Handshake.HTTP;

   private static final String COMMAND_CHANNEL_HOST = "localhost";
   private static final int COMMAND_CHANNEL_PORT = 8000;

   private static final String READ_TRIGGER_NAME = "ReadTrigger";
   private static final String READ_TRIGGER_TYPE = Trigger.TIMER;
   private static final String READ_TRIGGER_VALUE = "ms=2000";

   private static final String NOTIFICATION_TRIGGER_NAME = "NotificationTrigger";
   private static final String NOTIFICATION_TRIGGER_TYPE = Trigger.CONTINUOUS;
   private static final String NOTIFICATION_TRIGGER_VALUE = "";

   private static final String DATA_SELECTOR_NAME = "DataSelector";
   private static final String[] EVENT_FILTERS = new String[] {
         EventType.EV_OBSERVED, EventType.EV_LOST};
   private static final String[] FIELD_NAMES = new String[] {
         FieldName.EVENT_TYPE, FieldName.READER_NAME, FieldName.TAG_ID,
         FieldName.TAG_ID_AS_PURE_URI, FieldName.TAG_ID_AS_TAG_URI,
         FieldName.SOURCE_NAME};

   private static final String NOTIFICATION_CHANNEL_NAME = "NotificationChannel";
   private static final String NOTIFICATION_CHANNEL_HOST = "localhost";
   private static final int NOTIFICATION_CHANNEL_PORT = 9000;
   private static final String NOTIFICATION_CHANNEL_MODE = "connect";
   private static final String NOTIFICATION_CHANNEL_ADDRESS = "tcp://"
         + NOTIFICATION_CHANNEL_HOST + ":" + NOTIFICATION_CHANNEL_PORT
         + "?mode=" + NOTIFICATION_CHANNEL_MODE;

   public static void main(String[] args) throws Exception {
      // create handshake
      Handshake handshake = new Handshake();
      handshake.setMessageFormat(MESSAGE_FORMAT);
      handshake.setTransportProtocol(TRANSPORT_PROTOCOL);

      // get reader device proxy
      System.out.println("Get reader device proxy.");
      ReaderDevice readerDevice = ReaderDeviceFactory.getReaderDevice(
            COMMAND_CHANNEL_HOST, COMMAND_CHANNEL_PORT, handshake);

      // get current source proxy
      System.out.println("Get current source.");
      Source source = readerDevice.getCurrentSource();
      System.out.println("Name of current source is: " + source.getName());

      // create read trigger
      System.out.println("Create read trigger.");
      Trigger readTrigger = TriggerFactory.createTrigger(READ_TRIGGER_NAME,
            READ_TRIGGER_TYPE, READ_TRIGGER_VALUE, readerDevice);

      // create notification trigger
      System.out.println("Create notification trigger.");
      Trigger notificationTrigger = TriggerFactory.createTrigger(
            NOTIFICATION_TRIGGER_NAME, NOTIFICATION_TRIGGER_TYPE,
            NOTIFICATION_TRIGGER_VALUE, readerDevice);

      // data selector
      System.out.println("Create data selector.");
      DataSelector dataSelector = DataSelectorFactory.createDataSelector(
            DATA_SELECTOR_NAME, readerDevice);
      System.out.println("Add event filters to data selector.");
      dataSelector.addEventFilters(EVENT_FILTERS);
      System.out.println("Add field names to data selector.");
      dataSelector.addFieldNames(FIELD_NAMES);
      //System.out.println("Add tag fields to data selector.");
      //dataSelector.addTagFieldNames(TAG_FIELDS);

      // create notification channel
      System.out.println("Create notification channel.");
      NotificationChannel notificationChannel = NotificationChannelFactory
            .createNotificationChannel(NOTIFICATION_CHANNEL_NAME,
            NOTIFICATION_CHANNEL_ADDRESS, readerDevice);
      System.out.println("Set data selector of notification channel.");
      notificationChannel.setDataSelector(dataSelector);
      System.out.println("Add notification trigger to notification channel.");
      notificationChannel.addNotificationTriggers(
            new Trigger[] {notificationTrigger});

      // add current source to notification channel
      System.out.println("Add source to notification channel.");
      notificationChannel.addSources(new Source[] {source});

      // add read trigger to source
      System.out.println("Add read trigger to source.");
      source.addReadTriggers(new Trigger[] {readTrigger});
   }
}

In order to process the notification messages from the reader, the proxy provides the class org.fosstrak.reader.rp.proxy.NotificationChannelEndPoint. The class that is interested in receiving the notification messages has to implement the interface org.fosstrak.reader.rp.proxy.NotificationChannelListener and has to be registered with the NotificationChannelEndPoint as shown below.

import org.fosstrak.reader.rp.proxy.NotificationChannelListener;
import org.fosstrak.reader.rprm.core.msg.notification.Notification;

public class ReaderNotificationChannelListener implements NotificationChannelListener {

   public void dataReceived(Notification notification) {
      System.out.println("Notification received: " + notification);

      // add your code to process notification message here
   }
}

Code to create a NotificationChannelListener and to add a listener to it:

   NotificationChannelListener notificationChannelListener =
         new ReaderNotificationChannelListener();

   // create notification channel endpoint to receive messages
   System.out.println("Create NotificationChannelEndpoint at port '"
         + NOTIFICATION_CHANNEL_PORT + "'.");
   NotificationChannelEndPoint notificationChannelEndPoint =
         new NotificationChannelEndPoint(NOTIFICATION_CHANNEL_PORT);

   // add listerner to notification channel endpoint
   notificationChannelEndPoint.addListener(notificationChannelListener);

Configure the reader with the configuration engine and a corresponding configuration file

An other way to configure the reader is to use the ReaderConfigurator that is part of the Fosstrak Reader RP Proxy module. It is less flexible than using method calls for each configuration item but needs less code too.

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.fosstrak.reader.proxy.configurator.ReaderConfigurator;

public class ReaderConfiguratorExample {

   private static final String CONFIG_FILE_PATH =
         "./props/ReaderDeviceConfiguration.xml";

   private static final Logger LOG = Logger.getLogger(
         ReaderConfiguratorExample.class);

   public static void main(String[] args) throws Exception {

      // initialize the logger
      BasicConfigurator.configure();

      // configure the reader
      LOG.info("Configurate reader device.");
      ReaderConfigurator.initReaderDeviceConfiguration(CONFIG_FILE_PATH);
   }
}

The corresponding ReaderDeviceConfiguration.xml configuration file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<configurationDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ReaderDeviceConfiguration.xsd">
   <readerDeviceConfiguration>

      <!-- reader configuration -->
      <readerConfig>
         <commandChannelHost>localhost</commandChannelHost>
         <commandChannelPort>8000</commandChannelPort>
         <transportProtocol>HTTP</transportProtocol>
         <transportFormat>XML</transportFormat>
      </readerConfig>

      <!-- read triggers -->
      <triggers>
         <timerTrigger name="ReadTrigger">
            <value>2000</value>
         </timerTrigger>
      </triggers>

      <!-- notification triggers -->
      <triggers>
         <continuousTrigger name="NotificationTrigger"/>
      </triggers>

      <!-- data selectors -->
      <dataSelectors>
         <dataSelector name="DataSelector">
            <fieldNames>
               <fieldName>eventType</fieldName>
               <fieldName>readerName</fieldName>
               <fieldName>tagID</fieldName>
               <fieldName>tagIDasPureURI</fieldName>
               <fieldName>tagIDasTagURI</fieldName>
               <fieldName>sourceName</fieldName>
            </fieldNames>
            <eventFilters>
               <eventFilter>evObserved</eventFilter>
               <eventFilter>evLost</eventFilter>
            </eventFilters>
         </dataSelector>
      </dataSelectors>

      <!-- notification channels -->
      <notificationChannels>
         <notificationChannel name="NotificationChannel">
            <notificationChannelHost>localhost</notificationChannelHost>
            <notificationChannelPort>9000</notificationChannelPort>
            <transportProtocol>TCP</transportProtocol>
            <notificationChannelMode>connect</notificationChannelMode>
            <sources>
               <source>Shelf1</source>
            </sources>
            <notificationTriggers>
               <triggerName>NotificationTrigger</triggerName>
            </notificationTriggers>
            <dataSelector>DataSelector</dataSelector>
         </notificationChannel>
      </notificationChannels>

      <!-- sources -->
      <sources>
         <source name="Shelf1">
            <triggerName>ReadTrigger</triggerName>
         </source>
      </sources>

   </readerDeviceConfiguration>
</configurationDocument>