/****************************************************************************/
/* Summary	: Command-line functions for BEDS Prototype on Persistor CF2	*/
/* Filename : bedsCmd.c														*/
/* Author	: Robert Herlien (rah)											*/
/* Project	: BEDS (Benthic Event Detection System)							*/
/* Revision : 1.0															*/
/* Created	: 09/17/2012													*/
/****************************************************************************/
/* Modification History:													*/
/* 17sep2012 rah - created from Persistor "toPico" stationery and			*/
/*				   previous BEDS prototypes									*/
/* $Log$
 */
/****************************************************************************/

#include <mbariTypes.h>			/* MBARI type definitions				*/
#include <beds.h>				/* BEDS general definitions				*/
#include <bedsUI.h>				/* BEDS Command line processor			*/
#include <bedsCmd.h>			/* BEDS Command line processor			*/
#include <file.h>				/* BEDS file I/O definitions			*/
#include <fileUtils.h>			/* BEDS file utilities definitions		*/
#include <clock.h>				/* BEDS Clock module					*/
#include <variable.h>			/* Variable function definitions		*/
#include <syslog.h>				/* BEDS System logger					*/
#include <serial.h>				/* BEDS Serial I/O						*/
#include <utils.h>				/* BEDS Utility routines				*/
#include <picConfig.h>			/* For picSoftReset()					*/
#include <adc.h>				/* BEDS Analog Module					*/
#include <watch.h>				/* For sensorsOn()						*/
#include <ymodem.h>				/* YModem definitions					*/
#include "ZModem/bedszm.h"		/* ZModem definitions					*/
#include <getopt.h>
#include <fatFs/ff.h>			/* FatFs definitions					*/

#include <stdio.h>
#include <string.h>


/****************************************/
/*		External Data					*/
/****************************************/

Extern Int32	sensorWarmup, platformID;
Extern char		*timespecErr;
Extern char		*watchIdxName, *eventIdxName;


/****************************************/
/*		Module Local Data				*/
/****************************************/

MLocal char		*idxFileErr = "Cannot open index file";
MLocal char		*oFileErr	= "Cannot create output file";
MLocal char		*noFileErr	= "No file name";
MLocal Nat16	oFileIndex = 1;
MLocal FIL		ifp, dfp, ofp;
MLocal char		syslogBuf[CMDBUF_LEN];


/****************************************/
/*		Module Local Data				*/
/****************************************/


/************************************************************************/
/* Function	   : QuitCmd												*/
/* Purpose	   : Exit command line parser								*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : ABORT													*/
/************************************************************************/
CmdRtn quitCmd(int argc, char **argv)
{
	sysLog("Exiting command parser");
	return(ABORT);

} /* QuitCmd() */


/************************************************************************/
/* Function	   : DeployCmd												*/
/* Purpose	   : Go to deployment mode									*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn DeployCmd(int argc, char **argv)
{
	int			opt, help=0, quit=0, n=0;

    while ((opt = getopt(argc, argv, "hnq")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'n': n=1;; break;
		  case 'q': quit=1; break;
		}
	}

	if (help)
	{
		printf("\r\n%s [-q] [-n]\tGo to deployment mode\r\n"
			   "\t[-q] Just query current mode\r\n"
			   "\t[-n] Turn off deployment mode\r\n\n", argv[0]);
		return(OK);
	}

	if (n)
		setDeploymentMode(FALSE);
	else if (!quit)
		setDeploymentMode(TRUE);
	
	printf("\r\nDeployment mode = %s\r\n", getDeploymentMode() ? "ON" : "OFF");
	return(OK);
}


/************************************************************************/
/* Function	   : resetConfirm											*/
/* Purpose	   : Confirm user command									*/
/* Inputs	   : None													*/
/* Outputs	   : TRUE if user confirm, else FALSE						*/
/************************************************************************/
MBool resetConfirm(void)
{
	int		c;

	printf("Are you really sure?  ");
	c = ser_getc_tmout(getConsole(), 30*TICKS_PER_SECOND);
	newline();
	return((c == 'Y') || (c == 'y'));
}


