RFID Integration in Java: Complete Implementation Guide

RFID (Radio-Frequency Identification) enables wireless identification of objects using radio waves. Here's a comprehensive guide to implementing RFID integration in Java for various applications.


RFID Architecture Overview

Key RFID Technologies

  • LF (Low Frequency): 125-134 kHz, short range
  • HF (High Frequency): 13.56 MHz, NFC compatible
  • UHF (Ultra High Frequency): 860-960 MHz, long range
  • Active vs Passive: Battery-powered vs powered by reader

Common RFID Protocols

  • ISO 14443: NFC proximity cards
  • ISO 15693: Vicinity cards
  • EPC Gen2: UHF RFID standard
  • MIFARE: NXP's popular HF protocol

Basic RFID Reader Implementation

Example 1: Basic RFID Reader using Serial Communication

import gnu.io.*;
import java.io.*;
import java.util.*;
public class BasicRFIDReader implements SerialPortEventListener {
private SerialPort serialPort;
private InputStream inputStream;
private OutputStream outputStream;
private BufferedReader reader;
private String portName;
private int baudRate;
private List<RFIDEventListener> listeners;
public BasicRFIDReader(String portName, int baudRate) {
this.portName = portName;
this.baudRate = baudRate;
this.listeners = new ArrayList<>();
}
public boolean connect() {
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.err.println("Port " + portName + " is currently in use");
return false;
}
serialPort = (SerialPort) portIdentifier.open("RFIDReader", 2000);
serialPort.setSerialPortParams(baudRate, 
SerialPort.DATABITS_8, 
SerialPort.STOPBITS_1, 
SerialPort.PARITY_NONE);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | 
SerialPort.FLOWCONTROL_RTSCTS_OUT);
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
System.out.println("Connected to RFID reader on " + portName);
return true;
} catch (Exception e) {
System.err.println("Failed to connect to RFID reader: " + e.getMessage());
return false;
}
}
public void disconnect() {
try {
if (serialPort != null) {
serialPort.removeEventListener();
serialPort.close();
}
if (inputStream != null) inputStream.close();
if (outputStream != null) outputStream.close();
System.out.println("Disconnected from RFID reader");
} catch (Exception e) {
System.err.println("Error disconnecting: " + e.getMessage());
}
}
public void sendCommand(byte[] command) {
try {
outputStream.write(command);
outputStream.flush();
} catch (IOException e) {
System.err.println("Error sending command: " + e.getMessage());
}
}
@Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
String data = reader.readLine();
if (data != null && !data.trim().isEmpty()) {
processRFIDData(data.trim());
}
} catch (IOException e) {
System.err.println("Error reading serial data: " + e.getMessage());
}
}
}
private void processRFIDData(String data) {
// Parse RFID data based on reader protocol
RFIDTag tag = parseTagData(data);
if (tag != null) {
notifyListeners(tag);
}
}
private RFIDTag parseTagData(String data) {
// Common RFID data formats:
// "TAG: 1234567890"
// "EPC: 300833B2DDD9014000000000"
// "UID: 04A1B2C3D4E5F6"
try {
RFIDTag tag = new RFIDTag();
if (data.startsWith("TAG: ")) {
String tagId = data.substring(5).trim();
tag.setTagId(tagId);
tag.setProtocol("UNKNOWN");
} else if (data.startsWith("EPC: ")) {
String epc = data.substring(5).trim();
tag.setTagId(epc);
tag.setProtocol("EPC Gen2");
tag.setTagType("UHF");
} else if (data.startsWith("UID: ")) {
String uid = data.substring(5).trim();
tag.setTagId(uid);
tag.setProtocol("ISO14443A");
tag.setTagType("HF");
} else if (data.matches("[0-9A-Fa-f]{8,24}")) {
// Raw hex data
tag.setTagId(data.toUpperCase());
tag.setProtocol("UNKNOWN");
} else {
return null; // Unrecognized format
}
tag.setTimestamp(System.currentTimeMillis());
tag.setReaderId(portName);
return tag;
} catch (Exception e) {
System.err.println("Error parsing RFID data: " + e.getMessage());
return null;
}
}
public void addEventListener(RFIDEventListener listener) {
listeners.add(listener);
}
public void removeEventListener(RFIDEventListener listener) {
listeners.remove(listener);
}
private void notifyListeners(RFIDTag tag) {
for (RFIDEventListener listener : listeners) {
listener.onTagDetected(tag);
}
}
// Common RFID commands
public void startContinuousReading() {
// Send command to start continuous reading
byte[] startCmd = {0x02, 0x52, 0x03}; // Example command
sendCommand(startCmd);
}
public void stopContinuousReading() {
// Send command to stop continuous reading
byte[] stopCmd = {0x02, 0x53, 0x03}; // Example command
sendCommand(stopCmd);
}
public void setPower(int powerLevel) {
// Set reader power (0-100%)
String powerCmd = String.format("POWER %02X", powerLevel);
sendCommand(powerCmd.getBytes());
}
public static void main(String[] args) {
BasicRFIDReader reader = new BasicRFIDReader("COM3", 9600);
reader.addEventListener(new RFIDEventListener() {
@Override
public void onTagDetected(RFIDTag tag) {
System.out.println("Tag detected: " + tag);
}
@Override
public void onReaderError(String error) {
System.err.println("Reader error: " + error);
}
});
if (reader.connect()) {
reader.startContinuousReading();
// Keep running for 30 seconds
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
reader.stopContinuousReading();
reader.disconnect();
}
}
}
// Supporting classes
interface RFIDEventListener {
void onTagDetected(RFIDTag tag);
void onReaderError(String error);
}
class RFIDTag {
private String tagId;
private String protocol;
private String tagType;
private String readerId;
private long timestamp;
private int rssi;
private int antenna;
private Map<String, Object> additionalData;
public RFIDTag() {
this.additionalData = new HashMap<>();
}
// Getters and setters
public String getTagId() { return tagId; }
public void setTagId(String tagId) { this.tagId = tagId; }
public String getProtocol() { return protocol; }
public void setProtocol(String protocol) { this.protocol = protocol; }
public String getTagType() { return tagType; }
public void setTagType(String tagType) { this.tagType = tagType; }
public String getReaderId() { return readerId; }
public void setReaderId(String readerId) { this.readerId = readerId; }
public long getTimestamp() { return timestamp; }
public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
public int getRssi() { return rssi; }
public void setRssi(int rssi) { this.rssi = rssi; }
public int getAntenna() { return antenna; }
public void setAntenna(int antenna) { this.antenna = antenna; }
public Map<String, Object> getAdditionalData() { return additionalData; }
public void setAdditionalData(Map<String, Object> additionalData) { this.additionalData = additionalData; }
@Override
public String toString() {
return String.format("RFIDTag{id=%s, protocol=%s, type=%s, reader=%s, time=%tT}", 
tagId, protocol, tagType, readerId, new Date(timestamp));
}
}

