Read String from Arduino serial port with JAVA and jssc lib - java

String Serial_Input must contain a serial number card RFID (MIFARE) like this A45F45A7 (8 byte). sometimes when I approach the card to the RFID reader of arduino the string is like this A45F45 (truncated) , miss any char. there is a solution better that while loop ? (more elegant and efficient) Using Arduino IDE Serial Monitor the card's serial number is correct.
public static void connectionToCom(SerialPort serialPort, ComboBox<String> cbxComPort, TextArea txaMessages) throws SerialPortException
{
int baudrate = 9600; int databits = 8; int stopbits = 1; int parity = 0;
serialPort.openPort() ;
serialPort.setParams(baudrate, databits, stopbits, parity) ;
String Serial_Input = null;
try {
while (true)
{
if (serialPort.readString() != null)
{
Serial_Input = serialPort.readString(8);
System.out.println("Card Serial: " + Serial_Input + "\n");
//serialPort.closePort();
}
}
}
catch (SerialPortException ex){
txaMessages.appendText(ex.toString());
}
}
Here the result image

You could use the method addEventListener(SerialPortEventListener listener, int mask). It call a callback method whenever you receive a byte via serialPort.
The problem with the incomplete string could be 2 problems
The code is executing before the whole string is received. To solve this, you must add a code to verify the length of string you are receiving.
You are using readString twice. You may lost some bytes of the string in first usage.

Related

using JSSC to read from a serial port. How do I use inputstream

I am using JSSC to communicate with a serialport.
The data comes in 1 byte at a time. New string is started by carriage return/newline.
The string length is variable. (82 characters max)
Each string begins with #.
As the data comes in 1 byte at a time, I have to assemble the string. I tried using a bufferedreader and inputstreamreader from a RXTX example, but I was unsuccessful.
So my question is, how do I assemble the string byte by byte and refresh the string on ?
I need it to be 1 string at a time as it will be parsed.
I have tried googling various things:
"jssc inputreader bufferedreader example"
"jssc inputreader serialPort.readString()"
etc.
//Array list declaration
static List<String> datat = new ArrayList<String>();
...
...
public void serialEvent(SerialPortEvent event) {
try {
String getdata = serialPort.readString(event.getEventValue());
//System.out.print(getdata);
String[] parts= getdata.split("\\r");
if(!datat.isEmpty()){
datat.set(datat.size() - 1, datat.get(datat.size() - 1) + parts[0]);
}
for (int i=1; i<parts.length; i++) {
if (parts[i].contains("\n")) {
if(!datat.isEmpty()) {
datat.clear();
System.out.println("data cleared");
}
} else if (!parts[i].equals("\\r") | !parts[i].equals("\\n")) {
datat.add(parts[i]);
System.out.println(datat);
}
}
}
catch (SerialPortException ex) {
}
}
}
Declare an arraylist
Receive byte from serial port. If byte received is not new line add to arraylist otherwise convert arraylist into byte array
These steps needs to be done in a while loop

When sending integer through PrintWriter from server to client, no parsing is possible

I am programming a little server-client-programm, which sends a text from one client who is writing on a file, to the other clients with the same filename, and got the following error
But I am just sending an integer and no other characters...
Here's the code:
Server
String[] splitter = scanText.split("\n");
String length = splitter.length + "";
//sending scanText to clients
for (PrintWriter pw2 : userMap.get(filename) ) {
if(!pw2.equals(pw))
{
pw2.println(length + "\n" + scanText);
}
}
Client
class "UpdateInBackground" is a class which is in the Client-class
class UpdateInBackground extends Thread {
#Override
public void run() {
int lines; //to know how much lines are send from the server
String scanText;
while (!this.isInterrupted()) {
scanText = "";
lines = Integer.parseInt(sc.nextLine()); //here I get the error
while (lines-- > 0) {
scanText += sc.nextLine() + "\n";
}
output.setText(scanText);
}
}
}
#asparagus, please define sc in line sc.nextLine(), considering this is an object from class Scanner, I need to know the input. The question must be self explainable with the definitions of variables and what are the inputs.
In Class UpdateInBackground,
lines = Integer.parseInt(sc.nextLine());// here nextLine() is for any String , please refer documentation
Reason for NumberFormatException : You are converting the value to int, without knowing, what is getting as input.
Try to use exception handling, to know what types of errors, might just come, to avoid the program getting struck.

Parse serial input[UART] on ioio board from an arduino TX output

