Slow serial transfer from Java to Arduino - java

I have bidirectional communication between Java and Arduino, but am finding that when sending data from Java to Arduino it takes about 3.5 seconds to show up in the sketch.
Data sent from Arduino to Java has no such latency.
Any idea why this is the case?
Arduino code.
Here's my main loop,
void loop() {
connection.sendData(systemVariables);
connection.receiveData(systemVariables);
world(systemVariables, ctr++);
}
Here's the sender,
void sendData(SystemVariables &sv) {
String msg = String(sv.getReference());
String pstr = String(sv.getPosition(), 2);
msg = msg + "," ;
msg = msg + pstr;
msg = msg + "," ;
msg = msg + sv.getOutput();
Serial.println(msg);
}
Here's the receiver,
float receiveData(SystemVariables &sv) {
String str;
while (Serial.available() > 0) {
str = Serial.readStringUntil('\n');
Serial.print('>');
Serial.println(str);
}
if (str.length() > 0)
sv.setOutput( str.toFloat());
return sv.getOutput();
}
Java
The Java loop has a 25ms delay.
receiver
public synchronized void serialEvent(SerialPortEvent oEvent) {
//System.out.println("ET " + oEvent.getEventType());
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
String inputLine = null;
try {
inputLine = input.readLine();
if (inputLine.length() > 0) {
logger.log(Level.INFO, "{0}", inputLine);
if (!inputLine.startsWith(">")) {
String[] arr = inputLine.split(",");
for (int i = 0; i < arr.length; i++) {
try {
float newf = Float.parseFloat(arr[i]);
try {
if (data.size() <= i) {
data.add(newf);
} else {
data.set(i, newf);
}
} catch (IndexOutOfBoundsException e) {
logger.warning(e.toString());
}
} catch (NumberFormatException e) {
logger.log(Level.WARNING, "{0} <{1}> <{2}>", new Object[]{e.toString(), inputLine, arr[i]});
}
}
}
}
} catch (IOException ex) {
Logger.getLogger(SerialSensorSingleton.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception e) {
logger.warning(e.toString() + " Data received " + inputLine == null ? "null" : "<" + inputLine + ">");
}
}
}
Sender
public void write(String s) throws IOException {
logger.log(Level.INFO, ":{0}", s);
output.write(s.getBytes());
output.flush();
}

I have resolved this now. The problem was that I was trying to implement synchronous communication with asynchronous methodology.
That is, I was using SerialEvent listener, but this is only intended for one way communication. I was trying to use the port to send data back the other way, but it was being blocked by the queue of data that built up for a certain period.
I have changed the method calls to read and writes so that each end sends only one message and than waits for incoming data. In this way each end is synchronised, and it now works like a dream.

Related

Message from the server doesn't reach the client