Advanced RFID Framework

Example 2: Comprehensive RFID Management System

import java.util.*;
import java.util.concurrent.*;
import java.sql.*;
public class RFIDManagementSystem {
private final Map<String, RFIDReader> readers;
private final ScheduledExecutorService scheduler;
private final Connection databaseConnection;
private final TagProcessor tagProcessor;
private final AlertManager alertManager;
private final Map<String, TagHistory> tagHistory;
private boolean systemRunning;
public RFIDManagementSystem() {
this.readers = new ConcurrentHashMap<>();
this.scheduler = Executors.newScheduledThreadPool(5);
this.databaseConnection = initializeDatabase();
this.tagProcessor = new TagProcessor();
this.alertManager = new AlertManager();
this.tagHistory = new ConcurrentHashMap<>();
this.systemRunning = false;
}
public void initializeSystem() {
systemRunning = true;
// Load reader configurations
loadReaderConfigurations();
// Start monitoring
startReaders();
// Start background tasks
startBackgroundTasks();
System.out.println("RFID Management System initialized");
}
public void shutdownSystem() {
systemRunning = false;
// Stop all readers
for (RFIDReader reader : readers.values()) {
reader.stop();
}
// Shutdown scheduler
scheduler.shutdown();
// Close database connection
try {
if (databaseConnection != null) {
databaseConnection.close();
}
} catch (SQLException e) {
System.err.println("Error closing database: " + e.getMessage());
}
System.out.println("RFID Management System shutdown");
}
private void loadReaderConfigurations() {
// Load from database or configuration file
try {
Statement stmt = databaseConnection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM reader_configurations");
while (rs.next()) {
String readerId = rs.getString("reader_id");
String port = rs.getString("port");
int baudRate = rs.getInt("baud_rate");
String protocol = rs.getString("protocol");
int power = rs.getInt("power_level");
RFIDReader reader = new RFIDReader(readerId, port, baudRate, protocol);
reader.setPower(power);
reader.addEventListener(new SystemTagListener());
readers.put(readerId, reader);
}
rs.close();
stmt.close();
} catch (SQLException e) {
System.err.println("Error loading reader configurations: " + e.getMessage());
}
}
private void startReaders() {
for (RFIDReader reader : readers.values()) {
if (reader.connect()) {
reader.start();
System.out.println("Started reader: " + reader.getReaderId());
} else {
System.err.println("Failed to start reader: " + reader.getReaderId());
}
}
}
private void startBackgroundTasks() {
// Tag history cleanup (every hour)
scheduler.scheduleAtFixedRate(this::cleanupTagHistory, 1, 1, TimeUnit.HOURS);
// Database synchronization (every 5 minutes)
scheduler.scheduleAtFixedRate(this::syncWithDatabase, 5, 5, TimeUnit.MINUTES);
// System health check (every minute)
scheduler.scheduleAtFixedRate(this::healthCheck, 1, 1, TimeUnit.MINUTES);
}
private Connection initializeDatabase() {
try {
Class.forName("org.sqlite.JDBC");
return DriverManager.getConnection("jdbc:sqlite:rfid_system.db");
} catch (Exception e) {
System.err.println("Failed to initialize database: " + e.getMessage());
return null;
}
}
private class SystemTagListener implements RFIDEventListener {
@Override
public void onTagDetected(RFIDTag tag) {
// Process tag in background
scheduler.execute(() -> processTagDetection(tag));
}
@Override
public void onReaderError(String error) {
alertManager.raiseAlert("READER_ERROR", error);
}
}
private void processTagDetection(RFIDTag tag) {
try {
// Update tag history
updateTagHistory(tag);
// Process tag data
TagProcessingResult result = tagProcessor.processTag(tag);
// Check for alerts
if (result.hasAlerts()) {
for (String alert : result.getAlerts()) {
alertManager.raiseAlert("TAG_ALERT", alert);
}
}
// Store in database
storeTagInDatabase(tag, result);
// Notify interested parties
notifyTagEvent(tag, result);
} catch (Exception e) {
System.err.println("Error processing tag " + tag.getTagId() + ": " + e.getMessage());
}
}
private void updateTagHistory(RFIDTag tag) {
String tagId = tag.getTagId();
TagHistory history = tagHistory.computeIfAbsent(tagId, k -> new TagHistory(tagId));
history.addDetection(tag);
// Check for rapid succession reads (potential read errors)
if (history.getRecentDetections(5).size() >= 5) {
alertManager.raiseAlert("RAPID_READS", 
"Tag " + tagId + " detected rapidly at reader " + tag.getReaderId());
}
}
private void storeTagInDatabase(RFIDTag tag, TagProcessingResult result) {
try {
PreparedStatement stmt = databaseConnection.prepareStatement(
"INSERT INTO tag_detections (tag_id, reader_id, timestamp, rssi, antenna, processed_data) " +
"VALUES (?, ?, ?, ?, ?, ?)"
);
stmt.setString(1, tag.getTagId());
stmt.setString(2, tag.getReaderId());
stmt.setTimestamp(3, new Timestamp(tag.getTimestamp()));
stmt.setInt(4, tag.getRssi());
stmt.setInt(5, tag.getAntenna());
stmt.setString(6, result.getProcessedData().toString());
stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
System.err.println("Error storing tag in database: " + e.getMessage());
}
}
private void notifyTagEvent(RFIDTag tag, TagProcessingResult result) {
// Could send to message queue, web socket, etc.
System.out.println("Tag event: " + tag.getTagId() + " at " + 
new Date(tag.getTimestamp()) + " - " + result.getStatus());
}
private void cleanupTagHistory() {
long cutoffTime = System.currentTimeMillis() - (24 * 60 * 60 * 1000); // 24 hours ago
Iterator<Map.Entry<String, TagHistory>> it = tagHistory.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, TagHistory> entry = it.next();
if (entry.getValue().getLastDetectionTime() < cutoffTime) {
it.remove();
}
}
}
private void syncWithDatabase() {
// Sync any pending data with database
System.out.println("Performing database synchronization...");
}
private void healthCheck() {
for (RFIDReader reader : readers.values()) {
if (!reader.isConnected()) {
alertManager.raiseAlert("READER_DISCONNECTED", 
"Reader " + reader.getReaderId() + " is disconnected");
}
}
}
// Public API methods
public List<RFIDTag> getRecentTags(int minutes) {
List<RFIDTag> recentTags = new ArrayList<>();
long cutoffTime = System.currentTimeMillis() - (minutes * 60 * 1000);
for (TagHistory history : tagHistory.values()) {
for (RFIDTag tag : history.getDetectionsSince(cutoffTime)) {
recentTags.add(tag);
}
}
return recentTags;
}
public TagHistory getTagHistory(String tagId) {
return tagHistory.get(tagId);
}
public void addReader(RFIDReader reader) {
readers.put(reader.getReaderId(), reader);
if (systemRunning) {
reader.connect();
reader.start();
}
}
public void removeReader(String readerId) {
RFIDReader reader = readers.remove(readerId);
if (reader != null) {
reader.stop();
reader.disconnect();
}
}
public static void main(String[] args) {
RFIDManagementSystem system = new RFIDManagementSystem();
system.initializeSystem();
// Keep system running
try {
Thread.sleep(300000); // 5 minutes
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
system.shutdownSystem();
}
}
// Extended RFID Reader class
class RFIDReader extends BasicRFIDReader {
private String readerId;
private String protocol;
private boolean running;
public RFIDReader(String readerId, String portName, int baudRate, String protocol) {
super(portName, baudRate);
this.readerId = readerId;
this.protocol = protocol;
this.running = false;
}
public String getReaderId() { return readerId; }
public String getProtocol() { return protocol; }
public boolean isRunning() { return running; }
public void start() {
if (!running) {
startContinuousReading();
running = true;
}
}
public void stop() {
if (running) {
stopContinuousReading();
running = false;
}
}
public boolean isConnected() {
// Implementation depends on specific reader
return running;
}
public void setPower(int powerLevel) {
if (powerLevel < 0 || powerLevel > 100) {
throw new IllegalArgumentException("Power level must be between 0 and 100");
}
super.setPower(powerLevel);
}
}
// Tag processing classes
class TagProcessor {
private Map<String, TagRule> rules;
private Map<String, TagMetadata> tagDatabase;
public TagProcessor() {
this.rules = new HashMap<>();
this.tagDatabase = new HashMap<>();
loadRules();
loadTagDatabase();
}
public TagProcessingResult processTag(RFIDTag tag) {
TagProcessingResult result = new TagProcessingResult();
result.setTagId(tag.getTagId());
result.setTimestamp(tag.getTimestamp());
// Apply rules
for (TagRule rule : rules.values()) {
if (rule.matches(tag)) {
rule.apply(tag, result);
}
}
// Look up metadata
TagMetadata metadata = tagDatabase.get(tag.getTagId());
if (metadata != null) {
result.setMetadata(metadata);
} else {
result.addAlert("UNKNOWN_TAG", "Tag " + tag.getTagId() + " not in database");
}
return result;
}
private void loadRules() {
// Load processing rules from configuration
rules.put("RSSI_CHECK", new RssiRule(-70));
rules.put("RAPID_READ", new RapidReadRule(1000)); // 1 second
rules.put("LOCATION_CHECK", new LocationRule());
}
private void loadTagDatabase() {
// Load tag metadata from database
// This would typically come from an external database
tagDatabase.put("E20000172211012421703C79", 
new TagMetadata("E20000172211012421703C79", "Pallet_001", "WAREHOUSE", "ACTIVE"));
tagDatabase.put("E20000172211009921703C80", 
new TagMetadata("E20000172211009921703C80", "Box_042", "SHIPPING", "ACTIVE"));
}
}
class TagProcessingResult {
private String tagId;
private long timestamp;
private String status;
private TagMetadata metadata;
private List<String> alerts;
private Map<String, Object> processedData;
public TagProcessingResult() {
this.alerts = new ArrayList<>();
this.processedData = new HashMap<>();
this.status = "PROCESSED";
}
// Getters and setters
public String getTagId() { return tagId; }
public void setTagId(String tagId) { this.tagId = tagId; }
public long getTimestamp() { return timestamp; }
public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public TagMetadata getMetadata() { return metadata; }
public void setMetadata(TagMetadata metadata) { this.metadata = metadata; }
public List<String> getAlerts() { return alerts; }
public boolean hasAlerts() { return !alerts.isEmpty(); }
public void addAlert(String type, String message) { 
alerts.add(type + ": " + message); 
}
public Map<String, Object> getProcessedData() { return processedData; }
public void setProcessedData(Map<String, Object> processedData) { this.processedData = processedData; }
}
class TagMetadata {
private String tagId;
private String itemName;
private String location;
private String status;
private Map<String, String> additionalInfo;
public TagMetadata(String tagId, String itemName, String location, String status) {
this.tagId = tagId;
this.itemName = itemName;
this.location = location;
this.status = status;
this.additionalInfo = new HashMap<>();
}
// Getters and setters
public String getTagId() { return tagId; }
public String getItemName() { return itemName; }
public String getLocation() { return location; }
public String getStatus() { return status; }
public Map<String, String> getAdditionalInfo() { return additionalInfo; }
}
// Tag rules
interface TagRule {
boolean matches(RFIDTag tag);
void apply(RFIDTag tag, TagProcessingResult result);
}
class RssiRule implements TagRule {
private int minRssi;
public RssiRule(int minRssi) {
this.minRssi = minRssi;
}
@Override
public boolean matches(RFIDTag tag) {
return true; // Apply to all tags
}
@Override
public void apply(RFIDTag tag, TagProcessingResult result) {
if (tag.getRssi() < minRssi) {
result.addAlert("LOW_SIGNAL", 
"Low RSSI (" + tag.getRssi() + "dBm) for tag " + tag.getTagId());
}
}
}
class RapidReadRule implements TagRule {
private long minInterval;
public RapidReadRule(long minIntervalMs) {
this.minInterval = minIntervalMs;
}
@Override
public boolean matches(RFIDTag tag) {
return true; // Apply to all tags
}
@Override
public void apply(RFIDTag tag, TagProcessingResult result) {
// This would need access to tag history
// Implementation would check if this tag was recently read
}
}
class LocationRule implements TagRule {
@Override
public boolean matches(RFIDTag tag) {
return true; // Apply to all tags
}
@Override
public void apply(RFIDTag tag, TagProcessingResult result) {
// Check if tag is in expected location based on reader
String readerLocation = getLocationForReader(tag.getReaderId());
if (result.getMetadata() != null) {
String expectedLocation = result.getMetadata().getLocation();
if (!readerLocation.equals(expectedLocation)) {
result.addAlert("WRONG_LOCATION", 
"Tag " + tag.getTagId() + " in " + readerLocation + 
" but expected in " + expectedLocation);
}
}
}
private String getLocationForReader(String readerId) {
// Map reader IDs to locations
Map<String, String> readerLocations = new HashMap<>();
readerLocations.put("READER_001", "WAREHOUSE_IN");
readerLocations.put("READER_002", "WAREHOUSE_OUT");
readerLocations.put("READER_003", "SHIPPING_DOCK");
return readerLocations.getOrDefault(readerId, "UNKNOWN");
}
}
// Tag history tracking
class TagHistory {
private String tagId;
private List<RFIDTag> detections;
private long firstSeen;
private long lastSeen;
public TagHistory(String tagId) {
this.tagId = tagId;
this.detections = new ArrayList<>();
this.firstSeen = System.currentTimeMillis();
this.lastSeen = 0;
}
public void addDetection(RFIDTag tag) {
detections.add(tag);
lastSeen = tag.getTimestamp();
}
public List<RFIDTag> getDetectionsSince(long timestamp) {
List<RFIDTag> recent = new ArrayList<>();
for (RFIDTag tag : detections) {
if (tag.getTimestamp() >= timestamp) {
recent.add(tag);
}
}
return recent;
}
public List<RFIDTag> getRecentDetections(int count) {
int fromIndex = Math.max(0, detections.size() - count);
return new ArrayList<>(detections.subList(fromIndex, detections.size()));
}
public long getLastDetectionTime() {
return lastSeen;
}
public int getDetectionCount() {
return detections.size();
}
}
// Alert management
class AlertManager {
private List<AlertListener> listeners;
public AlertManager() {
this.listeners = new ArrayList<>();
}
public void raiseAlert(String type, String message) {
Alert alert = new Alert(type, message, System.currentTimeMillis());
for (AlertListener listener : listeners) {
listener.onAlert(alert);
}
// Also log to console
System.out.println("ALERT [" + type + "]: " + message);
}
public void addListener(AlertListener listener) {
listeners.add(listener);
}
}
interface AlertListener {
void onAlert(Alert alert);
}
class Alert {
private String type;
private String message;
private long timestamp;
private boolean acknowledged;
public Alert(String type, String message, long timestamp) {
this.type = type;
this.message = message;
this.timestamp = timestamp;
this.acknowledged = false;
}
// Getters and setters
public String getType() { return type; }
public String getMessage() { return message; }
public long getTimestamp() { return timestamp; }
public boolean isAcknowledged() { return acknowledged; }
public void acknowledge() { this.acknowledged = true; }
}

