Thread.Sleep crashes my app - java

This app talks to a serial device over an usb to serial dongle. I have been able to get it to process my single queries no problem but I have a command that will send multiple queries to the serial device and It seems to me the buffer if getting overrun. Here is part of my code:
This is my array with 20 query commands:
String [] stringOneArray = {":000101017d", ":0001060178", ":00010B016C", ":000110017D",
":0001150178", ":00011A016C", ":00011F0167", ":0001240178", ":0001290173",
":00012E0167", ":0001330178", ":0001380173", ":00013D0167", ":0001420178",
":0001470173", ":00014C0167", ":0001510178", ":0001560173", ":00015B0167", ":0001600178"};
This is how I use the array:
getVelocitiesButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ftDev.setLatencyTimer((byte) 16);
int z;
for (z = 0; z < 19; z++) {
String writeData = (String) stringOneArray[z];
byte[] OutData = writeData.getBytes();
ftDev.write(OutData, writeData.length());
try {
Thread.sleep(50);
} catch (InterruptedException e) { }
}
}
});
Not sure the rest of the code is necessary but will add it if needed.
So ftdev is my serial device. It sends the query command to the serial device, it receives the response in bytes, I use a For loop to build the response until all bytes (31 bytes per response) then I process that response and at that time it should receive the second query command from the array, so on until the last command is sent.. It is all fine an dandy if I allow the FOR loop to send only one or 2 queries but with a larger number of array index and it crashes. Figured I just slow down the FOR loop and add the thread.sleep but it freezes the app and crashes... What gives? Is there any other way to control the speed to which the commands are sent? I rather send them as soon as it is possible but I am afraid I don't know java as much. This has been so far my major stepping stone in finishing this personal project, been stuck for 2 days researching and trying solutions.

Looks like you're sleeping for ~1000ms (well 950 to be exact because your last operation is not being sent to the serial device) plus the time needed to perform the writes over your serial connection. That's a pretty long time to do nothing. Remove the Thread.sleep(50) call and put the entire contents of the onClick into the run method of the following code:
AsyncTask.execute(new Runnable {
#Override
public void run() {
// talk to device here
}
});
Then, ask a different question about the quick writes crashing your connection.

Related

How to investigate Java socket program performance issue

