JavaEE, JavaFX and RFID - Part 2: Reading RFID from Java
source link: http://fxapps.blogspot.com/2014/08/javaee-javafx-and-rfid-part-2-reading.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Part 1: The Application
Part 2: Reading RFID from Java
Part 3: REST API and Security
Part 4: The Client
The RFID reader
RFID is simply an identification that will be read using a Radio Frequency. The ID is in RFID tags which can be read using a RFID Reader. My purpose is only read the tag, so we won't go deep in the writing part, we will focus on reading a RFID tag.I used the simplest RFID Reader I could find since I was avoiding unnecessary trouble. The reader is connected by USB and we just have to connect it to a PC so we can start hearing the buzz when we approach a RFID tag to the reader.
Notice that the reader and the tags have some conditions such as frequency of operation. I won't go deep on these details on this post.
The reader I bought is integrated with the FTDI chip and it has total support for installation in the popular operating systems we have. Notice that the main duty of this chip was to interface the old RS232 interface with USB, so we need a driver.
Installing the library(driver)
Initially I found some issues to install the driver so I can perform the communication with the chip and simply read the incoming data. In another scenarios, it's usual to also write data, but today we will only read.First thing I did was to download the driver on D2XX web page, then I followed the instructions on the installation guide for linux, which was basically was run the following commands:
sudo cp /releases/build/arch/lib* /usr/local/lib
cd /usr/local/lib
sudo ln –s libftd2xx.so.1.1.12
libftd2xx.so
sudo chmod 0755 libftd2xx.so.1.1.12
* arch is the architecture of my operating system.
After this, I could see that a new directory was created under /dev when I connected my RFID reader using the USB cable: So I opened the file(well, actually a symlink) under serial/by-id directory and I was able to read the content of my RFID when I approached the RFID tag to the reader: After setting native stuff, it was time to find a way to read it from Java!
Reading FTDI from Java
In D2XX page we can find two libraries to read it from Java, however, I tried to use these and I had issues. The main issue was related to the native part and, as I said, I didn't want to waste time on this...Well, everything is a file in Linux, remember we were reading data using cat command. Why not read the content of that file from Java? Having this in mind, I created a simple program to read the content of that file, see the code:
package org.jugvale.rfid;
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import java.util.List; import java.util.Scanner; import java.util.stream.Collectors;
/** * Will read the file created by FTDI when a compatible chip is connected to a * Linux machine using the USB port * * @author william * */ public class LinuxFTDISerialReader { private static final String DEFAULT_DEVICE_BASE_PATH = "/dev/serial/by-id"; private String deviceBasePath; public static final String DEFAULT_ERROR_MESSAGE = "Device not found. Check if a device is connected, the driver FTDI was correctly installed and if the device base Path is right(default is " + DEFAULT_DEVICE_BASE_PATH + ")";
public LinuxFTDISerialReader() { deviceBasePath = DEFAULT_DEVICE_BASE_PATH; }
public LinuxFTDISerialReader(String deviceBasePath) { this.deviceBasePath = deviceBasePath; }
public List<Path> getAvailableDevices() throws IOException { List<Path> deviceList = Collections.emptyList(); try { deviceList = Files.list(Paths.get(deviceBasePath)).collect( Collectors.toList()); } catch (Exception e) { e.printStackTrace(); throw new IOException(DEFAULT_ERROR_MESSAGE, e); } return deviceList; }
/** * Will lock the thread reading the device. Should be executed in a * separated thread! * * @param device * @return * @throws IOException */ public String waitAndRead(Path device) throws IOException { if (device == null || !Files.exists(device)) { throw new IOException("Device should not be null!"); } Scanner scanner = new Scanner(device); String rfid = null; while (scanner.hasNextLine()) { rfid = scanner.nextLine(); if (rfid != null && !rfid.trim().isEmpty()) break; } scanner.close(); return rfid.substring(1); } }
A reader from JavaFX
package org.jugvale.rfid.ui;
import java.io.IOException; import java.nio.file.Path; import java.util.concurrent.ExecutionException; import java.util.function.Consumer;
import javafx.concurrent.Task; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.control.TitledPane; import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane;
import org.jugvale.rfid.LinuxFTDISerialReader;
/** * @author william * */ public class FTDIReaderPane extends TitledPane {
LinuxFTDISerialReader reader = new LinuxFTDISerialReader(); ListView<Path> listDevices; /** * To be invoked when we read the RFID */ Consumer<String> onRead; Consumer<String> onError;
private Path selectedDevice;
public FTDIReaderPane() { this(null, null); } public FTDIReaderPane(Consumer<String> onRead, Consumer<String> onError) { super(); this.onRead = onRead; this.onError = onError; settings(); initComponent(); }
public void setOnRead(Consumer<String> onRead) { this.onRead = onRead; }
public void setOnError(Consumer<String> onError) { this.onError = onError; }
/** * * Will show up and read a RFID tag, but it will always ask to select a tag * * @throws IOException * Error when it can't read the device */ public void askForDeviceAndReadTag() { try { if (selectedDevice == null) fillDevices(); else { readDevice(); } setVisible(true); } catch (Exception e) { e.printStackTrace(); fail(LinuxFTDISerialReader.DEFAULT_ERROR_MESSAGE); } }
private void settings() { setText("Read RFID Tag"); setMaxHeight(200); setMaxWidth(300); setStyle("-fx-stroke-width: 20;"); setCollapsible(false); setVisible(false); }
private void initComponent() { StackPane root = new StackPane(); Label lblPassCard = new Label("Pass RFID Card"); lblPassCard.setStyle("-fx-font-size: 20px; -fx-font-weight: bold"); listDevices = new ListView<>(); listDevices.setOnMouseReleased(this::newDeviceSelectedAction); root.getChildren().addAll(listDevices, lblPassCard); lblPassCard.visibleProperty().bind(listDevices.visibleProperty().not()); this.setContent(root); }
private void newDeviceSelectedAction(MouseEvent e) { Path selectedPath = listDevices.getSelectionModel().getSelectedItem(); if (selectedPath != null) { listDevices.setVisible(false); listDevices.getSelectionModel().clearSelection(); selectedDevice = selectedPath; readDevice(); return; } }
private void fillDevices() throws IOException { listDevices.setVisible(true); listDevices.getItems().setAll(reader.getAvailableDevices()); listDevices.getSelectionModel().clearSelection(); }
private void readDevice() { new Thread(new Task<String>() { @Override protected String call() throws Exception { return reader.waitAndRead(selectedDevice); }
@Override protected void succeeded() { try { success(this.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } setVisible(false); }
@Override protected void failed() { fail(LinuxFTDISerialReader.DEFAULT_ERROR_MESSAGE); setVisible(false); selectedDevice = null; } }).start(); } private void success(String value) { if(onRead == null) { throw new Error("You must set an onRead funcion"); } onRead.accept(value); } private void fail(String value) { if(onError == null) { throw new Error("You must set an onError funcion"); } onError.accept(value); } }
Conclusion
Read RFID from Java is not a hard task on Linux. It could be, however, simpler if we had a library to make the operations for us.
Source Code on github
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK