I wrote a program which clicks on a button at a specific time. This button sends a request to the server (I don't own this server) which will output an arrival time.
This arrival time includes milliseconds, so each millisecond is worth a lot.
At first I ping the server (in this example I pinged google) and get the latency. Because I just need the travel time to the server, I divide it by 2. Then Robot bot (the clickbot) clicks the button at the specific time which has the format: yyyy-MM-dd HH:mm:ss.SSS
Unfortunately, I have a really high deviation between this program and the arrival time. This is what I want to optimize. If I optimize it manually, then I get an average deviation of 30 milliseconds, but I always need to adapt it manually each time I want to use it.
So the deviation constantly changes. Now I want to adapt the program so that I no longer have to adapt it manually. I want to achieve the minimum deviation without manually interaction.
How can I achieve this? I have already synchronized with the server's time server, so my program should have the same time as the server that sends me the arrival time.
What else should I consider? I already have considered the latency and the server time.
Edit: Yes, it is possible to "dry fire" the button, but I don't know how to do it. At the moment I try to learn it, but it is still difficult for me.
@Joachim Sauer you mean "dry fire" with a post request, right?
@Joop Eggen Ok. If I click a button, then the server gets the request and outputs the arrival time. Now I imitate the click with "robot bot" and calculate the latency/2 to get as close as possible to the arrival time I want to have (arrival time I want to have = "date = dateFormatter.parse("2020-08-28 23:51:50.000");" in this example).
Now when I adapt the timer/date manually, I still have a deviation around 30 milliseconds. If I don't adapt it manually, I will have a deviation of 700+ milliseconds.
So I want to have the smallest deviation possible without manually adapting the timer/date. But how can I achieve this? I already have considered the latency and the server time.
package Timen;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;
public class timeclick {
//The task which you want to execute
private static class MyTimeTask extends TimerTask
{
public void run()
{
Robot bot;
try {
bot = new Robot();
bot.mouseMove(611, 529);
bot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
bot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
} catch (AWTException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args)throws Exception {
// create the ping command as a list of strings
timeclick ping = new timeclick();
List<String> commands = new ArrayList<String>();
commands.add("ping");
commands.add("111.222.33.4");
double latencyToServer=ping.doCommand(commands);
//convert String into int
int latencyToServer1 = (int)latencyToServer;
int allDelays= (latencyToServer1) /2;
System.out.println("All deviations: "+allDelays);
//the Date and time at which you want to execute
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date;
try {
date = dateFormatter.parse("2020-08-28 23:51:50.000");
System.out.println ("current time " + dateFormatter.format(date));
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(date);
calendar1.add(Calendar.MILLISECOND, -allDelays);
date = calendar1.getTime();
System.out.println ("new time " + dateFormatter.format(date));
//Now create the time and schedule it
Timer timer = new Timer();
//Use this if you want to execute it once
timer.schedule(new MyTimeTask(), date);
//Use this if you want to execute it repeatedly
//int period = 10000;//10secs
//timer.schedule(new MyTimeTask(), date, period );
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public double doCommand(List<String> command)
throws IOException
{
String s = null;
ProcessBuilder pb = new ProcessBuilder(command);
Process process = pb.start();
Process process1 = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader stdInput1 = new BufferedReader(new InputStreamReader(process1.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null)
{
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null)
{
System.out.println(s);
}
//get the average latency
System.out.println("here is the average latency :\n");
double latency = 0.0;
while ((s = stdInput1.readLine()) != null)
{
if (s.contains("Mittelwert")) {
String timeWithValue = s.split(" = ")[2];
String value = timeWithValue.split("ms")[0];
latency = Double.parseDouble(value);
System.out.println("latency " + latency);
}
}
return latency;
}
}