EPC Gen2 UHF RFID Implementation

Example 3: EPC Gen2 Protocol Implementation

import java.util.*;
public class EPCGen2Protocol {
private static final int MEMORY_BANK_EPC = 1;
private static final int MEMORY_BANK_TID = 2;
private static final int MEMORY_BANK_USER = 3;
public static class EPCGen2Tag {
private String epc;
private String tid;
private int rssi;
private int antenna;
private int readCount;
private byte[] pcBits;
private byte[] crc;
public EPCGen2Tag(String epc) {
this.epc = epc;
this.readCount = 1;
}
// Getters and setters
public String getEpc() { return epc; }
public String getTid() { return tid; }
public void setTid(String tid) { this.tid = tid; }
public int getRssi() { return rssi; }
public void setRssi(int rssi) { this.rssi = rssi; }
public int getAntenna() { return antenna; }
public void setAntenna(int antenna) { this.antenna = antenna; }
public int getReadCount() { return readCount; }
public void incrementReadCount() { this.readCount++; }
public byte[] getPcBits() { return pcBits; }
public void setPcBits(byte[] pcBits) { this.pcBits = pcBits; }
public byte[] getCrc() { return crc; }
public void setCrc(byte[] crc) { this.crc = crc; }
public String getEpcPure() {
// Remove header and CRC if present
if (epc.length() > 8) {
return epc.substring(2, epc.length() - 4); // Adjust based on encoding
}
return epc;
}
public String getEpcBinary() {
return hexToBinary(epc);
}
@Override
public String toString() {
return String.format("EPCGen2Tag{epc=%s, rssi=%d, antenna=%d, reads=%d}", 
epc, rssi, antenna, readCount);
}
}
public static class EPCGen2Reader {
private String readerId;
private int power;
private int session;
private int target;
private String[] antennaPorts;
public EPCGen2Reader(String readerId, String[] antennaPorts) {
this.readerId = readerId;
this.antennaPorts = antennaPorts;
this.power = 300; // Default 30 dBm
this.session = 0;
this.target = 0;
}
public List<EPCGen2Tag> inventory() {
List<EPCGen2Tag> tags = new ArrayList<>();
// Simulate inventory process
// Real implementation would send commands to reader
// For each antenna port
for (int i = 0; i < antennaPorts.length; i++) {
List<EPCGen2Tag> antennaTags = performInventoryOnAntenna(i);
tags.addAll(antennaTags);
}
return tags;
}
private List<EPCGen2Tag> performInventoryOnAntenna(int antenna) {
List<EPCGen2Tag> tags = new ArrayList<>();
// Select antenna
selectAntenna(antenna);
// Send Query command
byte[] queryCommand = buildQueryCommand(session, target);
byte[] queryResponse = sendCommand(queryCommand);
if (queryResponse != null && queryResponse.length > 0) {
// Process RN16 responses
List<Short> rn16List = extractRN16FromQueryResponse(queryResponse);
for (Short rn16 : rn16List) {
EPCGen2Tag tag = handleTagRN16(rn16, antenna);
if (tag != null) {
tags.add(tag);
}
}
}
return tags;
}
private EPCGen2Tag handleTagRN16(short rn16, int antenna) {
// Send ACK command with RN16
byte[] ackCommand = buildAckCommand(rn16);
byte[] ackResponse = sendCommand(ackCommand);
if (ackResponse != null && ackResponse.length >= 20) { // Minimum EPC length
EPCGen2Tag tag = extractTagFromAckResponse(ackResponse);
if (tag != null) {
tag.setAntenna(antenna);
// Read TID
byte[] readTidCommand = buildReadCommand(rn16, MEMORY_BANK_TID, 0, 2);
byte[] tidResponse = sendCommand(readTidCommand);
if (tidResponse != null) {
tag.setTid(bytesToHex(tidResponse));
}
return tag;
}
}
return null;
}
public byte[] readTagMemory(String epc, int memoryBank, int wordAddress, int wordCount) {
// Select the specific tag
byte[] selectCommand = buildSelectCommand(epc);
sendCommand(selectCommand);
// Inventory to get RN16
byte[] queryCommand = buildQueryCommand(session, target);
byte[] queryResponse = sendCommand(queryCommand);
if (queryResponse != null) {
List<Short> rn16List = extractRN16FromQueryResponse(queryResponse);
if (!rn16List.isEmpty()) {
short rn16 = rn16List.get(0);
// Send read command
byte[] readCommand = buildReadCommand(rn16, memoryBank, wordAddress, wordCount);
return sendCommand(readCommand);
}
}
return null;
}
public boolean writeTagMemory(String epc, int memoryBank, int wordAddress, byte[] data) {
// Similar to read, but with write command
// Implementation depends on specific reader
return false;
}
public void setPower(int power) {
this.power = power;
// Send power setting command to reader
}
public void setSession(int session) {
this.session = session;
}
public void setTarget(int target) {
this.target = target;
}
// Command building methods
private byte[] buildQueryCommand(int session, int target) {
// Build EPC Gen2 Query command
byte[] command = new byte[10]; // Simplified
command[0] = 0x01; // Command type: Query
command[1] = (byte) session;
command[2] = (byte) target;
// Add DR, M, TR, etc.
return command;
}
private byte[] buildAckCommand(short rn16) {
byte[] command = new byte[4];
command[0] = 0x02; // Command type: ACK
command[1] = (byte) ((rn16 >> 8) & 0xFF);
command[2] = (byte) (rn16 & 0xFF);
return command;
}
private byte[] buildReadCommand(short rn16, int memoryBank, int wordAddress, int wordCount) {
byte[] command = new byte[8];
command[0] = 0x03; // Command type: Read
command[1] = (byte) ((rn16 >> 8) & 0xFF);
command[2] = (byte) (rn16 & 0xFF);
command[3] = (byte) memoryBank;
command[4] = (byte) ((wordAddress >> 8) & 0xFF);
command[5] = (byte) (wordAddress & 0xFF);
command[6] = (byte) wordCount;
return command;
}
private byte[] buildSelectCommand(String epc) {
// Build Select command for specific EPC
// Implementation depends on reader
return new byte[0];
}
private void selectAntenna(int antenna) {
// Send antenna selection command
}
private byte[] sendCommand(byte[] command) {
// Send command to physical reader and get response
// This would use serial communication, TCP/IP, etc.
return null; // Placeholder
}
private List<Short> extractRN16FromQueryResponse(byte[] response) {
List<Short> rn16List = new ArrayList<>();
// Parse response to extract RN16 values
// This is highly reader-specific
return rn16List;
}
private EPCGen2Tag extractTagFromAckResponse(byte[] response) {
// Extract EPC from ACK response
if (response.length >= 20) {
// Assuming EPC starts at byte 2 and is 12 bytes (96 bits)
byte[] epcBytes = Arrays.copyOfRange(response, 2, 14);
String epc = bytesToHex(epcBytes);
EPCGen2Tag tag = new EPCGen2Tag(epc);
// Extract PC bits (bytes 0-1)
if (response.length >= 2) {
tag.setPcBits(Arrays.copyOfRange(response, 0, 2));
}
// Extract CRC (last 2 bytes)
if (response.length >= 16) {
tag.setCrc(Arrays.copyOfRange(response, 14, 16));
}
return tag;
}
return null;
}
}
// Utility methods
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
public static String hexToBinary(String hex) {
StringBuilder binary = new StringBuilder();
for (int i = 0; i < hex.length(); i++) {
char hexChar = hex.charAt(i);
int value = Integer.parseInt(String.valueOf(hexChar), 16);
String bin = Integer.toBinaryString(value);
while (bin.length() < 4) {
bin = "0" + bin;
}
binary.append(bin);
}
return binary.toString();
}
public static byte[] hexToBytes(String hex) {
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ Character.digit(hex.charAt(i+1), 16));
}
return data;
}
public static void main(String[] args) {
EPCGen2Reader reader = new EPCGen2Reader("UHF_READER_001", 
new String[]{"ANT1", "ANT2", "ANT3", "ANT4"});
reader.setPower(300); // 30 dBm
// Perform inventory
List<EPCGen2Tag> tags = reader.inventory();
System.out.println("Found " + tags.size() + " tags:");
for (EPCGen2Tag tag : tags) {
System.out.println("  " + tag);
// Read TID if not already read
if (tag.getTid() == null) {
byte[] tidData = reader.readTagMemory(tag.getEpc(), 
MEMORY_BANK_TID, 0, 2);
if (tidData != null) {
tag.setTid(bytesToHex(tidData));
System.out.println("    TID: " + tag.getTid());
}
}
}
}
}

