Java usb4java reading from usb device on windows 10 platform - java

I am trying to read a message from RFID reader connected via USB to windows 10pro machine with usb4java library.
I have managed to claim the interface, opened pipe and registered listener for the data, however the listener is never triggered. The reader acts as keyboard and whatever it reads ends up in active application, such as IDE i have open, instead of in listener.
UsbInterface usbInterface = activeInteface(device);
// there is only one endpoint in the list
UsbEndpoint endpoint = (UsbEndpoint)usbInterface.getUsbEndpoints().get(0);
UsbPipe pipe = endpoint.getUsbPipe();
try {
usbInterface.claim();
// true
System.out.println("claimed usb interface: " + usbInterface.isClaimed());
pipe.open();
// true
System.out.println("pipe open: " + pipe.isOpen());
pipe.addUsbPipeListener(new MessageListener());
// true
System.out.println("pipe active: " + pipe.isActive());
// keep main thread alive, async call should be done from another thread i guess
Thread.sleep(15000);
}
catch (Exception any) {System.out.println(any);}
}
And the listener:
private static class MessageListener implements UsbPipeListener {
#Override
public void errorEventOccurred(UsbPipeErrorEvent event) {
System.out.println(event.toString() + " , " +event.getUsbException());
}
#Override
public void dataEventOccurred(UsbPipeDataEvent event) {
// this code block never triggers
System.out.println("listener ...);
int actualLength = event.getActualLength();
System.out.println("length: " + actualLength);
byte[] data = event.getData();
System.out.println("data length " + data.length);
}
}
i have also tried synchronous read instead of asynchronous in the block above, like this:
byte[] buffer = new data[8];
// this fails on its own, don't even need to read something with RFID reader
int received = pipe.syncSubmit(buffer);
fails with:
USB error1: Transfer error on interrupt endpoint: Input/Output error
There is some windows specific property that library supports: org.usb4java.javax.useUSBDK = true
but this fails when i try to set it with an exception.
I have 0 experience with USB devices so not sure how to proceed from here. Is there something wrong with the code, do i need USBDK or device does not support libUSB driver ? Sadly this is not my device and i don't have access to documentation of the device so cannot be sure if it is device driver issue.

I know that this is 2 years old, but i've had similar issue and this was one of the first questions that i ran into looking for solution, which took me hours.
So, basically, windows doesn't let to read/write keyboard devices directly, to do so, you have to override it's driver (That's why you're getting Input/Output error, and it's written in the hid4java's FAQ).
First way to override device driver is described in libusb wiki.
As far as i know you would have to install a new driver every time you connect the device to a new USB port, which is why i recommend you to read further.
Second way is what you've already mentioned, which is using UsbDk (Usb Drivers Development Kit for Windows). It makes the device accessible for you by detaching the kernel driver and reattaching it back after you're done playing with it.
In order to use it, you need to do two things:
Set the org.usb4java.javax.useUSBDK = true in you javax.usb.properties file as stated in the manual (this can also be done manually in low-level usb4java, see OPTION_USE_USBDK and setOption(Context, int)).
Download and install UsbDk on your system (simplest way is to download x64 or x86 version msi installer which has GUI and is fully automated), which is sadly not in the manual (maybe it's obvious for some people, but took me amount of time that i am not proud of to realize).
Im guessing that the lack of second step is why OP has been getting an exception.
Hope that this will help someone, knowing all this two days ago would save me a lot of headache.

RFID readers operate in keyboard emulation mode by default.
You can normally get a tool from the manufacturer's website to configure the RFID reader.
This will allow you to change the reader to HID mode.
This should resolve your issues.
Sorry for the late response but I hope it helps others.

Related

Android show no output from Inputstream reader and Procees return exit code 1

i am trying to run a process and to read it's data from InputStreamReader, but it fails in a weird way.
The executable is "ip neigh show"
When trying to run the command from connected device via adb shell the command executes OK and also displays data correctly.
But when trying to execute it from kotlin code it exit with exit code 1 and InputStreamReader show empty data also.
This is how i am trying it :
val p = Runtime.getRuntime().exec("ip neigh show")
InputStreamReader(p!!.inputStream).forEachLine fori#{ line ->
val teDhenat = line.split("\\s+".toRegex())
if (teDhenat[0] == ip) {
if (teDhenat.size < 4) {
return#fori
} else {
uGjet = true
macAddress = teDhenat[4]
return#fori
}
}
}
The problem seems to happen in that line : val p = Runtime.getRuntime().exec("ip neigh show") but i don't understand why.
Also tried with val p = Runtime.getRuntime().exec("/system/bin/ip neigh show") and it's still the same.
Also i have tried using ProcessBuilder() and it doesn't work too.
The Compile and Target SDK is 31
The phone is Xiaomi running Android 11 (SDK 30)
PS: Also i am using same logic for other executables and they work very fine like "ping", "top" etc...
Since Android 11 (SDK 30) :
In addition, non-privileged apps can't access the device’s MAC
address; only network interfaces with an IP address are visible. This
impacts the getifaddrs() and NetworkInterface.getHardwareAddress()
methods, as well as sending RTM_GETLINK Netlink messages.
The following is a list of the ways that apps are affected by this
change:
NetworkInterface.getHardwareAddress() returns null for every
interface.
Apps cannot use the bind() function on NETLINK_ROUTE
sockets.
The ip command does not return information about interfaces.
Apps cannot send RTM_GETLINK messages. Note that most developers
should use the higher-level APIs of ConnectivityManager rather than
lower-level APIs like NetworkInterface, getifaddrs(), or Netlink
sockets. For example, an app that needs up-to-date information on the
current routes can get this information by listening for network
changes using ConnectivityManager.registerNetworkCallback() and
calling the network's associated LinkProperties.getRoutes().

How to properly handle IOException with NFCA.transceive?

I'm a beginner with Android developement and I'm trying to configure a "pass-through" mode for NFC. Basically I2C writes something on an NFC TAG, Mobile Phone picks it up, new data is written by I2C and so on. I kind of struggle with the time the tag is written: Meanwhile, the phone gets an "NAK" and throws back an IOException since transceive fails. How can I properly handle it? I tried with "thread.millis" to wait till I2C is done, but this solution looks pretty crappy and only works with my arduino and phone.
while (Schleife < 1000) {
try {
answer = ultralight.transceive(command); //This one throws an IOException if the data is not ready yet
Schleife = Schleife + 1;
} catch (IOException ioe) {
//Log.e("UnsupportedEncoding", ioe.toString());
}
}
I want the program to re execute the process. One thing I tried was to include the catch statement into the while-loop, but it took forever sometimes to rerun the while loop.
I'm thankful for every answer.
Kind regards
My reading of the datasheet for the chip is that you are looping around transceiving the wrong command.
After a READ or FAST_READ command involving the terminator page of the SRAM, bit SRAM_RF_READY and bit RF_LOCKED are automatically reset to 0b allowing the I2C interface to further write data into the SRAM buffer.To signal to the host that further data is ready to be written, the following mechanisms are in place:•The NFC interface polls/reads the bit SRAM_RF_READY from NS_REG (see Table14) to know if new data has been written by the I2C interface in the SRAM
You loop should be read E8h block and checking the to see if the SRAM is ready to be read by the RF connection, then read 64 bytes with fast read when the right bits are set in byte 0
This is how the chip implements a flow control mechanism between the I2C interface and the RF interface to prevent errors.
update
Ok the implementation sheet shows how to do it without flow control.
For the question how to handle a NACK, first you need to check for it
Below is how I check for a NACK
if ((answer != null) && (answer.length == 1) && ((answer[0] & 0x00A) != 0x00A)) {
// Got NACK
Log.e("Nack", Schleife); //added to identify iteration.
}
It would be helpful to also log the iteration number of any IOException
I'm thinking that the NACK and IO exception are on different iterations.
As a proper NACK is not an IO Exception.
Also Android code the anticollision under the hood, so the only thing you can try when receiving the NACK is close and connect again.
or
A low level transeive to "0x95 0x70 (UID bytes)" be correct
(taken from https://android.googlesource.com/kernel/common/+/android-3.18/net/nfc/digital_technology.c#349 )
"0x95 0x70" I think is the correct Anti-collison command for the card type.

Modbus4J Modbus RTU master

Currently I am working with the Schneider Power Logic electrical device. I want to read the data from the device and show the value in my system. So far, I discover J2mod, Jamod and Modbus4Java library. I used all modbus4java to connect and get the device's data.
Actually I still confuse whether I suppose to create Master side or Slave side. Based on my understanding, the device will be Slave and my system will be Master (1st question).
Below is the setting AT MY DEVICE. It indicate that the device in slave mode and its protocol is Modbus RTU. So, I need to create a master apps to communicate with it right which is using the ModbusRTU protocol right ? (2nd question)
Mode: Slave
Protocol: Modbus RTU
Address: 1
Baud Rate: 38400
Parity: None
Below is the code of my apps act as the Master and using the ModbusRTU protocol
public static void main(String[] args) throws ModbusTransportException, ErrorResponseException {
ModbusFactory factory = new ModbusFactory();
SerialParameters params = new SerialParameters();
params.setCommPortId("COM6");
params.setBaudRate(9600);
params.setDataBits(8);
params.setStopBits(1);
params.setParity(0);
ModbusMaster master = factory.createRtuMaster(params);
master.setTimeout(1000);
master.setRetries(0);
long start = System.currentTimeMillis();
try {
master.init();
} catch (Exception e) {
System.out.println( "Modbus Master Init Error: " + e.getMessage());
return;
}
try {
System.out.println("Reg. 1001 Value:" + master.getValue(1, RegisterRange.HOLDING_REGISTER, 3110, DataType.FOUR_BYTE_FLOAT_SWAPPED));
}
finally {
master.destroy();
}
System.out.println("Time elapsed: " + (System.currentTimeMillis() - start) + "ms");
}
This is the code that I get from the sample code provide by the Modbus4Java page. The other thing that concern me is the value of params.setCommPortId("COM6"); What other value than "COM6" that I can put there. Because basically it receive a String value. So am I able to put any String value to it ? And what is the function of this particular setCommPortID. (3rd question)
Looking at the sample code provide by the Modbus4Java page, it does not put the IP address of the device. But in my case, my device got an IP address. And the IP address only use in the Slave apps only. How should my system recognize the IP address of the device ? (4th question).
And after I run this code snippet, I got an error:
Stable Library
Native lib Version = RXTX-2.1-7
Java lib Version = RXTX-2.1-7
Modbus Master Init Error: com.serotonin.io.serial.SerialPortException: gnu.io.NoSuchPortException
Please, please and please help me. I been stuck with this almost a month. Really hope someone out there will be able to help me. Thank you in advance for any kind of help and suggestion.
I'm the maintainer for j2mod, so my answer is going to suggest you look at the test programs which are included with j2mod. You can find j2mod on SourceForge at this URL --
https://sourceforge.net/projects/j2mod/
I'm pretty good about answering questions there, but I also follow stackoverflow, so I can explain more here as well. There are a LOT of questions in here, so I apologize in advance if I've missed anything.
The Schneider device is the slave, or "server" and your application is the master or "client". Modbus is a master/slave protocol, with the master initiating all requests. Your application will be the master and responsible for making all requests of your device.
The exact communications will be provided by the device documentation. In this instance, you indicate that the device uses 38400 baud, and so forth. Those are the parameters you will use to update SerialParameters with the RXTX library (which just so happens to also be used by j2mod).
The value passed to setCommPortId() is the Windows COM port identifier - you should be able to pass any value which is associated with an actual COM port -- "COM1", "COM2", etc. Note that some USB converters change their COM port each time they are used, so you may be chasing port names.
You mentioned that your device also has an IP address. You cannot use the RTU classes and methods to access a Modbus/TCP device. The same is true for jamod and j2mod - most Modbus libraries have different classes for RTU and TCP transports (as well as ASCII and UDP, for libraries which support those other transports).

ELM327 returns `?` when trying to use it with ODB Java API

I'm trying to use ODB Java API (this library) to get the data from ELM327 via Bluetooth from my car, but in returns ? on every request, and library raises MisunderstoodException
Here is my code:
socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
socket.connect();
final CustomRPMCommand engineRpmCommand = new CustomRPMCommand();
final SpeedObdCommand speedObdCommand = new SpeedObdCommand();
while (!Thread.currentThread().isInterrupted()) {
engineRpmCommand.run(socket.getInputStream(), socket.getOutputStream());
speedObdCommand.run(socket.getInputStream(), socket.getOutputStream());
runOnUiThread(new Runnable() {
#Override
public void run() {
speedometerGauge.setSpeed(engineRpmCommand.getRPM(), true);
rpmGauge.setSpeed(speedObdCommand.getMetricSpeed(), true);
}
});
}
What's wrong?
I also used the same library for the first steps into trying out OBD, so I can say at least at the time I used it, it worked fine.
From my experience however, getting ? back can sometimes happen with cheap Bluetooth devices (maybe even with expensive ones? never had one). I guess this happens, if some bits are lost during the transmission, because then command will be misunderstood.
What I did to circumvent this problem is setting up a process where I sent all AT commands up to 10 times until I get the desired response of OK (except for ATZ, which will respond with ELM327). As for value requests like RPM etc. I usually just throw away the erroneous values.
That's the short answer, but since such problems with the devices can annoy a lot, I will guide you into debugging the whole process...
Setting up a terminal on windows
First of all to test the functionality of the ELM device, you can send commands to the serial interface directly. On windows, this is possible using for example TeraTerm and then setting up new Bluetooth connection on your windows as a COM device (search for Bluetooth in start -> search box and then choose Change Bluetooth settings or similar). From there, go to COM connections and then add a new one Outgoing for the Bluetooth OBDII device. Wait a bit for windows to calculate the new COM port number, you will need it.
If you cannot find OBDII in the dropdown box, you have to bond your PC with your Bluetooth device first. This can be done via devices and printers, there you should see the OBDII device, so you only have to connect it (PIN usually is 1234).
If you're on Linux, it might be somewhat easier, but I haven't done it :)
Sending some commands via terminal
Once you have your Bluetooth connection and TeraTerm installed, you can start TeraTerm and connect to the adapter. Choose Serial and then the port you just set up. Ensure, that no other device is connected to the OBD adapter (also not your phone). Only one device can be connected at a time.
If connection was successful, you should be able to type letters. Usually, in default settings you should be able to see the letters you type (Echo mode on), but since this is not certain, just type ATZ and hit <Enter>. The ELM should respond with "ELM327" in the same line now (which for me usually results in odd display if echo mode was on, but you should get any response).
From terminal I usually send these commands in order:
ATZ
E1
L1
010c
This will trigger:
Reset of the OBD device
Make sure that echo is on, so I see what I am typing
Make sure Line feed is on, so we get responses in the next line
Request RPM from the vehicle
Between each command I'll check what is the reply of the device. For all AT commands (1., 2. and 3.) it must be OK. If I get back ?, which can happen, I will repeat the command another time. You will see that in such a case the device indeed did not follow the instructions, e.g. did not set line feed on if it was off. So we really have to send it again.
In programming mode on the other hand, we will set e0 and l0 (echo mode off and line feed off), because we do not want to get sent back what we already sent out.

Java URLConnection crashes the entire process when I call getInputStream

I am writing a Java applet that downloads images from a web server and displays them to the user. It works fine in Java 1.6.0_3 and later, but on older versions it will completely crash the process about once every 20 page views. There are no error messages in the Java console, because the process is completely frozen. I've waited for almost 15 minutes sometimes, but it never un-freezes.
I added a debug message after every line of code, and determined that the line that is causing the crash is this: InputStream data = urlConn.getInputStream().
urlConn is a URLConnection object that is pointed at the image I want to load. I've tried every combination of options that I can think of, but nothing helps. I haven't been able to find anything in the Java bug database or the release notes for 1.6.0_3.
Has anyone encountered this problem before? Any idea how to fix it?
To determine if it really is the whole JVM process that's frozen, or something else:
(1) get a java stack dump (sigquit/ctrl-break/jstack)
(2) have another background thread doing something you can observe; does it stop?
(3) check if another process (browser/etc) can contact server during freeze? (There's a chance the real problem is server connection depletion)
Is it randomly once-in-every-20-fetches (for example, 5% of the time, sometimes the first fetch in the JVM run), or always after about 20 fetches? If the latter, it sounds like something isn't being closed properly.
If on Linux you can use 'netstat -t' or 'lsof' (with certain options or grepped to show only some lines) to see open sockets; if after each fetch, one more is open, and the count never goes down, you're not closing things properly.
If so, calling close() on the stream you get back and/or disconnect() on the HttpUrlConnection after each try may help. (There may also be more severe limits on the number of connections an applet can leave open, so you're hitting this more quickly than you would in a standalone app.)
The fact that it 'works' in later Javas is also suggestive that some sort of automatic cleanup might be happening more effectively/regularly by finalization/GC. It's best to close things up cleanly yourself but you could also try forcing a GC/runFinalization in the earlier Javas showing the problem.
I'm unsure the cause of the problem you are facing, but I use the following code successfully for synchronously loading images from within applets (loads from either jar file or the server):
public Image loadImage(String imageName) {
// get the image
Image image = getImage(getCodeBase(), imageName);
// wait for it to fully load
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(image, 0);
boolean interrupted = false;
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
interrupted = true;
}
int status = tracker.statusID(thisImageTrackerID, false);
if (status != MediaTracker.COMPLETE) {
throw new RuntimeException("Failed to load " + imageName + ", interrupted:" + interrupted + ", status:" + status);
}
return image;
}

Categories