I'm trying to have an Arduino UNO send values to a IOIO board (https://github.com/ytai/ioio/wiki/UART) over UART. As someone turns a rotary encoder, I want it to send a 0 for CW, 1 for CCW, and 2 for a press. Everything checks out in the Serial Monitor from the Arduino, but I don't know how to read the values and parse them on the Java-end correctly. It all comes through as seemingly random numbers, sometimes occasionally the correct number is there.
I've tried both of these methods on the Arduino side:
Serial.write(1);
byte data[] = {1};
Serial.write(data, 1);
Also Serial.write automatically writes to pin 1, so theres no need to create a SoftwareSerial object.
When reading this on the Java side, I just get mostly 255, occasionally the correct number, and occasionally a random number in between 0 and 255:
#Override
public void connect() throws ConnectionLostException {
try{
// rx pin = 6
mUart = ioio_.openUart(RX_PIN, IOIO.INVALID_PIN, 9600, Parity.NONE, StopBits.ONE);
mInput = mUart.getInputStream();
}
catch(ConnectionLostException e){
Log.e(TAG, "connection lost:" + e.getMessage());
ioio_.disconnect();
throw e;
}
}
#Override
public void loop(int loopCount) throws ConnectionLostException {
try{
byte[] response = new byte[1];
int read = mInput.read();
}catch(IOException e){
Log.d(TAG, "error: " + e.getMessage());
}
}
I've also tried using BufferedReaders, while passing Strings through Serial.println, but a lot of crazy characters were getting output from the Java side (tried encoding in both UTF-8 and ASCII).
Baud rates are matched up at 9600, and I'm on a 5v RX pin on the IOIO, and that pin is connected to the TX pin (pin 1) on the Arduino Uno.
Does anyone point to a simple way of transmitting & receiving an integer?

Android cannot recieve all characters via bluetooth

I'm creating an app that sends and receive data with an arduino via bluetooth. Sending works fine, however when receiving data I don't get the first few characters of the string sent. I always don't get the first character, the second I sometimes get it, the third I almost always get it, etc.
So for example if the arduino sends "OK 1" I receive "K 1" or " 1" or "1", but never the complete string. An easy fix would be to add a few dummy characters, but that's a shit fix.
Here's the method which listens to incoming connections, directly copy/pasted from Android sample bluetooth code to send a simple string via bluetooth (though with a few fixes):
void beginListenForData()
{
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
final boolean stopWorker = false;
final int readBufferPosition = 0;
final byte[]readBuffer = new byte[1024];
Thread workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = inStream.available();
int readBufferPosition2 = readBufferPosition;
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
inStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition2];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes);
readBufferPosition2 = 0;
handler.post(new Runnable()
{
public void run()
{
result.setText(data);
}
});
}
else
{
readBuffer[readBufferPosition2++] = b;
}
}
}
}
catch (IOException ex)
{
}
}
}
});
workerThread.start();
}
Here's all my code in case you want to test it (warning: lots of dummy and outdated code):
MainActivity.java http://pastebin.com/cdjW4Y1V
XML layout file http://pastebin.com/Ruf5euPP
Click on the first button to connect to the arduino and click on the second button to send a string and to begin receiving data.
So yep, I have absolutely no idea why it doesn't work. It works fine with TerminalBT so it's not a problem with the arduino, it's a problem with my app, but why do I receive characters randomly?
one thing i noticed is that you should not use 10 for the delimiter.
I have encountered this error before if you use 10 then some times it does not get recognized properly.
you should use standard Java Function to parse the delimiter.
System.getProperty("line.separator");
//OR
System.lineSeparator();

What is the least painful way to extract data at the protocol layer in Java?