/************************************************************************/
/* Function	   : resetCmd												*/
/* Purpose	   : Reset the system										*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK, if it ever returns at all							*/
/************************************************************************/
CmdRtn resetCmd(int argc, char **argv)
{
	printf("\r\nThis could cause permanent loss of communication.\r\n");
	if (!resetConfirm())
		return(OK);

	sysLog("Resetting system by user request");
	fileClose();

	picSoftReset();
	return(OK);
}


/************************************************************************/
/* Function	   : recoverCmd												*/
/* Purpose	   : Recover the system										*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK, if it ever returns at all							*/
/************************************************************************/
CmdRtn recoverCmd(int argc, char **argv)
{
	int			opt, help=0;

    while ((opt = getopt(argc, argv, "h")) != -1)
	{
        if (opt == 'h')
			help = 1;
	}

	if (help)
	{
		printf("\r\nRecover the system. Closes files and waits forever\r\n");
		return(OK);
	}

	if (resetConfirm())
	{
		fileClose();
		printf("Now power off\r\n");
		while(TRUE)
			;
	}

	return(OK);

} /* recoverCmd() */


/************************************************************************/
/* Function	   : syslogCmd												*/
/* Purpose	   : Command-line command to write to syslog				*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK														*/
/************************************************************************/
CmdRtn syslogCmd(int argc, char **argv)
{
	int		i;

	newline();
	memset(syslogBuf, 0, sizeof(syslogBuf));
	
	for (i = 1; i < argc; i++)
		strcat(syslogBuf, argv[i]);

	sysLog(syslogBuf);
	return(OK);

} /* syslogCmd() */

/************************************************************************/
/* Function	   : timeCmd												*/
/* Purpose	   : Get/Set Time and Date									*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK														*/
/************************************************************************/
CmdRtn timeCmd(int argc, char **argv)
{
	time_t			oldSecs, newSecs;
	struct tm		*newtime;
	int				i, n, year, mon, day, hour, min, sec;
	MBool			changed = FALSE;

	oldSecs = newSecs = clkTime();
	newtime = gmtime(&oldSecs);					/* Init newtime in case	*/
												/* user input has no date*/
	for (i = 1; i < argc; i++)
	{
		if (sscanf(argv[i], " %u/%u/%u", &year, &mon, &day) >= 3)
		{
			if	(year < YEAR0)					/* If 2 digit year & < 70 */
				year += 100;					/*	use 21st century	  */
			else if (year >= 1900)				/* If 4 digit year, adjust*/
				year -= 1900;					/*for mktime (offset 1900)*/
			newtime->tm_year = year;			/* Copy into struct tm	  */
			newtime->tm_mon = mon -1;			/* Normalize month		  */
			newtime->tm_mday = day;	
			changed = TRUE;
		}
		else if ((n = sscanf(argv[i], " %u:%u:%u", &hour, &min, &sec)) >= 2)
		{
			newtime->tm_hour = hour;
			newtime->tm_min = min;
			newtime->tm_sec = (n > 2) ? sec : 0;
			changed = TRUE;
		}
	}

	if (changed)
		if ((newSecs = mktime(newtime)) != -1)
			clkSetTime(newSecs);

	clkPrintTime(newSecs);
	newline();

	return( OK );

} /* timeCmd() */


/************************************************************************/
/* Function	   : analogCmd												*/
/* Purpose	   : Command to read A/D channel(s)							*/
/* Inputs	   : CmdInfoPtr												*/
/* Outputs	   : NULL if OK, else error message							*/
/************************************************************************/
CmdRtn analogCmd(int argc, char **argv)
{
	Nat16		val;
	Flt32		engValue;
	char		*units;
	int			i, opt, chan=0, help=0, navg=1, nchans=1;

    while ((opt = getopt(argc, argv, "a:hn:")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'a': navg = atoi(optarg); break;
		  case 'n': nchans = atoi(optarg); break;
		}
	}

	if (help)
	{
		printf("\r\nANALOG\tRead analog channel(s)\r\n"
			   "ANALOG [-a<n>] [-n<n>] [-p[n]] <chan>\r\n"
			   "\t [-a<n>] Average <n> samples\r\n"
			   "\t [-n<n>] Read <n> channels\r\n");
		return(OK);
	}

	if (argc > optind)
		chan = atoi(argv[optind]);
	else
		nchans = 6;

	for (i = chan; i < chan+nchans; i++)
	{
		if (navg > 1)
			val = adcSampleAvg(i, navg);
		else
			val = adcSample(i);
		engValue = adcEngValue(i, val, &units);
		printf("Channel %d = %u counts %5.2f volts %6.3f %s\r\n",
			   i, val, RAW_TO_VOLTS(val), engValue, units);
	}

	return(OK);

} /* AnalogCmd() */


