/*
  ranger.c

  Copyright 15-June-2004 MBARI
  Written: 15-June-2004 Mark Sibenac
  Last mod: 24-June-2004 sib - logs everything 

  Connects to acoustic modem and sends range commands.
	
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _QNX
#include <unistd.h>
#include <sys/select.h>
#else
#include <sys/unistd.h>
#endif
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>

#include "error.h"
#include "serial.h"
#include "util.h"

#define ALARM_PERIOD (10) /* seconds */

int DEBUG_LEVEL = 0; // default to no debug

char getKeyBoard (void)
{
  char str_in[2] = "\000";
  int ret;
  struct timeval tv;
  fd_set readFds;

  tv.tv_sec = 0; tv.tv_usec = 100000; // sleep for 100ms waiting for keyboard
  FD_ZERO (&readFds);
  FD_SET (0/*stdin*/, &readFds);
  
  if ((ret = select (1, &readFds, 0, 0, &tv)) < 0)
    { 
      ERROR ("err: getKeyBoard select failed %d: %s\n", ret, strerror(errno));
      return 0;
    }
  else if (ret > 0) // did not timeout; got a character
    {
      if ((ret = read (0/*stdin*/, str_in, 1)) < 0)
	{
	  ERROR ("err: getKeyBoard read failed %d: %s\n", ret, 
		 strerror(errno));
	}
      DEBUG (5, "getKeyBoard read got '%c'\n", *str_in);
      return *str_in;
    }

  return 0;
}

void flushStdin (void)
{
  char str[256];
  int ret;
  struct timeval tv;
  fd_set readFds;

  tv.tv_sec = 0; tv.tv_usec = 0; // sleep for 0ms waiting for keyboard
  FD_ZERO (&readFds);
  FD_SET (0/*stdin*/, &readFds);
  
  if ((ret = select (1, &readFds, 0, 0, &tv)) < 0)
    { 
      ERROR ("err: flushStdin select failed %d: %s\n", ret, strerror(errno));
      return;
    }
  else if (ret > 0) // did not timeout; got a character
    {
      if ((ret = read (0/*stdin*/, str, 255)) < 0)
	{
	  ERROR ("err: flushStdin read failed %d: %s\n", ret, 
		 strerror(errno));
	}
    }
}

int main (int argc, char **argv)
{
  int modem_port;
  int i;
  char shutdown = 0;
#if VER_0
  char keyboard = 0;
  struct termios termios_p;
#endif
  time_t t1, talarm;
  char devname[128]="/dev/ser6";
  int remote_modem = 1;
  char command_str[128]="ATR1";

  for (i=1; i < argc; ++i) 
  {
    if (*argv[i] == '-') // got something
    {
      if (!strcmp(argv[i]+1, "dev")) // modem device name
	strncpy (devname, argv[i+1], 128);
      else if (!strcmp(argv[i]+1, "debug")) // debug level
	DEBUG_LEVEL = atoi(argv[i+1]);
      else if (!strcmp(argv[i]+1, "rem")) // remote modem address
	remote_modem = atoi(argv[i+1]);
      else if (!strcmp(argv[i]+1, "cmd")) // command to send
	strcpy (command_str, argv[i+1]);
      else // print usage
	{
	  printf ("usage: ranger [-dev modem_dev_name] [-cmd ***] [-debug "
		  "debug_level]\n");
	  printf ("eg.    ranger -dev /dev/ser6 -cmd ATV\\? -debug 2\n");
	  printf ("default dev='%s'\n", devname);
	  printf ("default cmd='%s'\n", command_str);
	  printf ("default debug level=%d\n", DEBUG_LEVEL);
	  return -1;
	}
    }
  }

  printf ("dev='%s'\n", devname);
  printf ("cmd='%s'\n", command_str);
  printf ("debug level=%d\n", DEBUG_LEVEL);

#if VER_0
  if (tcgetattr (0/*stdin*/, &termios_p) < 0)
    {
      ERROR ("err: main() could not tcgetattr on stdin: %s\n",
	     strerror (errno));
      return -1;
    }

  termios_p.c_lflag |= ICANON;	// Enable Line Oriented Mode 

  if (tcsetattr (0/*stdin*/, TCSANOW, &termios_p) < 0)
    {
      ERROR ("err: main() tcsetattr failed on stdin: %s\n", strerror(errno));
      return -1;
    }
#endif /* VER_0 */

  DEBUG (1, "Debug Level=%d\n", DEBUG_LEVEL);
  DEBUG (1, "time = %d\n", (int)time(0));

#ifdef _QNX
  if (openPort (devname, &modem_port, 9600, 8, 1, "NONE") < 0)
    {
      ERROR ("err: Could not open '%s'\n", devname);
      return -1;
    }
#else /* _QNX */
  if (openPort (devname, &modem_port, B9600, 8, 1, "NONE") < 0)
    {
      ERROR ("err: Could not open '%s'\n", devname);
      return -1;
    }
#endif /* _QNX */

  if (openLogFile (modem_port, "modem") < 0)
    {
      ERROR ("err: Could not open modem_ logfile\n");
      return -1;
    }

  DEBUG (1, "modem_port fd= %d\n" , modem_port);

  sendStr (modem_port, "+++\r\n\r\n\r\n");

  msleep (2000); /* wait for "In Command Mode" */

  t1 = time(0);
  talarm = t1;

  while (!shutdown) {
    char rstr[129];
#if VER_0
    // first check for keyboard hit
    if ((keyboard = getKeyBoard ())) {
       switch (keyboard) {
	case 'Q':
	case 'q': // Quit
	  // shutdown properly
	  shutdown = 1;
	  break;
	case 0x0a: // line feed
	case 0x0d: // carriage return 
	  break; // do nothing
	default : // uh-oh
	  printf ("Command '%c' not recognized...\n", keyboard);
	} // switch(keyboard)
    } // if (keyboard = ...)
#endif /* VER_0 */

    recvAllStr (modem_port, rstr, 128); /* log serial traffic */
    printf (rstr);
    fflush (0);

    // now see if alarm is here
    t1 = time(0);
    if (t1 >= talarm) // ring!! ring!!! ring!!!!
      {
	static int cycle=1;
	char sstr[15];
	talarm = t1 + ALARM_PERIOD;
	DEBUG (102, "ALARM!!! time=%d next alarm=%d\n", (int)t1, (int)talarm);
	flushRecv (modem_port);
	printf ("Sending '%s' command for cycle %d...\n", command_str, cycle);
	sprintf (sstr, "%s\r\n", command_str);
	sendStr (modem_port, sstr);
	sleep (1);
	cycle++; 
      } // if (t1 > talarm)
  } // while (!shutdown)

  closeLogFile (modem_port);
  closePort (modem_port);

#if VER_0
  termios_p.c_lflag |= ICANON;	// Enable Line Oriented Mode
	
  if (tcsetattr (0/*stdin*/, TCSANOW, &termios_p) < 0)
    {
      ERROR ("err: main() tcsetattr failed on stdin: %s\n", strerror(errno));
      return -1;
    }

  tcflush (0, TCIOFLUSH);
#endif /* VER_0 */

  printf ("\n\nHave a super day...\n");

  return 0;
}

