NeuronRobotics / nrjavaserial

A Java Serial Port system. This is a fork of the RXTX project that uses in jar loading of the native code.
Other
344 stars 143 forks source link

RFC2217 ports cannot be opened #176

Closed RafalLukawiecki closed 4 years ago

RafalLukawiecki commented 4 years ago

Based on several discussions here and here, I suspect that nrjavaserial does not attempt to open RFC2217 ports at the moment. Sincere apologies if I misunderstood how nrjavaserial works, I only have an extremely basic view of it and I am not a Java developer.

From my looking at it, it seems that opening RFC2217 ports is handled by the factory in RFC2217PortCreator.java. However, even if I pass an rfc2217 URI as the port to open, ie.

String port = "rfc2217://192.168.40.180:2001";
NRSerialPort serial = new NRSerialPort(port, baudRate);

it seems that NRSerialPort constructor will call RxTxPortCreator.createPort instead of first checking if the port is an RFC2217 URI. I can see a call is being made to it from this call stack:

java.lang.ExceptionInInitializerError thrown while loading gnu.io.RXTXCommDriver
java.lang.NoClassDefFoundError: Could not initialize class gnu.io.RXTXCommDriver thrown while loading gnu.io.RXTXCommDriver
Failed to connect on port: rfc2217://192.168.40.180:2001 exception:
gnu.io.NoSuchPortException
        at gnu.io.CommPortIdentifier.getPortIdentifier(CommPortIdentifier.java:273)
        at gnu.io.factory.RxTxPortCreator.createPort(RxTxPortCreator.java:35)
        at gnu.io.NRSerialPort.connect(NRSerialPort.java:99)

It looks like some logic is missing that figures out that the port to open is the RFC2217 one.

RafalLukawiecki commented 4 years ago

I just noticed a commit from you https://github.com/NeuronRobotics/nrjavaserial/commit/61746b78aa65e2fa638515b5b94929afb2fa0374 !

madhephaestus commented 4 years ago

Resolved in 61746b78aa65e2fa638515b5b94929afb2fa0374

RafalLukawiecki commented 4 years ago

I will test right now.

RafalLukawiecki commented 4 years ago

I can see your new code is correctly identifying the port as rfc2217 now, but it does not manage to createPort because of a missing class org.apache.commons.net.telnet.TelnetInputListener

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/net/telnet/TelnetInputListener
        at gnu.io.factory.RFC2217PortCreator.createPort(RFC2217PortCreator.java:38)
        at gnu.io.NRSerialPort.connect(NRSerialPort.java:104)
        at net.rafal.App.main(App.java:21)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.net.telnet.TelnetInputListener
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        ... 3 more

I can see it is being imported in TelnetSerialPort.java and a couple of other places, but perhaps it is not in the dependencies of the project? I don't know how to add this dependency to build.gradle, but if you do, I will be happy to retest.

Many thanks for your help.

RafalLukawiecki commented 4 years ago

Perhaps the issue is in my testing. Trying to figure out how to get the Apache commons-net libraries locally here.

RafalLukawiecki commented 4 years ago

Well, I have managed to get the commons-net onto my machine by cloning from GH, compiling and then copying into the test app's build/classes, which is also how I have been testing nrjavaserial in this app: by copying its built classes into the test app. Unfortunately, I do not have the knowledge how to overcome this:

Exception in thread "main" java.lang.ExceptionInInitializerError
        at gnu.io.rfc2217.TelnetSerialPort.<init>(TelnetSerialPort.java:225)
        at gnu.io.factory.RFC2217PortCreator.createPort(RFC2217PortCreator.java:39)
        at gnu.io.NRSerialPort.connect(NRSerialPort.java:103)
        at net.rafal.App.main(App.java:21)
Caused by: java.lang.RuntimeException: can't find resource /jvser.properties
        at gnu.io.rfc2217.Version.<clinit>(Version.java:79)
        ... 4 more

I realise that I have no clue how to put together all those dependencies into my little test app, so I have no choice but to give up. Maven is too much for me, and I have now invested more than a day not moving forward—frustrating, but Java is not my future.

What I am missing is how to get my app to find all of the dependencies inside nrjavaserial. I suppose what I was hoping to do is to get the two jars together and call java something and it would run. :(

RafalLukawiecki commented 4 years ago

PS. What is the right syntax, or what do I need to do, to be able to run the test app against your jar? I suppose if I get past that point I will know if rfc2217 works, at last, or not.

java -cp ~/nrjavaserial/build/libs/nrjavaserial-5.1.1.jar -jar target/nrjavaserialfreebsdtest-1.0-SNAPSHOT.jar
Hello World!
Exception in thread "main" java.lang.NoClassDefFoundError: gnu/io/NRSerialPort
        at net.rafal.App.main(App.java:20)
Caused by: java.lang.ClassNotFoundException: gnu.io.NRSerialPort
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        ... 1 more
madhephaestus commented 4 years ago

you are missing Gradle!

Ok, so you are basically bypassing the build tool and trying to do it all by hand? Not a good idea.

Gradle is to Java what Make is to C.

It is stand alone and should run so long as your JAVA_HOME environment variable is set.

To build, in bash:

./gradlew jar

and it will compile a jar and put it in build/libs/

To run all the unit test in test/src/

./gradlew test

I just pushed a template unit test for you to copy if you want to add your own unit tests as you go.

RafalLukawiecki commented 4 years ago

Yes, I have a feeling that gradle could be the thing—Maven is not for the faint-hearted, it seems. Thank you for the unit test, and thank you for understanding my frustration. Hopefully I will bring back good news shortly.

madhephaestus commented 4 years ago

Maven is a system protocol, designed for machine parsing, not hand parsing. It is all handled automatically by the gradle script.

RafalLukawiecki commented 4 years ago

Thank you again, @madhephaestus, for your support. I can confirm that nrjavaserial now connects over RFC2217. I was not able to get any data through it, however, because for that I need to run it inside openhab, which I plan on doing as soon as this new version is on Maven—it is easier for me to rebuild OH that way than to figure out how to make things work locally.

One thing I have noticed is that if the port specification is incorrect, the NRSerialPort constructor hangs waiting. I suppose this may be the right behaviour, as, I hope, it is waiting for a connection. I will know more when it is in OH.

Do you need me to recompile anything again for FreeBSD? I suppose not, unless you have also changed any of the native library code.

I have also rerun tests using a non-rfc2217 test. I will report that on the other thread, #175