Errno splitAndDecimate(char *fname, int nsplit, int ndec)
{
	return(OK);
}


/************************************************************************/
/* Function	   : sendEvent												*/
/* Purpose	   : Send a compressed event file via YModem or ZModem		*/
/* Inputs	   : Evt num, split factor, decimate factor, protocol		*/
/* Outputs	   : Errno													*/
/************************************************************************/
MLocal Errno sendEvent(long eventNum, int split, int decimate,
					   SendProtocol protocol)
{
	int			result = 0;
	int			num;
	FILINFO		finfo;
	FSIZE_t		size;
	char		fname[32], suffix[8];

	getDataFileName(eventNum, "EVT", fname);

	if (((decimate > 1) || (split > 1)) &&
		(splitAndDecimate(fname, split, decimate) == OK))
	{
		for (num = 0; num < split; num++)
		{
			sprintf(suffix, "E%02u", num);
			getDataFileName(eventNum, suffix, fname);
			
			switch(protocol)
			{
			  case YMODEM:
				size = 0;
				if (f_stat(fname, &finfo) == FR_OK)
					size = finfo.fsize;
				result = ymdmSendFile(fname, size, syslogBuf);
				break;

			  default:
				result = zmSendFiles(fname, 0, 1024, 0);
			}

			printf("\r\n%s: result = %d\r\n", fname, result);

			if (result == OK)
			{
				printf("Erasing %s\r\n", fname);
				unlink(fname);
			}
			else
				return(ERROR);
		}
	}
	else
	{
		switch(protocol)
		{
		  case YMODEM:
			size = 0;
			if (f_stat(fname, &finfo) == FR_OK)
				size = finfo.fsize;
			result = ymdmSendFile(fname, size, syslogBuf);
			break;

		  default:
			result = zmSendFiles(fname, 0, 1024, 0);
		}
	}

	return(result==0 ? OK : ERROR);

} /* sendEvent() */


/************************************************************************/
/* Function	   : displayIndexEntry										*/
/* Purpose	   : Display one index entry								*/
/* Inputs	   : IdxRcd pointer											*/
/* Outputs	   : None													*/
/************************************************************************/
MLocal void displayIndexEntry(IdxRcd *idxp)
{
	struct tm	*tmp;
	int			fileNum;
	Flt32		fmaxVal;

	tmp = gmtime(&idxp->startTime);
	fmaxVal = (float)(idxp->maxVal) / 65536.0f;
	idxp->fileName[15]='\0';
	if (sscanf(&idxp->fileName[3], "%d", &fileNum) <= 0)
		fileNum = -1;

	printf("%4d	 %04d/%02d/%02d %02d:%02d:%02d.%03d %4d.%03u %7.4f  %s\r\n",
		   fileNum, tmp->tm_year+1900, tmp->tm_mon+1, tmp->tm_mday,
		   tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
		   idxp->startMs, idxp->duration/1000, idxp->duration%1000,
		   fmaxVal, idxp->fileName);

} /* displayIndexEntry() */


/************************************************************************/
/* Function	   : showIndexFunc											*/
/* Purpose	   : Function for more() to show one index entry			*/
/* Inputs	   : Line number, IndexStruct								*/
/* Outputs	   : TRUE if found entry, else FALSE						*/
/************************************************************************/
MLocal MBool showIndexFunc(int lineNo, IndexStruct *ip)
{
	if (lineNo >= ip->entries)
		return(FALSE);

	displayIndexEntry(&ip->index[lineNo]);

	return(TRUE);

} /* showIndexFunc() */


/************************************************************************/
/* Function	   : showIndexAltFunc										*/
/* Purpose	   : Alternate function for more() to show one index entry	*/
/* Inputs	   : Line number, FIL pointer								*/
/* Outputs	   : TRUE if found entry, else FALSE						*/
/************************************************************************/
MLocal MBool showIndexAltFunc(int lineNo, FIL *fp)
{
	IdxRcd		idxRec;

	if (!getNextRec(fp, IndexType, (RcdUnion *)&idxRec))
		return(FALSE);

	displayIndexEntry(&idxRec);

	return(TRUE);

} /* showIndexAltFunc() */