I'm trying to implement an Android application to connect to the open source software Motion. The goal is to be able to check the status of the application and get the last image captured.
I do not program in Java very much, my background is principally in C and Python. I've not had any real issues with understanding the UI part of Android, but I've found it to be incredibly painful to work with any sort of byte buffer. The Motion software has an HTTP API that is very simple. Opening the URL connection is easy in Java. The response from the default page looks like this
Motion 3.2.12 Running [4] Threads
0
1
2
3
For my purposes the first thing the application needs to do it parse out the number of threads. At some point I can also retrieve the version number from the first line, but that's not really important presently.
Here's my code
package com.hydrogen18.motionsurveillanceviewer;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
public class MotionHttpApi {
String host;
int port = 80;
boolean secure = false;
int numberOfThreads = -1;
String getBaseUrl()
{
StringBuilder sb = new StringBuilder();
sb.append(secure ? "https://" : "http://");
sb.append(host);
sb.append(':');
sb.append(port);
return sb.toString();
}
public int getNumberOfCameras() throws IOException
{
if(numberOfThreads == -1)
{
retrieveSplash();
}
if(numberOfThreads == 1)
{
return 1;
}
return numberOfThreads - 1;
}
void retrieveSplash () throws IOException
{
URL url = new URL(getBaseUrl());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
if(conn.getResponseCode()!=HttpURLConnection.HTTP_OK)
{
throw new IOException("Got response code" + conn.getResponseCode());
}
try{
Byte[] buffer = new Byte[512];
byte[] sbuf = new byte[128];
int offset = 0;
InputStream in = new BufferedInputStream(conn.getInputStream());
boolean foundInfoString= false;
while( ! foundInfoString)
{
//Check to make sure we have not run out of space
if(offset == buffer.length)
{
throw new IOException("Response too large");
}
//Read into the smaller buffer since InputStream
//can't write to a Byte[]
final int result = in.read(sbuf,0,sbuf.length);
//Copy the data into the larger buffer
for(int i = 0; i < result;++i)
{
buffer[offset+i] = sbuf[i];
}
//Add to the offset
offset+=result;
//Wrap the array as a list
List<Byte> list = java.util.Arrays.asList(buffer);
//Find newline character
final int index = list.indexOf((byte) '\n');
//If the newline is present, extract the number of threads
if (index != -1)
{
//Find the number of threads
//Thread number is in the first lin like "[X]"
final int start = list.indexOf((byte)'[');
final int end = list.indexOf((byte)']');
//Sanity check the bounds
if(! (end > start))
{
throw new IOException("Couldn't locate number of threads");
}
//Create a string from the Byte[] array subset
StringBuilder sb = new StringBuilder();
for(int i = start+1; i != end; ++i)
{
final char c = (char) buffer[i].byteValue();
sb.append(c);
}
String numThreadsStr = sb.toString();
//Try and parse the string into a number
try
{
this.numberOfThreads = Integer.valueOf(numThreadsStr);
}catch(NumberFormatException e)
{
throw new IOException("Number of threads is NaN",e);
}
//No more values to extract
foundInfoString = true;
}
//If the InputStream got EOF and the into string has not been found
//Then an error has occurred.
if(result == -1 && ! foundInfoString )
{
throw new IOException("Never got info string");
}
}
}finally
{
//Close the connection
conn.disconnect();
}
}
public MotionHttpApi(String host,int port)
{
this.host = host;
this.port = port;
}
}
The code works just fine when you call getNumberOfCameras(). But I think I must not be really understandings omething in terms of java, because the retrieveSplash method is far too complex. I could do the same thing in just 10 or so lines of C or 1 line of Python. Surely there must be a saner way to manipulate bytes in java?
I think there are some style issues, like I probably should not be throwing IOException whenever the integer fails to parse. But that's a separate issue.
Read the first line as Gautam Tandon suggested and then use a regex.
You can then check if the regex matches and even easily extract the number.
Regex' can be created at http://txt2re.com. I've already done that for you.
The page even creates Java, Pyhton, C, etc. files for you to work with.
// URL that generated this code:
// http://txt2re.com/index-java.php3?s=Motion%203.2.12%20Running%20[4]%20Threads&-7&-19&-5&-20&-1&2&-22&-21&-62&-63&15
import java.util.regex.*;
class Main
{
public static void main(String[] args)
{
String txt="Motion 3.2.12 Running [4] Threads";
String re1="(Motion)"; // Word 1
String re2="( )"; // White Space 1
String re3="(3\\.2\\.12)"; // MMDDYY 1
String re4="( )"; // White Space 2
String re5="(Running)"; // Word 2
String re6="( )"; // White Space 3
String re7="(\\[)"; // Any Single Character 1
String re8="(\\d+)"; // Integer Number 1
String re9="(\\])"; // Any Single Character 2
String re10="( )"; // White Space 4
String re11="((?:[a-z][a-z]+))"; // Word 3
Pattern p = Pattern.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher m = p.matcher(txt);
if (m.find())
{
String word1=m.group(1);
String ws1=m.group(2);
String mmddyy1=m.group(3);
String ws2=m.group(4);
String word2=m.group(5);
String ws3=m.group(6);
String c1=m.group(7);
String int1=m.group(8);
String c2=m.group(9);
String ws4=m.group(10);
String word3=m.group(11);
System.out.print("("+word1.toString()+")"+"("+ws1.toString()+")"+"("+mmddyy1.toString()+")"+"("+ws2.toString()+")"+"("+word2.toString()+")"+"("+ws3.toString()+")"+"("+c1.toString()+")"+"("+int1.toString()+")"+"("+c2.toString()+")"+"("+ws4.toString()+")"+"("+word3.toString()+")"+"\n");
}
}
}
//-----
// This code is for use with Sun's Java VM - see http://java.sun.com/ for downloads.
//
// Paste the code into a new java application or a file called 'Main.java'
//
// Compile and run in Unix using:
// # javac Main.java
// # java Main
//
String int1=m.group(8); gives you the desired integer. Of course you can simplify the above code. It's way to verbose right now.
You can simplify the retrieveSplash method considerably by using BufferedReader. Here's a simpler version of your function:
void retrieveSplash_simpler() throws IOException {
URL url = new URL(getBaseUrl());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
// open the connection
conn.connect();
// create a buffered reader to read the input stream line by line
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// find number of threads
String firstLine = reader.readLine();
int x = firstLine.indexOf("[");
int y = firstLine.indexOf("]");
if (x > 0 && y > 0 && x < y) {
try {
numberOfThreads = Integer.parseInt(firstLine.substring(x+1, y));
} catch (NumberFormatException nfe) {
// disconnect and throw exception
conn.disconnect();
throw new IOException("Couldn't locate number of threads");
}
} else {
// disconnect and throw exception
conn.disconnect();
throw new IOException("Couldn't locate number of threads");
}
// disconnect
conn.disconnect();
}
I'd further clean up the above method by using try/catch/finally blocks at the appropriate places so that I don't have to duplicate that "conn.disconnect()". But I didn't do that here to keep it simple (try/catch/finally do become tricky sometimes...).

Categories

Resources