Professional Documents
Culture Documents
AppNote - MR NFT Sample
AppNote - MR NFT Sample
SourceCode Sample
Multi-Reader
Notification-Sample
(based on SDK version up from 4.02.00)
Public (B)
2012-05-25
AppNote_MR-NFT-Sample.docx
OBID i-scan ® Application-Note Multi-Reader NTF-Sample
Note
With the edition of this document, all previous editions become void. Indications made in this manual may be
changed without previous notice.
Copying of this document, and giving it to others and the use or communication of the contents thereof are
forbidden without express authority. Offenders are liable to the payment of damages. All rights are reserved
in the event of the grant of a patent or the registration of a utility model or design.
Composition of the information in this manual has been done to the best of our knowledge. FEIG
ELECTRONIC GmbH does not guarantee the correctness and completeness of the details given in this
manual and may not be held liable for damages ensuing from incorrect or incomplete information. Since,
despite all our efforts, errors may not be completely avoided, we are always grateful for your useful tips.
The instructions given in this manual are based on advantageous boundary conditions. FEIG ELECTRONIC
GmbH does not give any guarantee promise for perfect function in cross environments and does not give
any guaranty for the functionality of the complete system which incorporates the subject of this document.
FEIG ELECTRONIC call explicit attention that devices which are subject of this document are not designed
with components and testing methods for a level of reliability suitable for use in or in connection with surgical
implants or as critical components in any life support systems whose failure to perform can reasonably be
expected to cause significant injury to a human. To avoid damage, injury, or death, the user or application
designer must take reasonably prudent steps to protect against system failures.
Use Exclusion in Transportation Market: Devices which are subject of this document may NOT be sold,
used, leased, offer for sale, or otherwise transferred, exported, and imported by anyone in the Transportation
Market. “Transportation Market” means (i) Electronic Toll and Traffic Management (ETTM), (ii) Public Sector
Vehicle Registration, Inspection and Licensing Programs, (iii) Railroad Locomotive and Wagon tracking, (iv)
airport based ground transportation management systems (GTMS) and taxi dispatch, (v) revenue based
parking, and (vi) vehicle initiated mobile payment applications, where the RFID sticker/tag is initially attached
to the vehicle but not incorporated at the point of vehicle manufacture.
FEIG ELECTRONIC GmbH assumes no responsibility for the use of any information contained in this
manual and makes no representation that they free of patent infringement. FEIG ELECTRONIC GmbH does
not convey any license under its patent rights nor the rights of others.
® ®
OBID and OBID i-scan are registered trademarks of FEIG ELECTRONIC GmbH.
Windows is a registered trademark of Microsoft Corporation in the United States and other countries.
®
Linux is a registered Trademark of Linus Torvalds.
Contents
1. Abbreviated terms
This Application Note describes the use of software libraries which are also described in detail in
manuals or document files. For this reason we have limited the documentation to what is
absolutely necessary for understanding the functionality and use of the libraries. It is assumed that
the reader of this tutorial reads the system manual of the used OBID®-Reader and the OBID®-
Library manuals too.
FEIG ELECTRONIC GmbH does not repeat the same information about OBID® readers in different
manuals or use cross-references to certain pages in a different document. This is necessary due to
the constant updating of manuals, and it prevents confusion caused by information in out-of-date
documents. The reader of this Application Note is therefore well advised to check regularly that he
has the latest manuals. If not, these can of course be obtained whenever needed from FEIG
ELECTRONIC GmbH.
3. Introduction
4. Fundamentals of Notification-Mode
The Notification-Mode is an automatic read mode and the fastest way of scanning Transponder
data and is supported by many OBID i-scan® Readers. It should be preferred for applications with
short timing conditions to detect and read from a Transponder. The second advantage is the
buffering of the collected data in a First-in First-out buffer to provide the discontinuous request of
these data records.
The Notification-Mode is an extension of the Buffered-Read-Mode. While the Buffered-Read-Mode
needs polling from the host-side application for receiving the automatic scanned Transponder data,
the Notification-Mode transmits these data automatically to a configurable destination (see
parameter group: OperatingMode.NotificationMode.Transmission.Destination.
IPv4).
1
In C++: callback function; in Java: listener method; in C#: delegate
2
Step (3) overwrites older data records.
If the acknowledge option is configured in the Reader’s configuration, the asynchronous task inside
FEISC will transmit this protocol after the callback function returns (5). By default, a Reader
3
transmits the data records as fast as possible and is not waiting for an acknowledge .
FEDM
void MyClass::StartAsyncTask()
{
int back = 0;
FEDM_TASK_INIT taskInit; // task initialization structure (declared in FEDM_ISCReaderModule.h)
// and go…
back = reader.StartAsyncTask(&taskInit);
if(back != 0)
{
// error handling
}
}
3
When the secured data transmission is configured, handshake is enabled by default and cannot be disabled.
import de.feig.*;
try
{ // and go…
reader.startAsyncTask(FedmTaskOption.ID_NOTIFICATION, this, taskInit);
}
catch (Exception ex)
{
// error handling
}
}
C#
using OBID;
// total timeout (in seconds after receiving the first bytes of a record) is set internally to 30s
// Reader waits for an acknowledge, before the next records are transmitted.
// See also 4.6. Considerations for fail-safe operation
taskOpt.NotifyWithAck = 1;
try
{ // and go…
reader.StartAsyncTask(FedmTaskOption.ID_NOTIFICATION, this, taskOpt);
}
catch (Exception ex)
{
// error handling
}
}
FEDM
// definition of the callback function; must be declared as a static member in the header
// iError - error code (<0) or OK (0) or reader status byte (>0)
// ucCmd – command byte from notification protocol
// cIPAdr - IP-Address of the reader
// iPortNr - port number of the local port which has received the notification
void MyClass::cbsFct2(void* pAny, int iError, unsigned char ucCmd, char* cIPAdr, int iPortNr)
{
MyClass* pThis = (MyClass*)pAny;
if(iError != 0)
{
// process error codes, but leave the callback as fast as possible
return;
}
switch(ucCmd)
{
case 0x22: // notification data
// process the notification, but leave the callback as fast as possible
break;
case 0x6E: // diagnostic data (keep-alive protocol from Reader)
// process diagnostic data, but leave the callback as fast as possible
break;
case 0x74: // input status
// process input status, but leave the callback as fast as possible
break;
}
}
import de.feig.*;
/**
* Listener method for the transponder data coming with notification event.
* @param error error code (<0) or OK (0) or reader status byte (>0)
* @param remoteIP IP-Address of the reader
* @param portNr port number of the local port which has received the notification
*/
public void onNewNotification(int error, String remoteIP, int portNr)
{
if(iError != 0)
{
// process error codes, but leave the callback as fast as possible
return;
}
C#
using OBID;
// Listener method for the transponder data coming with notification event.
// error - error code (<0) or OK (0) or reader status byte (>0)
// remoteIP - IP-Address of the reader
// portNr - port number of the local port which has received the notification
If the listener thread is just calling the callback function, CancelAsyncTask() returns
immediately with the error code -4084 ("FEISC: asynchronous task is busy") and
CancelAsyncTask() has to be called again, until the return value is 0.
ConnectionHoldTime. With every connect to a server, a new transmit port is selected in the
Reader’s TCP stack and is blocked for up to 2 minutes before it gets into the closed state. In
high frequented notification situations, this can cause a problem in the Reader, because the
number of ports is limited and when all ports are used, a notification cannot be sent until the
first port reaches the closed state.
When the Ethernet cable gets broken while an active communication, the server-side application
(Host) may not indicate an error while he is listening for new transmissions. On the other side, the
Reader will run in an error with the next transmission and can close and reopen the socket. But the
close and reopen will never be noticed by the Host, as he is listening at a half-closed port.
The solution for this very realistic scenario is the activating of the Keep-Alive option on the server-
side (see code examples in 4.2. Register an event).
When the code execution is just inside a callback function from the main process and the
application calls CanceAsyncTask() in a loop, the main process will be locked by the loop and
the callback function will never return. This is a typical deadlock situation, where a caller is waiting
for completion of a process while this process is interrupted by the scheduler.
One solution for this situation is an repetitive asynchronous call (message driven?) of
CanceAsyncTask() to close the execution path of the main process immediately, when
CanceAsyncTask() returns with -4084 (busy). This enables the scheduler to continue the
callback function.
A second and familiar situation is the closing of an application while the listener thread is still inside
the callback function. The application programmer has to be ensure that closing the application
does not interrupt the canceling of the listener thread.
The sample has the task to receive notification messages from many Readers, to put these
messages in order of the time stamp and finally display the notification messages in a text window.
The GUI is kept very simple. Only the number of the Readers must be set. The listening will be
started with the button Listen. The display of the messages can be disabled for a long-term run to
avoid memory allocation for the textbox and the slowing-down of the sample.
Before the sample can be used, all Readers must be configured (e.g. with ISOStart) with an
applicable Port Number for the Notification-Mode (OperatingMode.NotificationMode.
Transmission.Destination.PortNumber). The first Reader should send notifications to the
Port 10005, the 2nd to 10006 and so one.
The three sub-tasks Receive, Collection/Distribution and Display of messages are assigned each
to one class FEListener, FEMsgCollector and FEBackEnd_Monitor. The picture below shows the
complete architecture and the data flow of the notification messages.
The main approach of the design is the efficient data flow in a multithreading environment. The
number of Readers and the number of notifications should not be limited by the program
architecture. Therefore, the architecture follows the principles of the Queuing Theory with
decoupling of events with waiting queues. For each physical Reader one Listener object is
established to put each notification of the dedicated Reader into the back of a First-In-First-Out
queue. The next processing element is the Collector which processes the queues of the listener,
put the messages in order of the time stamps and collect them in the queue (FIFO) of the
Collector. A deployment thread processes the collected messages and distributes them to one or
more back-ends. A back-end is finally the consumer of all notification messages.
5.3.1. FE_NTF_MESSAGE
This C Structure is the type of each notification message. It contains the pure values as they are
transmitted by the Reader. This message type is shipped from queue to queue and the back-end
can interpret and convert the values into human readable formats.
5.3.2. FEListener
The Listener class is the actor, which collects all notification messages of the dedicated Reader in
a queue. The access to the queue is synchronized with a Semaphor.
The Listener embeds the reader object of type FEDM_ISCReaderModule (C++) or FedmIscReader
(C#, Java) with which the Listener realizes the background listener thread.
For each physical Reader one Listener object is created. This has the consequence, that for each
physical Reader a separate listener port has to be opened. But only this guarantees a decoupling
of notification transmissions and no Reader must wait.
5.3.3. FEMsgCollector
The Message Collector transfers all messages from the Listener queues to its own message
queue. This is done in a thread and all messages are put in order of the time stamp. The Message
Collector has a second thread which deploys all messages to input queues of back-ends.
5.3.4. FEBackEnd_Monitor
A back-end is the consumer of the notification message. In principle, the sample can support one
or multiple back-ends. Each back-end must be derived from the base class FEBackEnd.
The architecture is flexible according the types of back-ends. With the sample, the Monitor back-
end is realized, but any other back-end can be implemented and added to the sample.