I'm road testing the Harting MICA Complete IIoT Starter Kit. In this blog series: Java! I want to talk to the BOSCH CISS sensor over USB, and - if I can get that to work - send the telemetry safely to MQTT.
I'm using the Linux Debian Stretch Container here, with a Java runtime 1.8 installed. Check here how to install the jre.
End goal:
In this post:
|
Development Environment
Because Java is cross-platform by default, and the BOSCH sensor works on Windows and Linux, I can develop on my laptop.
There are a few things to take into account to make it work on both platforms:
- parameterise the USB port name. It will be different on both systems.
- USB libraries in Windows and Linux are not compatible. The JSerialComm library luckily takes care of the platform specific dependencies.
I'm developing in the NetBeans IDE. I have a Java 1.8 JDK installed on my laptop.
This setup allows me to develop and debug on the Windows computer. I don't need the Harting MICA during that activity.
For my own peace of mind, I regularly test on the MICA though. After each major functionality change, I want to see if the program behaves on Linux.
I've ceated a NetBeans Maven project. Maven is a build tool that manages dependencies. Handy for the next step:
Dependencies
I'm usin a few java libraries to make life easy:
- USB communication: JSerialComm library
- Command line parsing: Apache CLI.
You can add the libraries to your project from NetBeans. Right-click on the Dependencies node and select Add Dependency ...
In the search button, first type CLI and add the Appache CLI lib, then enter JSerialComm and add that library too.
later, when you're deploying to the MICA, you have to move those .jar libraries over. You can right-click on them in the project to find their location on your pc.
Code
The main class - CISSBoschApp.java
package net.cumps.cissboschusb; /** * * @author jancu */ public class CISSBoschApp { public static void main(String[] args) { new Cli(args).parse(); } }
This is a very simple class. It just asks our parser to check the arguments. If all ok, the parser will kick off activities.
The command line parser - Cli.java
package net.cumps.cissboschusb; /** * * @author jancu * credit where credit due: http://www.thinkplexx.com/blog/simple-apache-commons-cli-example-java-command-line-arguments-parsing * */ import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; public class Cli { private static final Logger log = Logger.getLogger(Cli.class.getName()); private String[] args = null; private Options options = new Options(); public Cli(String[] args) { this.args = args; options.addOption("h", "help", false, "show help."); options.addOption("u", "usb", true, "USB character device to listen to (e.g., COM13, /dev/ttyACM0)"); options.addOption("b", "baud", true, "USB speed (baud, typical 115200)"); } public void parse() { CommandLineParser parser = new BasicParser(); CommandLine cmd = null; try { cmd = parser.parse(options, args); if (cmd.hasOption("h")) help(); if (cmd.hasOption("u")) { log.log(Level.INFO, "Using cli argument -usb=" + cmd.getOptionValue("u")); // Whatever you want to do with the setting goes here } else { log.log(Level.SEVERE, "Missing usb option"); help(); } if (cmd.hasOption("b")) { log.log(Level.INFO, "Using cli argument -baud=" + cmd.getOptionValue("b")); } else { log.log(Level.SEVERE, "Missing baud option"); help(); } CISSBoschUSBReader.read(cmd.getOptionValue("u"), Integer.parseInt(cmd.getOptionValue("b"))); } catch (ParseException e) { log.log(Level.SEVERE, "Failed to parse comand line properties", e); help(); } } private void help() { // This prints out some help HelpFormatter formater = new HelpFormatter(); formater.printHelp("Main", options); System.exit(0); } }
The USB handler - CISSBoschUSBReader.java
package net.cumps.cissboschusb; import com.fazecast.jSerialComm.SerialPort; import com.fazecast.jSerialComm.SerialPortDataListener; import com.fazecast.jSerialComm.SerialPortEvent; import java.util.logging.Logger; /** * * @author jancu */ public class CISSBoschUSBReader { private static final Logger log = Logger.getLogger(Cli.class.getName()); public static void read(String cDevice, int iBaud) { SerialPort comPort = SerialPort.getCommPort(cDevice); comPort.setBaudRate(iBaud); if (comPort.openPort()) { comPort.addDataListener(new SerialPortDataListener() { @Override public int getListeningEvents() { return SerialPort.LISTENING_EVENT_DATA_AVAILABLE; } @Override public void serialEvent(SerialPortEvent event) { if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) { return; } byte[] newData = new byte[comPort.bytesAvailable()]; int numRead = comPort.readBytes(newData, newData.length); System.out.println("Read " + numRead + " bytes."); } }); } } }
Debug on Windows
In NetBeans, define the command line parameters via Run -> Set Project Configuration -> Customize ...
Build the project by pressing the Build button.
Set a breakpoint in CISSBoschUSBReader.java, on this line:
SerialPort comPort = SerialPort.getCommPort(cDevice);
Then start the debugger. When it breaks, check the value of the usb port and speed.
If that is ok, you can continue running the program, or step through it if you want.
Test on Linux
Create a /root/java directory in Linux
Copy the two .jar files of the dependencies to that folder with winSCP. (install openssh-server if needed).
Copy the project's jar file t the same folder (it's found in the target folder of your project.
You should see this when you execute ls -l:
-rw-r--r-- 1 root root 5994 May 2 21:00 CISSBoschUSB-1.0-SNAPSHOT.jar -rw-r--r-- 1 root root 53820 May 2 12:54 commons-cli-1.4.jar -rw-r--r-- 1 root root 372375 May 2 20:14 jSerialComm-2.5.0.jar
Java files don't need the executable flag. It's the jre that needs to be executable, not the libs.
Now test your code:
java -cp ./CISSBoschUSB-1.0-SNAPSHOT.jar:./commons-cli-1.4.jar:jSerialComm-2.5.0.jar net.cumps.cissboschusb.CISSBoschApp -usb "/dev/ttyACM0" -baud 115200
If you have the CISSGateway container active, the program will exit with an error, because the gateway runs away with our data .
If the gateway was inactive before you started the MICA, then the program will sit there and show nothing.
That is good, because the BOSCH CISS sensor hasn't been initialised. That's for a next post.
Top Comments