I would like to that when the server gets a message from the client and the message is for example "start", server sends back ips and ports of the rest of clients.
Part of the server:
...
for (i = 0; i < max_clients; i++) {
sd = client_socket[i];
memset(buffer, 0, 10000);
if (FD_ISSET( sd , &readfds)) {
if ((valread = read( sd , buffer, 1024)) == 0) {
getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" ,
inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
close( sd );
client_socket[i] = 0;
}
else {
char cmd[10] = "";
int k;
for(k=0; k<strlen(buffer)-1; k++) {
char tmp[2] = "";
tmp[0] = buffer[k];
strcat(cmd, tmp);
}
if (strcmp(cmd, "start") == 0) {
char clientInfo[1000] = "[ ";
for(j=0; j<max_clients; j++) {
if (client_socket[j] > 0 && client_socket[j] != sd) {
char port[12];
sprintf(port, "%d", clients[j].port);
strcat(clientInfo, "{");
strcat(clientInfo, clients[j].addr);
strcat(clientInfo, " - ");
strcat(clientInfo, port);
strcat(clientInfo, "} ");
}
}
strcat(clientInfo, "]");
send(sd, clientInfo, strlen(clientInfo), 0);
printf("%s\n", clientInfo);
} else {
buffer[valread] = '\0';
for(j=0; j<max_clients; j++) {
int outSock = client_socket[j];
if(outSock != master_socket && outSock != sd) {
send(outSock , buffer , strlen(buffer) , 0 );
}
}
}
}
}
}
...
Part of the client:
public ChatWindowController() {
try {
clientSocket = new Socket("127.0.0.1", 54000);
outToServer = new DataOutputStream(clientSocket.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
thread = new Thread() {
#Override
public void run() {
try {
while(isRunning) {
if (ta_display != null) {
String message = inFromServer.readLine();
System.out.println(message);
ta_display.appendText(message + '\n');
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
};
thread.start();
} catch(Exception e) {
e.printStackTrace();
}
}
...
...
#FXML
void sendMsg(ActionEvent event) {
String message = tf_user_input.getText();
if (username == null || username.equals("") || username.trim().equals("")) {
ta_display.appendText("You can not send a message, set your username!\n");
return;
}
if (message != null && !message.equals("") && !message.trim().equals("")) {
try {
out.println(username + ": " +message);
out.flush();
} catch(Exception e) {
e.printStackTrace();
}
ta_display.appendText(username + ": " + message + "\n");
}
tf_user_input.setText("");
}
#FXML
void sendFile(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
out.println("start");
out.flush();
}
Messages from clients are sent to the server, and the server sends them to other clients, it works.
But when client send message "start" to the server I want to send back ips and ports of the rest of the clients, but it doesn't arrive to the client back, only when one of the other clients writes something, a message with ip and user ports comes.
E.g. "[{127.0.0.1 - 1234} {127.0.0.1}]User: example"
Like the message has been lost and arrived with another. I print the ips and ports to see if everything is alright and it prints corectly.
I'm not getting any errors.
Does anybody know how to send back a message after specific message from client?

java.net.SocketException: Connection reset by peer. In custom twitch bot

I created custom Twitch bot with using of cavariux library. I called this methods in main class.
bot.setOauth_Key("oauth:key_Value");
bot.connect();
bot.joinChannel(channel.toString());
bot.start();
Approximately one of the 5-6 launches of the bot is accompanied by an exception
java.net.SocketException: Connection reset by peer
. The stack trace indicates that the exception starts on this line.
while ((line = this.reader.readLine( )) != null && !stopped)
in TwitchBot class in method start(). I didn't change code of this library except adding utf encoding in method connect(String ip, int port).
this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
I've tested my bot on different PCs. On some machines I don't have this issue. On some I got this exception more often.
This is code of method start() in TwitchBot class.
public final void start()
{
if (isRunning()) return;
String line = "";
stopped = false;
try {
while ((line = this.reader.readLine( )) != null && !stopped) {
if (line.toLowerCase( ).startsWith("ping")) {
LOGGER.log(Level.INFO,"> PING");
LOGGER.log(Level.INFO,"< PONG " + line.substring(5));
this.writer.write("PONG " + line.substring(5) + "\r\n");
this.writer.flush();
} else if (line.contains("PRIVMSG"))
{
String str[];
str = line.split("!");
final User msg_user = User.getUser(str[0].substring(1, str[0].length()));
str = line.split(" ");
Channel msg_channel;
msg_channel = Channel.getChannel(str[2], this);
String msg_msg = line.substring((str[0].length() + str[1].length() + str[2].length() + 4), line.length());
LOGGER.log(Level.INFO,"> " + msg_channel + " | " + msg_user + " >> " + msg_msg);
if (msg_msg.startsWith(commandTrigger))
onCommand(msg_user, msg_channel, msg_msg.substring(1));
if (msg_user.toString().equals("jtv") && msg_msg.contains("now hosting")) {
String hoster = msg_msg.split(" ")[0];
onHost(User.getUser(hoster), msg_channel);
}
onMessage(msg_user, msg_channel, msg_msg);
} else if (line.contains(" JOIN ")) {
String[] p = line.split(" ");
String[] pd = line.split("!");
if (p[1].equals("JOIN"))
userJoins(User.getUser(pd[0].substring(1)), Channel.getChannel(p[2], this));
} else if (line.contains(" PART ")) {
String[] p = line.split(" ");
String[] pd = line.split("!");
if (p[1].equals("PART"))
userParts(User.getUser(pd[0].substring(1)), Channel.getChannel(p[2], this));
} else if (line.contains(" WHISPER ")) {
String[] parts = line.split(":");
final User wsp_user = User.getUser(parts[1].split("!")[0]);
String message = parts[2];
onWhisper(wsp_user, message);
} else if (line.startsWith(":tmi.twitch.tv ROOMSTATE")) {
} else if (line.startsWith(":tmi.twitch.tv NOTICE"))
{
String[] parts = line.split(" ");
if (line.contains("This room is now in slow mode. You may send messages every"))
{
LOGGER.log(Level.INFO,"> Chat is now in slow mode. You can send messages every " + parts[15] + " sec(s)!");
} else if (line.contains("subscribers-only mode")) {
if (line.contains("This room is no longer"))
LOGGER.log(Level.INFO,"> The room is no longer Subscribers Only!");
else
LOGGER.log(Level.INFO,"> The room has been set to Subscribers Only!");
} else {
LOGGER.log(Level.INFO,line);
}
} else if (line.startsWith(":jtv MODE "))
{
String[] p = line.split(" ");
if (p[3].equals("+o")) {
LOGGER.log(Level.INFO,"> +o " + p[4]);
} else {
LOGGER.log(Level.INFO,"> -o " + p[4]);
}
} else if (line.toLowerCase().contains("disconnected"))
{
LOGGER.log(Level.INFO, line);
this.connect();
} else
{
LOGGER.log(Level.INFO,"> " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
This is code of method connect() in TwitchBot class.
public void connect(String ip, int port)
{
if (isRunning()) return;
try{
if (user == null || user == "")
{
LOGGER.log(Level.SEVERE, "Please select a valid Username");
System.exit(1);
return;
}
if (oauth_key == null || oauth_key == "")
{
LOGGER.log(Level.SEVERE,"Please select a valid Oauth_Key");
System.exit(2);
return;
}
#SuppressWarnings("resource")
Socket socket = new Socket(ip, port);
this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),StandardCharsets.UTF_8));
this.writer.write("PASS " + oauth_key + "\r\n");
this.writer.write("NICK " + user + "\r\n");
this.writer.write("USER " + this.getVersion() + " \r\n");
this.writer.write("CAP REQ :twitch.tv/commands \r\n");
this.writer.write("CAP REQ :twitch.tv/membership \r\n");
this.writer.flush();
String line = "";
while ((line = this.reader.readLine()) != null)
{
if (line.indexOf("004") >= 0) {
LOGGER.log(Level.INFO,"Connected >> " + user + " ~ irc.twitch.tv");
break;
}else {
LOGGER.log(Level.INFO,line);
}
}
} catch (IOException e)
{
e.printStackTrace();
}
}
Thank you for the help
This error means that the peer (i.e. the Twitch server) closes abruptly your connection. See this answer for more details.
I don't know if you can do something to fix that because it can have various external origins (peer crash...). Maybe you can wait and try to reconnect later (note that you might be blacklisted if you connect too often).

Java UDP socket client not blocking

I'm trying to code a UDP client to receive packets from a server that is broadcasting on the local network. The problem is the receive method isn't blocking and waiting for a packet to arrive.
Instead, it's receiving null or empty packets.
I've tried to use .setSoTimeout(0), which supposedly will tell the receive to block until it receives a packet, but it doesn't.
Does anyone know how to fix this?
Here's the code:
while (search == true) {
InetAddress addr = InetAddress.getByName("0.0.0.0");
DatagramSocket sock = new DatagramSocket(1355);
sock.setSoTimeout(0);
byte[] recebe = new byte[1024];
sock.setBroadcast(true);
System.out.println("entrou1");
DatagramPacket packet = new DatagramPacket(recebe, recebe.length);
System.out.println("entrou2");
sock.receive(packet);
String info = new String(packet.getData());
System.out.println("tamanho: " + info.length());
if (info.trim().equals("") == false && info != null) {
System.out.println("entrou aqui");
System.out.println("info recebida:" + info + ":fsadfsfs");
String servs[] = info.split("\n");
list1.clear();
servidores.clear();
for (int i = 0; i < servs.length; i++) {
System.out.println("vec: " + servs[i]);
if (servs[i].trim().equals("")) {
System.out.println("break;");
break;
} else {
String aux = servs[i].substring(0, servs[i].lastIndexOf("->"));
System.out.println("aux: " + aux);
list1.add(aux);
servidores.add(servs[i]);
}
}
}
System.out.println("info:\n" + info);
sock.close();
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException ex) {
Logger.getLogger(AcederPartilhaGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

Java While Loop

I'm having some issues with a while loop. This while loop is run in a thread, and is the "main loop" of the thread, and I'm having issues with it not continuing if one of the if statements it loops over is false. This thread handles both sending and receiving IRC Commands/Messages for use in a minecraft client.
The code as it stands is below:
do {
System.out.println("IRC Thread Looped!");
if(tosend != "") {
writer.write("PRIVMSG " + channel + " :"+tosend+"\r\n");
System.out.println(tosend);
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] \2477"+nick+": \247f"+tosend);
tosend = "";
writer.flush();
}
if((line = reader.readLine()) != null) {
if(line.startsWith("PING ")) {
writer.write("PONG " + line.substring(5) + "\r\n");
writer.flush( );
}
else {
// we need to pretty this ugly sh*t up!
try {
String parsedline;
String args[] = line.split("!");
String args2[] = args[1].split(":");
args[0] = args[0].substring(1, args[0].length());
parsedline = "\2477"+ args[0] +": \247f"+ args2[1];
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] "+parsedline);
}
catch(Exception e) {
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f]\247f "+line);
continue;
}
}
}
try {
Thread.sleep(90L);}catch(Exception e) { };
}
} while(true);
Note that java threads like to eat exceptions that get thrown out of the run() method.
Since you have IO such as if((line = reader.readLine()) != null){ not in a try/catch, you might be throwing an exception and exiting.
What I like to do with threads is to put the main thread code in runImpl() and have the run() look like this.
public void run()
{
try
{
runImpl();
}
catch( Throwable t )
{
// log the throwable
}
}
Then at a minimum you can discover that your thread threw something unexpected.
If the problem is caused by getLine() blocking behavior you could probably fix it this way. I haven't run that code so I don't guarantee it will work. Also make sure that reader is a BufferedReader.
StringBuilder sb = new StringBuilder();
String line = null;
int n = 0;
do {
System.out.println("IRC Thread Looped!");
if(tosend != ""){
writer.write("PRIVMSG " + channel + " :"+tosend+"\r\n");
System.out.println(tosend);
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] \2477"+nick+": \247f"+tosend);
tosend = "";
writer.flush();
}
while (reader.ready()) {
int c = reader.read();
if (c == -1) {
if (n > 0) {
line = sb.toString();
sb = new StringBuilder();
}
break;
}
if (c == '\n' || c == '\r') {
line = sb.toString();
sb = new StringBuilder();
break;
}
sb.append((char)c);
n++;
}
if(line != null){
if (line.startsWith("PING ")) {
writer.write("PONG " + line.substring(5) + "\r\n");
writer.flush( );
}
else
{
//we need to pretty this ugly shit up!
try{
String parsedline;
String args[] = line.split("!");
String args2[] = args[1].split(":");
args[0] = args[0].substring(1, args[0].length());
parsedline = "\2477"+args[0] +": \247f"+ args2[1];
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] "+parsedline);
}catch(Exception e){
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f]\247f "+line);
continue;
}
}
line = null;
n = 0;
}
try{Thread.sleep(90L);}catch(Exception e){};
} while(true);

Java NIO multiple socket connections failing

I have a program that attempts to connect to port 80 on different machines and reports if there is a server running. I am using NIO which therefore uses sockets to do the connection. I do a connect and then poll using finishConnect().
I am getting inconsistent behaviour. Sometimes the program correctly reports that there are web servers running on the various machines that I am scanning. However at other times the connections do not get reported even though there are webservers running on the target machines.
I would understand this if I was using UDP sockets as these are not reliable but I am using a TCP connection that should be reliable i.e no dropped packets.
I need to be able to scan many machines but this inconsistent behaviour exhibits it self even when testing the program with just 4 target IP addresses that all have webservers on port 80.
TIA
Rod
class SiteFinder {
private static final long TIMEOUT = 500;
public void findSites() {
int numSocketChannels = 100;
int socketChannelCounter = 0;
long ipAddressCounter = 0;
boolean done = false;
List<String> allIpAddresses =
IPAddressGenerator.getIPAddresses(170);
SocketChannel[] socketChannelArray =
new SocketChannel[numSocketChannels];
Iterator<String> itr = allIpAddresses.iterator();
while(itr.hasNext()) {
int k;
for (k = 0; k < numSocketChannels && itr.hasNext(); k++) {
String ipAddress = itr.next();
ipAddressCounter++;
if (ipAddressCounter % 50000 == 0)
System.out.println(ipAddressCounter + " at " + new Date());
try {
socketChannelArray[k] = SocketChannel.open();
socketChannelArray[k].configureBlocking(false);
if (socketChannelArray[k].connect(
new InetSocketAddress(ipAddress,80))) {
System.out.println(
"connection established after connect() "
+ ipAddress);
socketChannelArray[k].close();
socketChannelArray[k] = null;
}
} catch (IOException ioe) {
System.out.println(
"error opening/connecting socket channel " + ioe);
socketChannelArray[k] = null;
}
}
while (k < numSocketChannels) {
socketChannelArray[k++] = null;
}
long startTime = System.currentTimeMillis();
long timeout = startTime + TIMEOUT;
connect:
while (System.currentTimeMillis() < timeout) {
//System.out.println("passing");
socketChannelCounter = 0;
for(int j = 0; j < socketChannelArray.length; j++) {
//System.out.println("calling finish connect");
if (socketChannelArray[j] == null) {
++socketChannelCounter;
if (socketChannelCounter == numSocketChannels) {
System.out.println("terminating connection loop");
break connect;
}
continue;
}
try {
if (socketChannelArray[j].finishConnect()) {
/*try {
out.write("connection established after " +
finishConnect()" +
clientChannelVector.elementAt(j).socket().
getInetAddress() + '\n');
out.flush();
} catch (IOException ioe) {
System.out.println(
"error writing to site-list "
+ ioe.getMessage());
}*/
System.out.println(
"connection established after finishConnect()"
+ socketChannelArray[j].socket().
getInetAddress());
socketChannelArray[j].close();
socketChannelArray[j] = null;
}
} catch (IOException ioe) {
System.out.println(
"error connecting from "
+ "clientChannel.finishConnect()");
try {
socketChannelArray[j].close();
} catch (IOException e) {
System.out.println("error closing socket channel");
} finally {
//System.out.println("removing socket channel");
//System.out.println(clientChannelVector.size());
socketChannelArray[j] = null;
}
}
}
}
closeConnections(socketChannelArray);
}
}
private void closeConnections(SocketChannel[] socketChannelArray) {
for (int i = 0; i < socketChannelArray.length; i++) {
if (socketChannelArray[i] == null) {
continue;
}
try {
socketChannelArray[i].close();
//System.out.println(
//"TIME OUT WAITING FOR RESPONSE CLOSING CONNECTION");
} catch (IOException ioe) {
System.out.println(
"error closing socket channel " + ioe.getMessage());
}
}
}
}

Categories

Resources