Maven Dependencies

pom.xml for RFID Project

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>rfid-integration</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- RXTX for serial communication -->
<dependency>
<groupId>org.rxtx</groupId>
<artifactId>rxtx</artifactId>
<version>2.1.7</version>
</dependency>
<!-- Database -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.42.0.0</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
</dependency>
<!-- JSON Processing -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

Platform-Specific Setup

Windows RXTX Setup

public class WindowsRFIDSetup {
static {
// Load RXTX native libraries for Windows
System.setProperty("java.library.path", "C:\\Program Files\\RXTX\\lib");
}
public static List<String> getAvailableCOMPorts() {
List<String> ports = new ArrayList<>();
// Windows COM ports typically COM1-COM256
for (int i = 1; i <= 256; i++) {
String portName = "COM" + i;
if (isPortAvailable(portName)) {
ports.add(portName);
}
}
return ports;
}
private static boolean isPortAvailable(String portName) {
// Check if port exists and is available
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
return true;
} catch (Exception e) {
return false;
}
}
}

Linux RXTX Setup

public class LinuxRFIDSetup {
static {
// Load RXTX native libraries for Linux
System.setProperty("java.library.path", "/usr/lib/jni");
}
public static List<String> getAvailableSerialPorts() {
List<String> ports = new ArrayList<>();
// Common Linux serial ports
String[] commonPorts = {"/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyACM0", 
"/dev/ttyS0", "/dev/ttyS1", "/dev/ttyAMA0"};
for (String port : commonPorts) {
File portFile = new File(port);
if (portFile.exists() && portFile.canRead()) {
ports.add(port);
}
}
return ports;
}
}