/************************************************************************/
/* Function	   : showIndexEntries										*/
/* Purpose	   : Display IndexRcd entries for .IDX file					*/
/* Inputs	   : Index file name, compare func for ordering, num lines for more*/
/* Outputs	   : NULL or error string									*/
/************************************************************************/
MLocal Errno showIndexEntries(char *fname, MBool (*compareFunc)(), int numLines)
{
	IndexStruct *ip;

	if ((ip = createSortedIndex(fname, compareFunc)) == NULL)
	{
		if (f_open(&ifp, fname, FA_READ) != FR_OK)
			return(ERROR);
		printf("\r\nProblem opening or sorting index file.  Printing in unsorted time order.\r\n");
	}

	printf("\r\nEvent          Start Time         Duration  Max G  File Name\r\n");

	if (ip == NULL)
	{
		more(numLines, showIndexAltFunc, &ifp);
		f_close(&ifp);
	}
	else
	{
		more(numLines, showIndexFunc, ip);
		free(ip);
	}

	return(OK);

} /* showIndexEntries() */


/************************************************************************/
/* Function	   : EventCmd												*/
/* Purpose	   : Command-line command to display and send events		*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn EventCmd(int argc, char **argv)
{
	int			i, opt, sends = 0;
	Errno		result;
	int			help=0, ym=0, tm = 0;
	int			n = 10, dec = 1, split = 1;
	SendProtocol protocol = ZMODEM;

    while ((opt = getopt(argc, argv, "hn:d:s:ty")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'n': n = atoi(optarg); break;
		  case 'd': dec= atoi(optarg); break;
		  case 's': split= atoi(optarg); break;
		  case 't': tm=1; break;
		  case 'y': protocol = YMODEM; break;
		}
	}

	if (help)
	{
		printf("EVENT [-t] [-n<n>] to display events\r\n"
			   "\t[-t] display in reverse time order (defaults to magnitude order)\r\n"
			   "\t[-n<n>] display <n> lines at a time (default 10)\r\n"
			   "EVENT [-d<dec>] [-s<sp>] <n> to send event [n] via ZModem or Kermit\r\n"
			   "\t[-d<dec>] decimate value by factor <dec>\r\n"
			   "\t[-s<sp>]	split file <sp> ways (2-99)\r\n"
			   "\t[-y] to send via YModem (dflt is ZModem)\r\n\r\n");
		return(OK);
	}

	newline();

	for (i = optind; i < argc; i++)
		if (atoi(argv[i]) >= 0)
		{
			if ((result = sendEvent(atoi(argv[i]), split, dec, protocol)) == OK)
				return(result);
			sends++;
		}

	if (sends == 0)
	{
		if (tm)
			return(showIndexEntries(eventIdxName, trueFunc, n));
		else
			return(showIndexEntries(eventIdxName, magnitudeFunc, n));
	}

	return(OK);

} /* EventCmd() */


/************************************************************************/
/* Function	   : WatchCmd												*/
/* Purpose	   : Command-line command to display watch cycles			*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn WatchCmd(int argc, char **argv)
{
	int			opt, help = 0, n = 10;

    while ((opt = getopt(argc, argv, "hn:")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'n': n = atoi(optarg); break;
		}
	}

	if (help)
	{
		printf("\r\nWATCH [-n<n>] to display watch cycles\r\n"
			   "\t[-n<n>] display <n> lines at a time (default 10)\r\n\n");
		return(OK);
	}

	return(showIndexEntries(watchIdxName, trueFunc, n));

} /* WatchCmd() */


