How to minimize the deviation?

Viewed 100

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;
           
    
    
    
         
        }
       
    }
0 Answers
Related