Security Considerations

Example 4: Secure RFID Operations

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
public class SecureRFIDOperations {
private final KeyGenerator keyGenerator;
private final Cipher cipher;
private final Mac hmac;
public SecureRFIDOperations() throws NoSuchAlgorithmException {
this.keyGenerator = KeyGenerator.getInstance("AES");
this.keyGenerator.init(128);
this.cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
this.hmac = Mac.getInstance("HmacSHA256");
}
public byte[] encryptTagData(String tagId, String sensitiveData, byte[] key) 
throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
String dataToEncrypt = tagId + "|" + sensitiveData + "|" + System.currentTimeMillis();
return cipher.doFinal(dataToEncrypt.getBytes());
} catch (InvalidKeyException e) {
throw new SecurityException("Invalid encryption key", e);
}
}
public String decryptTagData(byte[] encryptedData, byte[] key) 
throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decrypted = cipher.doFinal(encryptedData);
return new String(decrypted);
} catch (InvalidKeyException e) {
throw new SecurityException("Invalid decryption key", e);
}
}
public byte[] generateHMAC(byte[] data, byte[] key) throws InvalidKeyException {
SecretKeySpec secretKey = new SecretKeySpec(key, "HmacSHA256");
hmac.init(secretKey);
return hmac.doFinal(data);
}
public boolean verifyHMAC(byte[] data, byte[] receivedHMAC, byte[] key) 
throws InvalidKeyException {
byte[] computedHMAC = generateHMAC(data, key);
return MessageDigest.isEqual(computedHMAC, receivedHMAC);
}
public static class SecureRFIDTag {
private String tagId;
private byte[] encryptedData;
private byte[] hmac;
private long timestamp;
public SecureRFIDTag(String tagId, byte[] encryptedData, byte[] hmac) {
this.tagId = tagId;
this.encryptedData = encryptedData;
this.hmac = hmac;
this.timestamp = System.currentTimeMillis();
}
public boolean verifyIntegrity(byte[] key) {
try {
SecureRFIDOperations crypto = new SecureRFIDOperations();
return crypto.verifyHMAC(encryptedData, hmac, key);
} catch (Exception e) {
return false;
}
}
public String decryptData(byte[] key) {
try {
SecureRFIDOperations crypto = new SecureRFIDOperations();
return crypto.decryptTagData(encryptedData, key);
} catch (Exception e) {
throw new SecurityException("Failed to decrypt tag data", e);
}
}
}
}

Conclusion

Key Features Implemented

  1. Basic RFID Reading: Serial communication with RFID readers
  2. Advanced Management: Multi-reader support with event handling
  3. EPC Gen2 Protocol: UHF RFID standard implementation
  4. Data Processing: Tag filtering, validation, and business rules
  5. Security: Encryption and integrity verification
  6. Persistence: Database storage and historical tracking

Common Use Cases

  • Inventory Management: Real-time stock tracking
  • Access Control: Secure entry systems
  • Supply Chain: Package and pallet tracking
  • Asset Tracking: Equipment and tool management
  • Retail: Anti-theft and inventory systems
  • Healthcare: Patient and equipment tracking

Best Practices

  1. Error Handling: Robust exception handling for reader communication
  2. Performance: Asynchronous processing for high-volume reads
  3. Security: Implement encryption and access controls
  4. Scalability: Support for multiple readers and high tag volumes
  5. Maintenance: Reader health monitoring and automatic recovery

This comprehensive RFID implementation provides a solid foundation for building enterprise-grade RFID solutions in Java, supporting various reader types and protocols across different applications.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper