OutputStream.write() never ends - java

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();

Related

Display a string just for a few seconds with JLine2

I am using JLine 2 to write a console application in Java. I need to make a password visible on the console for say 10 seconds, then erase it (on a GNU terminal).
I tried different things, amongst which :
putString(pass);
Thread.sleep(10*1000);
resetLine();
but no luck. Either the text does not show, or the text is not cleared.
Ok, I finally came up with the following (the class extends ConsoleReader):
public boolean showPassword(String pass, int millis) {
try {
resetPromptLine(" password>", pass, pass.length());
Thread.sleep(millis);
if (setCursorPosition(0) && killLine()) resetPromptLine(" password>", "", 0);
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
return false;
}
I use resetLine to show a custom prompt and the password; I also set the cursor to the end of the line. I wait a bit. I set the cursor to the end of the line and "kill the line". For the password to actually disappear, I have to call resetPromptLine once again.
To wait for an input from the user vs a given time, use readCharacter() instead of Thread.sleep().

Handling multiple menu inputs java - returning to while loop in main?

I'm trying to design a program that has a menu and essentially for the duration of the program handles input from that menu. I have another menu that may be called by another class that may interrupt the flow of this program and call another method, which displays another menu. Is there a way to transfer this control back to the while loop inside main to continue handle the input, when the display menu is called from another class, or would it be more sensible to write this entirely differently?
The code is just an example of how this is currently being structured. Currently I've tried setting a flag when the other class wants to call displayNewMenu, and checking for this flag in the while loop, and calling it from there, but this seems not to be working.
public static void main(String[] args) {
displayMenu();
while(true) {
handleMenuInput();
}
public void displayNewMenu() {
}
Well if you want this MENU to be accessible all the time you will have to do some multithreading.
Otherwise you will not be able to do other work and still be able to take user input.
Create thread to handle user interaction, this will include scanner that gets user input , puts output into console and spawn threads for your work.
You cant do this in singlethreaded enviroment.You will make your program hang.
If you jsut want to go back to handle user input/change menu etc, you need to change a flow a bit
public void work1(){
//some work
}
work2,3,4()...
public void menuSelector(){
//get input
if(input=menu1){
menu1();
} ....
}
public void menu1(){
displayMenu1();
while(true){
//get input
if(input=work1){
work1();
}
if(input=exitmenu){
break;
}
}
menuSelector();
}
public void menu2(){
displayMenu2();
while(true){
//get input
if(input=work2){
work2();
}
if(input=exitmenu){
break;
}
}
menuSelector();
}
I think you get the idea.This will allow yo ut ojump between menus , and loop within menu as well.Ofcourse odnt just use multiple if statements , switch woud be appropriete here.
If you're not looking for a multi-threaded solution, consider this approach:
main(){
while(true){ // Infinite loop to ensure that the control always comes back to display the menu. Exits only when the user selects an option to quit.
displayMenu();
handleUserInput();
}
}
displayMenu(){
// Show menu options here:
// Press 1 to perform task 1.
// Press 2 to perform task 2.
// Press 3 to exit.
}
handleUserInput(opt){
if opt == 1, perform task 1
else if opt == 2, perform task 2
else if opt == 3, exit
else show error "invalid input"
}
performtask1(){
while(true){
displayTask1Menu();
handleTask1UserInput();
}
}
displayTask1Menu(){
// Show menu options here:
// Press 1 to perform sub task 1.
// Press 2 to perform sub task 2.
// Press 3 to exit to main menu.
}
handleTask1UserInput(){
if opt == 1, perform sub task 1
else if opt == 2, perform sub task 2
else if opt == 3, exit to main menu / break;
else show error "invalid input"
}
This way the user will be prompted back to the menu after performing each operation with in sub menus.
You can also alter the menu display based on the user inputs.

Thread.Sleep crashes my app

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.

Thread, while loop and a System.out.print statement

Hi guys I have a nested Thread and using it to see when a player has taken a turn (in a draughts game) O have a game object and a public variable changedTurns.
new Thread() {
public void run(){
check();
}
private void check(){
boolean sent = false;
while(true){
System.out.println("ee"); \\line 9
if(game.changedTurns){
System.out.println("gg");
if(!sent){
System.out.println("ok");
sent =true;
}
}
}
}.start();
Everything works as expected like above I.e console shows plenty of "ee" followed by "gg" and then "ok" when the player takes their turn, however without line 9 nothing is shown when the player takes their turn ?!
You don't need to use threading to analyze whether the player has taken a turn. Just create a Player[] array and add a variable turn for the index of the player whose turn it is. Increment turn when a Player makes a turn.

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