/************************************************************************/
/* Function	   : DecimateCmd											*/
/* Purpose	   : Command-line Decimate and split files					*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn DecimateCmd(int argc, char **argv)
{
	int			opt, help = 0, n = 10, dec=1, split=1;
	int			index;
	Errno		rtn;

    while ((opt = getopt(argc, argv, "hn:d:s:")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'n': n = atoi(optarg); break;
		  case 'd': dec= atoi(optarg); break;
		  case 's': split= atoi(optarg); break;
		}
	}

	if (help)
	{
		printf("\r\n%s [-d<dn>] [-s<sn>] <filename> Decimate and/or split file\r\n"
			   "\t[-d<dn>] to decimate file by factor of <dn>.\r\n"
			   "\t\tE.g., if <dn>=10, decimate 50Hz event to 5Hz\r\n"
			   "\t[-s<sn>] to split the file into <sn> parts\r\n"
			   "\t<filename> File to decimate or split.\r\n",
			   argv[0]);
		return(OK);
	}

	printf("\r\nDecimate/split file %s, dec=%d, split=%d\r\n", argv[optind], dec, split);
	clkDelayMs(1000);

	rtn = splitAndDecimate(argv[optind], split, dec);

	printf("done\r\n");
	return(rtn);

} /* DecimateCmd() */


/************************************************************************/
/* Function	   : SysRecCmd												*/
/* Purpose	   : Command-line command to display system records			*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn SysRecCmd(int argc, char **argv)
{
	time_t		startTime=0, now, nextSysRec;
	Int32		duration=1440, interval=1;
	int			opt, help=0, ym=0, tm;
	int			recType;
	IdxRcd		idxRec;
	SystemRcd	sysRec;
	FileHdr		hdr;
	Nat32		bw;
	struct tm	*tmp;
	FSIZE_t		fsize;
	short		result;
	char		fname[32];

    while ((opt = getopt(argc, argv, "hd:s:t:y")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'd': duration = getDuration(optarg); break;
		  case 's': startTime = getTimespec(optarg); break;
		  case 't': interval = getDuration(optarg); break;
		  case 'y': ym=1; break;
		}
	}

	if (help)
	{
		printf("\r\n%s\tGet System Records\r\n"
			   "%s [-s <timespec>] [-d <n[s|m|h|d]>] [-y]\r\n"
			   "\t [-s <timespec>] Starting time\r\n"
			   "\t [-d <n[s|m|h|d]>] Duration in seconds|minutes|hours|days\r\n"
			   "\t [-t <n[s|m|h|d]>] Display one sysrec every n seconds|minutes|hours|days\r\n"
			   "\t [-y] Send as file via Ymodem\r\n",
			   argv[0], argv);
		return(OK);
	}

	newline();
	now = clkTime();

	if (startTime == 0)
		startTime = now - duration;

	nextSysRec = startTime;

	if (f_open(&ifp, watchIdxName, FA_READ) != FR_OK)
		return(ERROR);
	
	if (ym)
	{
		sprintf(fname, "SR%04d.DAT", oFileIndex++);
		if (f_open(&ofp, fname, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
			return(ERROR);
		hdr.recType = FileHdrType;
		hdr.rsvd = 0;
		hdr.fmtVersion = FMT_VERSION;
		hdr.platformID = (Nat16)(platformID & 0xffff);
		hdr.dataRate = 0;
		hdr.startTime = startTime;
		hdr.startMs = 0;
		hdr.duration = duration;
		f_write(&ofp, &hdr, sizeof(hdr), &bw);
	}
	else
	{
		tmp = gmtime(&startTime);
		printf("Returning sys recs starting %04d/%02d/%02d %02d:%02d:%02d duration %d interval %d\r\n",
			   tmp->tm_year+1900, tmp->tm_mon+1, tmp->tm_mday,
			   tmp->tm_hour, tmp->tm_min, tmp->tm_sec, duration, interval);
	}

	while (getNextRec(&ifp, IndexType, (RcdUnion *)&idxRec))
	{
		if ((idxRec.startTime <= (startTime + duration)) &&
			((idxRec.startTime + idxRec.duration/1000) >= nextSysRec))
		{								/* Got a watch file in correct time */
			idxRec.fileName[15]='\0';
			if (f_open(&dfp, idxRec.fileName, FA_READ) == FR_OK)
			{
				while (getNextRec(&dfp, SysRecType, (RcdUnion *)&sysRec))
				{
					if (sysRec.rcdTime > (startTime + duration))
						break;
					if (sysRec.rcdTime >= nextSysRec)
					{
						if (ym)
							f_write(&ofp, &sysRec, sizeof(sysRec), &bw);
						else
						{
							tmp = gmtime(&sysRec.rcdTime);
							printf("%02d/%02d/%04d %02d:%02d:%02d Batt %5.2fV "
								   "Vmodem %5.2fV ExtPress %6.3f bar IntPress %5.2f psia "
								   "Temp %4.1f degC Hum %4.1f%%\r\n",
								   tmp->tm_mon+1, tmp->tm_mday, tmp->tm_year+1900,
								   tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
								   RAW_TO_BATTVOLTS(sysRec.battVoltage),
								   RAW_TO_BATTVOLTS(sysRec.minModemBatt),
								   adcEngValue(EXT_PRESS_CHAN, sysRec.extPressure, NULL),
								   adcEngValue(INT_PRESS_CHAN, sysRec.intPressure, NULL),
								   adcEngValue(TEMP_CHAN, sysRec.intTemp, NULL),
								   adcEngValue(HUMIDITY_CHAN, sysRec.intHumidity, NULL));
						}

						nextSysRec = sysRec.rcdTime + interval;
					}
					if (kbhit())
						break;
				}
				f_close(&dfp);
			}
		}

		if (kbhit())
			break;
	}

	f_close(&ifp);

	if (ym)
	{
		fsize = f_tell(&ofp);
		f_close(&ofp);
		printf("\r\nSet your terminal program to receive YModem\r\n");
		serWaitTxComplete(getConsole());
		ymdmSendFile(fname, fsize, syslogBuf);
		sysLogPrintf("Sent %s via YModem, result = %d", fname, result);
		unlink(fname);
	}

	return(OK);

} /* SysRecCmd() */


