#============================================================================
#  AuvTimeSync -   Send current time of this system to client for
#                  synchronization. The packet sent is a string representation
#                  of the current system time (e.g. "1049896563.230740")
#
#  Client notes  - The client should bind a UDP socket to the given port and
#                  read incoming time using recv or recvfrom. Use the first
#                  packet to form a baseline difference between the to system
#                  clocks. Then continuously track the drift between the two
#                  system clocks by comparing the baseline difference to the
#                  subsequent time differences:
#                          begin
#                             recv(WinXpTime)
#                             base = WinXpTime - mytime
#                             do (forever)
#                                recv(WinXpTime)
#                                drift = base - (WinXpTime - mytime)
#                             end
#                          end
#
#  Usage: ruby ats.rb
#
#============================================================================

require 'optparse'
require 'socket'

# Default parameters
#
$clientHost = 'localhost'   # Qnx hostname (default localhost)
$clientPort = 9009          # Port client must bind to and recvfrom on
$rate       = 20            # Broadcast interval in seconds

# Define command-line options
#
options = OptionParser.new
options.banner = "Usage: ats [-h host] [-p port] [-r rate]"
options.on("-h host", String)   {|val| $clientHost = val}
options.on("-p port", Integer)  {|val| $clientPort = val}
options.on("-r rate", Float)    {|val| $rate       = val}

# Parse the options, if any.
# On error, print the usage banner and exit.
#
begin
  options.parse(ARGV)
rescue Exception => e
  puts(e)
  puts(options.banner)
  exit
end

# Calculate the interval from the rate.
# Print the usage banner and exit if rate is unuseable
#
if ($rate <= 0)
  puts("! Rate must be > 0")
  puts(options.banner)
  exit
else
  $interval = 1/$rate
end

# Report connection attempt
# 
puts("\r   Connecting to host: #{$clientHost}   Port: #{$clientPort}...")
sleep(0.5)

# Connect to client host/port. Exit if connection failed.
#
sock = UDPSocket.new
begin
  sock.connect($clientHost, $clientPort)
rescue Exception => e
  puts(e)
  puts("ats failed to connect to #{$clientHost} on port #{$clientPort}")
  exit
end

# Report on connection and transmit rate.
#
puts("\r   Connected. Sending time data @ #{$rate}Hz...")
sleep(0.5)

# Continuously send the current time to client
# The packet is the string representation of the 
# current system time (e.g., "1049896563.230740")
#
ok = true
while (true)
  # Wait for the interval
  #
  sleep($interval)
  
  # Format packet string to a float representation, then a string.
  #
  pkt = Time.now.to_f.to_s

  # Send packet to client. Print an error message once
  # when send begins to fail, then once if/when it starts
  # working again.
  #
  if (sock.send(pkt, 0) <= 0 && ok)
    puts("ats: send failing at #{Time.now.to_s}")
    ok = false
  elsif (!ok)
    puts("ats: send working at #{Time.now.to_s}")
    ok = true
  end
  
end