I have two variations of the same set of Java programs [Server.java and Client.java] and [ServerTest.java and ClientTest.java]. They both do the same thing, the client connects to the server and sends pairs of integers across to the server to be multiplied and the result returned to the client, where it is then printed. This is performed 100 times each.
However, in the Test version, I create and close a new socket for each passing of an integer pair and their multiplication (100 multiplications are performed). In the normal version, I open a single persistent socket and perform all interaction with the client and close afterward.
Intuitively, I thought the approach where I create one persistent socket would be a little faster than creating, accepting and closing a socket each time - in reality, the approach where a new socket is created, accepted and closed is noticeably faster. On average, the persistent socket approach takes around 8 seconds, whereas the approach that creates a new socket every time takes around 0.4 seconds.
I checked the system call activity of both and noticed nothing different between the two. I then tested the same programs on another computer (macOS Sierra) and there was a neglible difference between the two. So it seems the problem doesn't even lie with the application code but how it interacts with the OS (I'm running Ubuntu LTS 16.04).
Does anyone know why there is such a difference in performance here, or how the issue could be investigated further? I've also checked system wide metrics (memory usage and CPU usage) when executing the programs and there seems to be plenty of memory and the CPU's have plenty of idle time.
See the code snippet of how both approaches differ below:
Creating new socket every time approach:
// this is called one hundred times
public void listen() {
try {
while (true) {
// Listens for a connection to be made to this socket.
Socket socket = my_serverSocket.accept();
DataInputStream in = new DataInputStream(socket
.getInputStream());
// Read in the numbers
int numberOne = in.readInt();
int numberTwo = in.readInt();
int result = numberOne * numberTwo;
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeInt(result);
// tidy up
socket.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
}
}
Persistent socket approach:
public void listen() {
try {
while (true) {
// Listens for a connection to be made to this socket.
Socket socket = my_serverSocket.accept();
for (int i = 0; i < 100; i++) {
DataInputStream in = new DataInputStream(socket
.getInputStream());
// Read in the numbers
int numberOne = in.readInt();
int numberTwo = in.readInt();
int result = numberOne * numberTwo;
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeInt(result);
}
// tidy up
socket.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
}
}
You didn't show us the code that is sending the integers for multiplication. Do you happen to have a loop in it in which in each iteration you send a pair and receive the result? If so make sure to turn off the Nagle's algorithm.
The Nagle's algorithm tries to overcome the "small-packet problem", i.e. when an application repeatedly emits data in small chunks. This leads to huge overhead, since packet header is often much larger than the data itself. The algorithm essentially combines a number of small outgoing messages and sends them all at once. If not enough data was gathered then the algorithm may still send the message, but only if some timeout has elapsed.
In your case, you were writing small chunks of data into the socket on both the client and the server side. The data weren't immediately transmitted. Rather the socket waited for more data to come (which didn't), so each time a timeout had to elapse.
Actually, the only difference between these 2 pieces of code is NOT how they handle incoming connections (by having one persistent socket or not), the difference is that in the one that you call "persistent", 100 pairs of numbers are multiplied, whereas in the other one, only 1 pair of number is multiplied then returned. This could explain the difference in time.

OutputStream.write() never ends

I have a car with a bluetooth interface that I connect to using my android app. Robot is programmed so that when he gets a digit 1-5, he makes an action.
1 - drive forward
2 - drive backward
3 - turn left
4 - turn right
5 - stop
I have 5 buttons in my app. Their events' look like this
public void button1(View view){
socket.write("1");
}
where socket is the class that holds BluetoothSocket and makes a connection and has write function:
public void write(String signal)
{
try
{
OutputStream.write(signal.getBytes());
Log.d("#Signal", " connected");
} catch (IOException e)
{
}
}
AND! When I connect, and press for example button that sends 2, robot starts moving backward but I don't get message from line
Log.d("#Signal", " connected");
So it looks like write(byte[] buffer) function never ends it's procedure. After pressing one button, when I try to press another one, it doesn't work. Like OutputStream.write() still tries to write something. I don't know why this happens, any solutions?
Try using flush() function after you call write() like this
OutputStream.write(signal.getBytes());OutputStream.flush();

For loop skipping two iterations with Thread.Sleep

I made an android application that simply calls the number range you enter.
Starts with starting number you enter and finishes with the "finish" number you enter. Application automatically hangs up after 7 seconds of ringing.
Code is below.
public void onClick(View view){
EditText starte = (EditText) findViewById(R.id.start);
EditText finishe = (EditText) findViewById(R.id.finish);
EditText prefixes = (EditText) findViewById(R.id.prefixes);
String prefix = prefixes.getText().toString();
/** Get Telephone number String **/
int startOriginal = Integer.parseInt(starte.getText().toString());
int finish = Integer.parseInt(finishe.getText().toString());
for (int start = startOriginal; start<=finish; start++) {
startCall(prefix, Integer.toString(start));
try {
Thread.sleep(7000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
new CallUtilities("endcall");
}
private void startCall(String prefix, String nr){
Intent intent = new Intent("android.intent.action.CALL");
Uri data = Uri.parse("tel:"+ prefix + nr);
/** Setting intent data */
intent.setData(data);
/** Starting the caller activity by the implicit intent */
startActivity(intent);
}
CallUtilities class is written by my end is simply ends the call via reflection methods. Now my problem is that when you enter a starting number and a finishing number the app always seems to call the first number for example 1 and after hanging it up it goes straight to 3 and then to 4 and 5 and so on like it should do. Any idea on what is wrong?
Also is it possible to use DisconnectCause here to get the reason of disconnect in case calls hangs up prematurely?
Thank you in advance!
This is a recipe for disaster. For a few reasons.
You are (assuming onClick(View v) runs on the UI Thread) attempting to sleep the UI Thread.
If the UI Thread hangs for longer than 5 seconds, it will cause an ANR.
Additionally, you appear to be attempting to launch multiple Activities at the same time. This is certainly not the right way to be designing your App.
Not to mention using Reflection to access core Android components to end the calls. That may cause issues for your App in the future.
My suggestion for the multiple Activities / sleep problem:
Remove the loop
Store next attempted number
Run the call function
In onActivityResult you can determine the next number to try
Go to 2. (make sure to include an end condition!

Return null result from reading data from Arduino into Processing

I want to read data from Arduino. My Arduino code is simple:
void setup()
{
// Initialize serial communications at a 9600 baud rate
Serial.begin(9600);
}
void loop()
{
// Send 'Hello, world!' over the serial port
Serial.println("Hello, World!!");
// Wait 100 milliseconds so we don't drive ourselves crazy
delay(100);
}
In Processing I have the following code
import processing.serial.*;
Serial myPort;
String val;
void setup() {
String portName = Serial.list()[1];
myPort = new Serial(this, portName, 9600);
}
void draw() {
if (myPort.available() > 0)
{
// If data is available,
val = myPort.readStringUntil('\n');
}
println(val); // pr
}
But val is always Null. I don't understand why it returns this value every time. The port is available.
In Processing, if you put in:
if (val == null) {
val = "0";
}
it should work. It'll keep printing 'val' without halting the program, but it'll return a value of "0" instead of "null".
Basically, you have to tell Processing to run even if it receives a "null" value.
The code posted should work. The things to check here are whether you are using the correct serial port. Try printing out the list of serial ports in setup:
println( Serial.list() );
If your code is correct, the port you want will be the second one. If that's not correct, change the number of the array index when you specify portName.
The other thing to check is whether the Arduino is actually printing what you think it's printing. When you open up the Serial Monitor, is it actually printing "Hello, world!" a bunch of times?

Java Logger for Arduino

I'm working on an Arduino logger written in Java.
I have started using the example code from the Arduino playground at:
http://arduino.cc/playground/Interfacing/Java
My problem is here I think:
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
int available = input.available();
byte chunk[] = new byte[available];
input.read(chunk, 0, available);
// Displayed results are codepage dependent
String print = new String(chunk);
test.write(print);
System.out.print(print);
} catch (Exception e) {
System.err.println(e.toString());
}
I wrote a class that will write the data to a csv file. When it prints the data to the console it is perfect. When I write it to the file I get some perfect lines and sometimes bad lines like:
60
4
5
28
I want it to print it like:
604
528
My write method is:
public void write(String print)
{
pw.print(System.currentTimeMillis());
pw.print(",");
pw.println(print);
}
Any advice is greatly appreciated !!
When you write about printing data on the console and in a file, you do not do exactly the same thing. You print raw data on the console, so you do not see any problems, while you process your data in your write() method which may make some problems appear.
The problem is not in your write() method, but rather the way you use it. As soon as you have some data, you print it. The thing is, you may have not receive all the data, so you print it too early.
It is quite common in data stream: the operating system warns you when data are available, but it may have receive only (let's say) 3 bytes out of 5 sent by the Arduino when it warns you. The operating system cannot know by itself that you were waiting 5 bytes and not only 3.
So you have to store and concatenate your data until you know it was all received. Two possibilities for that:
If you know that n bytes will be sent, store data until you received n bytes
Wait for a character flag indicating the end of your data: I suppose you use the Serial.println() method in Arduino, it means that the end of your data will have "\r\n" at the end. Incidentally, it is why you have some new lines in your file when printing data since you did not tell Jave to create new lines :-)
The code could be better, but to keep it simple since I am not sure of your level in Java, and to keep your code, you could do something like that (warning, I did not tested it):
// Should be outside of your serialEvent method
StringBuilder buffer = new StringBuilder();
public synchronized void serialEvent(SerialPortEvent oEvent) {
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
int available = input.available();
byte chunk[] = new byte[available];
input.read(chunk, 0, available);
// We store data in a buffer
buffer.append(new String(chunk));
// We check if we received the characters indicating
// the end of your data
int endOfLineIndex = buffer.indexOf("\r\n");
// We don't, so we leave and wait for more data
if (endOfLineIndex == -1) {
return;
}
// The "+2" is to keep the "\r\n"
String print = buffer.substring(0, endOfLineIndex+2);
// Do not forget to remove what was used in the buffer
buffer.delete(0, endOfLineIndex+2);
test.write(print);
System.out.print(print);
} catch (Exception e) {
System.err.println(e.toString());
}
}
// Ignore all the other eventTypes, but you should consider the other ones.
}
By the way, if you do not see any problems when directly printing data in your console, it is because the new lines characters comes from the Arduino and not the Java code. So you print a stream of data that is not broke, because you insert nothing between the characters you print on the screen. In your example, you first receive "60", then "4\r\n". It is a kind of automatic concatenation on the screen.

Categories