/************************************************************************/
/* Function	   : ZSCmd													*/
/* Purpose	   : ZModem Send with Wildcards Command						*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn	ZSCmd(int argc, char **argv)
{
	int			opt, index, rtn, verbose=0, help=0;
	unsigned	window=1024, framelen=0;

    while ((opt = getopt(argc, argv, "hl:v:w:")) != -1)
	{
        switch (opt)
		{
		  case 'h': help=1; break;
		  case 'l': framelen = atoi(optarg); break;
		  case 'v': verbose = atoi(optarg); break;
		  case 'w': window = atoi(optarg); break;
		}
	}

	newline();

	if (help)
	{
		printf("%s [-v<n>] [-w<n>] [-l<n>] - Send file via ZModem protocol\r\n"
			   "\t [-v<n>] Verbosity level (0-8)\r\n"
			   "\t [-w<n>] Window size (>= 256)\r\n"
			   "\t [-l<n>] Frame length (32<=n<=1024)\r\n",
			   argv[0]);
		return(OK);
	}

	if (argc < optind + 1)
	{
		printf("No file specified\r\n");
		return(ERROR);
	}

	for(index = optind; index < argc; index++)
		if ((rtn = zmSendFiles(argv[index], verbose, window, framelen)) != OK)
			break;

	clkDelayMs(1000);
	serRxFlush(getConsole());
	return((rtn == OK) ? OK : ERROR);
							  
} /* ZSCmd() */


#ifdef DEBUG_TIME

/************************************************************************/
/* Function	   : TimeTestCmd											*/
/* Purpose	   : Command-line command to test time parsing				*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn timeTestCmd(int argc, char **argv)
{
	time_t		t;
	struct tm	*tmp;

	if (argc < 2)
		printf("\r\nTest by passing strings of the form mm/dd/yyyyThh:mm:ss\r\n");
	else
	{
		printf("\r\ngetTimespec(\"%s\") returns ", argv[1]);
		if ((t = getTimespec(argv[1])) == 0)
			printf("%s\r\n", timespecErr);
		else if ((tmp = gmtime(&t)) == NULL)
			printf("%d, but gmtime() returns ERROR\r\n", t);
		else
			printf("%d = %d/%d/%d %02d:%02d:%02d\r\n",
				   t, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_year+1900,
				   tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
	}

	return(OK);

} /* TimeTestCmd() */


/************************************************************************/
/* Function	   : DurTestCmd												*/
/* Purpose	   : Command-line command to test time parsing				*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn durTestCmd(int argc, char **argv)
{
	if (argc < 2)
		printf("\r\nusage: DurTest <n>\r\n");
	else
		printf("\r\n\ngetDuration(\"%s\") returns %d\r\n",
			   argv[1], getDuration(argv[1]));

	return(OK);

} /* DurTestCmd() */

#endif /* DEBUG_TIME */
