// CommsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Dashboard.h"
#include "CommsDlg.h"
#include "DashboardRecipient.h"
#include "NmeaDlg.h"
#include "DashboardDlg.h"
#include "LogListener.h"
#include "TopsideLogDlg.h"

#include <remote/MMAhrs.h>
#include <remote/MMDepthSensor.h>
#include <remote/MMNavigation.h>
#include <remote/MMTailcone.h>
#include <remote/MMAlarm.h>
#include <remote/MMHoming.h>
#include <remote/MMGps.h>
#include <remote/MMPower.h>
#include <remote/MMDeviceInfo.h>
#include <remote/MMDvl.h>
#include <remote/MMDynamicControl.h>
#include <remote/MMDropWeight.h>
#include <remote/MMString.h>
#include <remote/MMNmea.h>
#include <remote/ModemBroker.h>
//#include <remote/Broker.h>
//#include <remote/ModemController.h>
//#include <remote/ModemIF.h>
#include <remote/ModemSocket.h>
#include <remote/ModemSerial.h>

#include <utils/Attributes.h>
#include <utils/IntegerAttribute.h>
#include <utils/StringAttribute.h>
#include <utils/BooleanAttribute.h>
#include <utils/AttributeParser.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//for getting connected status out

static bool m_Connected;

#define CONNECT_REMOTE 1
#define COMMSDLGCONFIG "CommsDlg.cfg"

#define DEFAULT_IP "192.168.0.1"
#define DEFAULT_CON False
#define DEFAULT_PORT "COM1"
#define DEFAULT_BAUD "2400"

/////////////////////////////////////////////////////////////////////////////
// CCommsDlg dialog


CCommsDlg::CCommsDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CCommsDlg::IDD, pParent)
{
	m_active = FALSE;
	m_nmeaDlg = NULL;

	// Init simple serial
	m_devNmeaIn = NULL;
	m_devNmeaOut = NULL;
	m_devRtcmIn = NULL;
	m_devUsbl = NULL;

	// Init modem system
	m_pModemBroker = NULL;
	m_pModemSocket1 = NULL;
	m_pModemSocket2 = NULL;
	m_pModemSerial1 = NULL;

	// Default startup state
	m_cycle = false;
	m_socketAlive1 = false;
	m_socketAlive2 = false;
	m_serialAlive1 = false;

	sprintf(m_nmeaBuf,"");
	sprintf(m_rtcmBuf,"");

	EnumerateSerialPorts(m_ports);

	loadConfiguration();

	m_socketConnection1 = FALSE;
	m_socketConnection2 = FALSE;
	
	m_serialConnection1 = FALSE;
	m_serialConnection2 = FALSE;
	m_serialConnection3 = FALSE;
	m_serialConnection4 = FALSE;
	m_serialConnection5 = FALSE;

	m_fix1 = -1;
	m_fix2 = -2;

	m_rtcmFailCount = 0;
	m_usblFailCount = 0;

	m_mw = false;
	
	//udp listener
	m_logListener = new LogListener();
	
	/*
	//{{AFX_DATA_INIT(CCommsDlg)
	m_socketConnection1 = FALSE;
	m_serialConnection2 = FALSE;
	m_serialConnection1 = FALSE;
	m_baudSelection2 = 9600;
	m_baudSelection1 = 9600;
	m_serialOn1 = FALSE;
	m_serialOn2 = FALSE;
	m_socketOn1 = FALSE;
	m_socketConnection2 = FALSE;
	m_socketOn2 = FALSE;
	m_baudSelection3 = 9600;
	m_serialConnection3 = FALSE;
	m_serialOn3 = FALSE;
	m_baudSelection4 = 9600;
	m_serialConnection4 = FALSE;
	m_serialOn4 = FALSE;
	m_serialSelection1 = 1;
	m_serialSelection2 = 1;
	m_serialSelection3 = 1;
	m_serialSelection4 = 1;
	m_serialSelection5 = 1;
	m_serialPort1 = "COM1";
  	m_serialPort2 = "COM1";
	m_serialPort3 = "COM1";
  	m_serialPort4 = "COM1";
	m_serialPort5 = "COM1";
	m_MessageWatcherString = _T("");
	m_serialConnection5 = FALSE;
	m_baudSelection5 = 9600;
	//}}AFX_DATA_INIT
	*/

}


void CCommsDlg::DoDataExchange(CDataExchange* pDX)
{
	m_pDX = pDX;

	CDialog::DoDataExchange(pDX);
	if (!m_mw) {
	//{{AFX_DATA_MAP(CCommsDlg)
	DDX_Control(pDX, IDC_BAUD5, m_baudCombo5);
	DDX_Control(pDX, IDC_SERIAL_PORT5, m_serialCombo5);
	DDX_Control(pDX, IDC_MESSAGEWATCHER, m_MessageWatcher);
	DDX_Control(pDX, IDC_SERIAL_PORT4, m_serialCombo4);
	DDX_Control(pDX, IDC_SERIAL_PORT3, m_serialCombo3);
	DDX_Control(pDX, IDC_SERIAL_PORT2, m_serialCombo2);
	DDX_Control(pDX, IDC_SERIAL_PORT1, m_serialCombo1);
	DDX_Control(pDX, IDC_BAUD4, m_baudCombo4);
	DDX_Control(pDX, IDC_BAUD3, m_baudCombo3);
	DDX_Control(pDX, IDC_BAUD2, m_baudCombo2);
	DDX_Control(pDX, IDC_BAUD1, m_baudCombo1);
	DDX_Control(pDX, IDC_SOCKET_ADDRESS2, m_socket2);
	DDX_Control(pDX, IDC_SOCKET_ADDRESS1, m_socket1);
	DDX_OCBool(pDX, IDC_SOCKET_CONNECT1, DISPID(2), m_socketConnection1);
	DDX_OCBool(pDX, IDC_SERIAL_CONNECT2, DISPID(2), m_serialConnection2);
	DDX_OCBool(pDX, IDC_SERIAL_CONNECT1, DISPID(2), m_serialConnection1);
	DDX_Text(pDX, IDC_BAUD2, m_baudSelection2);
	DDX_Text(pDX, IDC_BAUD1, m_baudSelection1);
	DDX_OCBool(pDX, IDC_SOCKET_CONNECT2, DISPID(2), m_socketConnection2);
	DDX_Text(pDX, IDC_BAUD3, m_baudSelection3);
	DDX_OCBool(pDX, IDC_SERIAL_CONNECT3, DISPID(2), m_serialConnection3);
	DDX_Text(pDX, IDC_BAUD4, m_baudSelection4);
	DDX_OCBool(pDX, IDC_SERIAL_CONNECT4, DISPID(2), m_serialConnection4);
	DDX_CBIndex(pDX, IDC_SERIAL_PORT1, m_serialSelection1);
	DDX_CBIndex(pDX, IDC_SERIAL_PORT2, m_serialSelection2);
	DDX_CBIndex(pDX, IDC_SERIAL_PORT3, m_serialSelection3);
	DDX_CBIndex(pDX, IDC_SERIAL_PORT4, m_serialSelection4);
	DDX_Text(pDX, IDC_SERIAL_PORT1, m_serialPort1);
	DDX_Text(pDX, IDC_SERIAL_PORT2, m_serialPort2);
	DDX_Text(pDX, IDC_SERIAL_PORT3, m_serialPort3);
	DDX_Text(pDX, IDC_SERIAL_PORT4, m_serialPort4);
	DDX_Text(pDX, IDC_MESSAGEWATCHER, m_MessageWatcherString);
	DDX_OCBool(pDX, IDC_SERIAL_CONNECT5, DISPID(2), m_serialConnection5);
	DDX_Text(pDX, IDC_BAUD5, m_baudSelection5);
	DDX_Text(pDX, IDC_SERIAL_PORT5, m_serialPort5);
	DDX_CBIndex(pDX, IDC_SERIAL_PORT5, m_serialSelection5);
	DDX_Control(pDX, IDC_MESSAGEGUAGE, m_MessageGuageControl);
	//}}AFX_DATA_MAP
	} else {
		DDX_Control(pDX, IDC_MESSAGEWATCHER, m_MessageWatcher);
		DDX_Text(pDX, IDC_MESSAGEWATCHER, m_MessageWatcherString);
	}

	if (!m_active) {
		DDX_OCBool(pDX, IDC_SOCKET_ON1, DISPID(2), m_socketOn1);
		DDX_OCBool(pDX, IDC_SOCKET_ON2, DISPID(2), m_socketOn2);
		DDX_OCBool(pDX, IDC_SERIAL_ON1, DISPID(2), m_serialOn1);
		DDX_OCBool(pDX, IDC_SERIAL_ON2, DISPID(2), m_serialOn2);
		DDX_OCBool(pDX, IDC_SERIAL_ON3, DISPID(2), m_serialOn3);
		DDX_OCBool(pDX, IDC_SERIAL_ON4, DISPID(2), m_serialOn4);
		DDX_OCBool(pDX, IDC_SERIAL_ON5, DISPID(2), m_serialOn5);
	}
}

BOOL CCommsDlg::OnInitDialog()
{
	BOOL val = CDialog::OnInitDialog();
	return val;
}

bool CCommsDlg::getConnected()
{
	return m_Connected;
}

void CCommsDlg::setLogDlg(CTopsideLogDlg *l)
{
	if(m_logListener != NULL) {
		m_logListener->setLogger(l);
	}
}

void CCommsDlg::addBaudToCombos(char *str)
{
	m_baudCombo1.AddString(str);
	m_baudCombo2.AddString(str);
	m_baudCombo3.AddString(str);
	m_baudCombo4.AddString(str);
	m_baudCombo5.AddString(str);
}

void CCommsDlg::InitStuff()
{
	if (m_baudCombo1.GetCount() == 0) {
	char defaultPort[5];
	for (int i=0; i<m_ports.GetSize(); i++) { // enumeratePorts seems to have different behavior on different machines, kludgy...
		if (m_ports.ElementAt(i) > 0) {
			sprintf(defaultPort,"COM%d",m_ports.ElementAt(i));
			m_serialCombo1.AddString(defaultPort);
			m_serialCombo2.AddString(defaultPort);
			m_serialCombo3.AddString(defaultPort);
			m_serialCombo4.AddString(defaultPort);
			m_serialCombo5.AddString(defaultPort);
		}
	}	

	addBaudToCombos("300");
	addBaudToCombos("1200");
	addBaudToCombos("2400");
	addBaudToCombos("4800");
	addBaudToCombos("9600");
	addBaudToCombos("19200");
	addBaudToCombos("38400");
	addBaudToCombos("57600");
	addBaudToCombos("115200");
	addBaudToCombos("230400");

	char tmp[32];
	sprintf(tmp,"%d",m_baudSelection1);
	m_baudCombo1.SelectString(-1,tmp);
	sprintf(tmp,"%d",m_baudSelection2);
	m_baudCombo2.SelectString(-1,tmp);
	sprintf(tmp,"%d",m_baudSelection3);
	m_baudCombo3.SelectString(-1,tmp);
	sprintf(tmp,"%d",m_baudSelection4);
	m_baudCombo4.SelectString(-1,tmp);
	sprintf(tmp,"%d",m_baudSelection5);
	m_baudCombo5.SelectString(-1,tmp);

	m_serialCombo1.SelectString(-1,m_serialPort1);
	m_serialCombo2.SelectString(-1,m_serialPort2);
	m_serialCombo3.SelectString(-1,m_serialPort3);
	m_serialCombo4.SelectString(-1,m_serialPort4);
	m_serialCombo5.SelectString(-1,m_serialPort5);
	
	
	BYTE b1,b2,b3,b4;
	splitIPAddress(m_socketAddress1,&b1,&b2,&b3,&b4);
	m_socket1.SetAddress(b1,b2,b3,b4);

	splitIPAddress(m_socketAddress2,&b1,&b2,&b3,&b4);
	m_socket2.SetAddress(b1,b2,b3,b4);
	
	m_active = true;
	}
}


CCommsDlg::~CCommsDlg()
{
	

	if (m_pModemBroker) delete m_pModemBroker;

	free(m_socketAddress1);
	free(m_socketAddress2);
/*
	if (m_pModemSocket1 != NULL) {
			((ModemFork *) m_pModemSocket1)->stop();
			delete m_pModemSocket1;
			m_pModemSocket1 = NULL;
	}

	if (m_pModemSocket2 != NULL) {
			((ModemFork *) m_pModemSocket2)->stop();
			delete m_pModemSocket2;
			m_pModemSocket2 = NULL;
	}

	if (m_pModemSerial1 != NULL) {
			((ModemFork *) m_pModemSerial1)->stop();
			delete m_pModemSerial1;
			m_pModemSerial1 = NULL;
	}
*/
	if (m_devNmeaIn != NULL) {
			delete m_devNmeaIn;
			m_devNmeaIn = NULL;
	}
	if (m_devNmeaOut != NULL) {
			delete m_devNmeaOut;
			m_devNmeaOut = NULL;
	}

	if (m_devRtcmIn != NULL) {
			delete m_devRtcmIn;
			m_devRtcmIn = NULL;
	}

	if (m_devUsbl != NULL) {
			delete m_devUsbl;
			m_devUsbl = NULL;
	}
}


void CCommsDlg::loadConfiguration()
{
	char *buf1, *buf2, *buf3, *buf4, *buf5;
	char *baud1, *baud2, *baud3, *baud4, *baud5;
	char *sock1, *sock2;
	unsigned char boola, boolb, bool1, bool2, bool3, bool4, bool5;
	Attributes attributes("CommsDlg");

	attributes.add(new StringAttribute("socketAddress1","IP Address", &sock1, DEFAULT_IP));
	attributes.add(new StringAttribute("socketAddress2","IP Address", &sock2, DEFAULT_IP));

	attributes.add(new StringAttribute("serialPort1","COM port", &buf1, DEFAULT_PORT));
	attributes.add(new StringAttribute("baudRate1","COM Baud Rate", &baud1, DEFAULT_BAUD));	
	attributes.add(new StringAttribute("serialPort2","COM port", &buf2, DEFAULT_PORT));
	attributes.add(new StringAttribute("baudRate2","COM Baud Rate", &baud2, DEFAULT_BAUD));	
	attributes.add(new StringAttribute("serialPort3","COM port", &buf3, DEFAULT_PORT));
	attributes.add(new StringAttribute("baudRate3","COM Baud Rate", &baud3, DEFAULT_BAUD));	
	attributes.add(new StringAttribute("serialPort4","COM port", &buf4, DEFAULT_PORT));
	attributes.add(new StringAttribute("baudRate4","COM Baud Rate", &baud4, DEFAULT_BAUD));	
	attributes.add(new StringAttribute("serialPort5","COM port", &buf5, DEFAULT_PORT));
	attributes.add(new StringAttribute("baudRate5","COM Baud Rate", &baud5, DEFAULT_BAUD));	

	attributes.add(new BooleanAttribute("socketOn1","Socket1 Connected", &boola, DEFAULT_CON));
	attributes.add(new BooleanAttribute("socketOn2","Socket2 Connected", &boolb, DEFAULT_CON));
	attributes.add(new BooleanAttribute("serialOn1","Serial1 Connected", &bool1, DEFAULT_CON));
	attributes.add(new BooleanAttribute("serialOn2","Serial2 Connected", &bool2, DEFAULT_CON));
	attributes.add(new BooleanAttribute("serialOn3","Serial3 Connected", &bool3, DEFAULT_CON));
	attributes.add(new BooleanAttribute("serialOn4","Serial4 Connected", &bool4, DEFAULT_CON));
	attributes.add(new BooleanAttribute("serialOn5","Serial5 Connected", &bool5, DEFAULT_CON));

	if(m_homeDir.IsEmpty()) {
		char temp[128];
		GetCurrentDirectory(128,temp);
		m_homeDir = temp;
	}

	CString path = m_homeDir+"\\"+COMMSDLGCONFIG;

	try{
		AttributeParser::parse(path.GetBuffer(0), &attributes);
	} catch(Exception e) {
		CString hold = e.msg;
		CString temp = hold+"CommsDlg config was not successfully loaded. Comms parameters set to defaults.";
		MessageBox(temp.GetBuffer(0));
		TRACE("AttributeParser in CommsDlg threw message: %s",
                       e.msg );
	} catch(...) {
		TRACE("Something wrong with attribute parser in comms dialogue\n");
	}

	m_socketAddress1 = sock1;
	m_socketAddress2 = sock2;

	m_serialPort1 = buf1;
	m_serialPort2 = buf2;
	m_serialPort3 = buf3;
	m_serialPort4 = buf4;
	m_serialPort5 = buf5;

	sscanf(baud1,"%d",&m_baudSelection1);
	sscanf(baud2,"%d",&m_baudSelection2);
	sscanf(baud3,"%d",&m_baudSelection3);
	sscanf(baud4,"%d",&m_baudSelection4);
	sscanf(baud5,"%d",&m_baudSelection5);
	
	m_socketOn1 = boola;
	m_socketOn2 = boolb;
	m_serialOn1 = bool1;
	m_serialOn2 = bool2;
	m_serialOn3 = bool3;
	m_serialOn4 = bool4;
	m_serialOn5 = bool5;

	
	free(buf1);
	free(buf2);
	free(buf3);
	free(buf4);
	free(buf5);
	free(baud1);
	free(baud2);
	free(baud3);
	free(baud4);
	free(baud5);
	//free(sock1);
	//free(sock2);
}

void CCommsDlg::storeConfiguration()
{
	char *bufa, *bufb;
	char *buf1, *buf2, *buf3, *buf4, *buf5;
	char str1[8], str2[8], str3[8], str4[8], str5[8];
	long i1, i2, i3, i4, i5;
	unsigned char boola, boolb, bool1, bool2, bool3, bool4, bool5;
	Attributes attributes("CommsDlg");


	attributes.add(new StringAttribute("socketAddress1","IP Address", &bufa, m_socketAddress1));
	attributes.add(new StringAttribute("socketAddress2","IP Address", &bufb, m_socketAddress2));

	m_serialCombo1.GetLBText(m_serialSelection1,str1);
	attributes.add(new StringAttribute("serialPort1","COM port", &buf1, m_serialPort1));
	attributes.add(new IntegerAttribute("baudRate1","COM Baud Rate", &i1, m_baudSelection1));

	m_serialCombo2.GetLBText(m_serialSelection3,str2);
	attributes.add(new StringAttribute("serialPort2","COM port", &buf2, m_serialPort2));
	attributes.add(new IntegerAttribute("baudRate2","COM Baud Rate", &i2, m_baudSelection2));

	m_serialCombo3.GetLBText(m_serialSelection3,str3);
	attributes.add(new StringAttribute("serialPort3","COM port", &buf3, m_serialPort3));
	attributes.add(new IntegerAttribute("baudRate3","COM Baud Rate", &i3, m_baudSelection3));

	m_serialCombo4.GetLBText(m_serialSelection4,str4);
	attributes.add(new StringAttribute("serialPort4","COM port", &buf4, m_serialPort4));
	attributes.add(new IntegerAttribute("baudRate4","COM Baud Rate", &i4, m_baudSelection4));

	m_serialCombo5.GetLBText(m_serialSelection5,str5);
	attributes.add(new StringAttribute("serialPort5","COM port", &buf5, m_serialPort5));
	attributes.add(new IntegerAttribute("baudRate5","COM Baud Rate", &i5, m_baudSelection5));

	attributes.add(new BooleanAttribute("socketOn1","Socket1 Connected", &boola, m_socketOn1));
	attributes.add(new BooleanAttribute("socketOn2","Socket2 Connected", &boolb, m_socketOn2));
	attributes.add(new BooleanAttribute("serialOn1","Serial1 Connected", &bool1, m_serialOn1));
	attributes.add(new BooleanAttribute("serialOn2","Serial2 Connected", &bool2, m_serialOn2));
	attributes.add(new BooleanAttribute("serialOn3","Serial3 Connected", &bool3, m_serialOn3));
	attributes.add(new BooleanAttribute("serialOn4","Serial4 Connected", &bool4, m_serialOn4));
	attributes.add(new BooleanAttribute("serialOn5","Serial5 Connected", &bool5, m_serialOn5));

	CString path = m_homeDir+"\\"+COMMSDLGCONFIG;

	AttributeParser::unparse(path.GetBuffer(0),&attributes,NULL);

	
	free(bufa);
	free(bufb);
	free(buf1);
	free(buf2);
	free(buf3);
	free(buf4);
	free(buf5);
	
}

void CCommsDlg::SaveSettings() {
	UpdateData(TRUE);

	BYTE b1, b2, b3, b4;
	m_socket1.GetAddress(b1,b2,b3,b4);
	if (b1 != 0) sprintf(m_socketAddress1,"%d.%d.%d.%d",b1,b2,b3,b4);
	m_socket2.GetAddress(b1,b2,b3,b4);
	if (b1 != 0) sprintf(m_socketAddress2,"%d.%d.%d.%d",b1,b2,b3,b4);
}


void CCommsDlg::runCycle() {
	// Vehicle Modem System
	int n;

	// Socket connection 1
	if (m_pModemSocket1 && m_socketAlive1) {
		n = m_socketConnection1;
		m_socketConnection1 = m_pModemSocket1->bHasConnectionChild();
		if (n != m_socketConnection1) {
		//	if ((!m_active) && (m_socketConnection1 == 0)) MessageBox("Lost fast socket connection","Lost Connection");
			UpdateData(false);
		}
	}

	// Socket connection 2
	if (m_pModemSocket2 && m_socketAlive2) {
		n = m_socketConnection2;
		m_socketConnection2 = m_pModemSocket2->bHasConnectionChild();
		if (n != m_socketConnection2) {
			//	if ((!m_active) && (m_socketConnection2 == 0)) MessageBox("Lost slow socket connection","Lost Connection");
			UpdateData(false);
		}
	}

	// Serial connection 1
	if (m_pModemSerial1 && m_serialAlive1) {
		n = m_serialConnection1;
		m_serialConnection1 = m_pModemSerial1->bHasConnectionChild();
		if (n != m_serialConnection1) {
			UpdateData(false);
		}
	}

	// Run cycle
	if (CONNECT_REMOTE && (m_socketAlive1 | m_socketAlive2 | m_serialAlive1)) {	
		m_cycle = true;
		m_pModemBroker->runCycle();
		m_cycle = false;
	}

	m_Connected = m_socketConnection1 || m_socketConnection2 || m_serialConnection1;
	m_dialog->setConnected(m_socketConnection1 || m_socketConnection2 || m_serialConnection1);

}


void CCommsDlg::runSerialCycle() 
{
	char tempBuf[256] = "";
	int len;

	if (m_devNmeaIn != NULL) {
		m_devNmeaIn->read(tempBuf, 256, 10);
		if (m_serialConnection2 != false) {
					m_serialConnection2 = false; UpdateData(false);
		}
		for (int i=0;i<=strlen(tempBuf);i++) {
			if ((tempBuf[i] == 0xD) || (tempBuf[i] == 0xA) || (strlen(m_nmeaBuf) > (250))) {
				if ((strlen(m_nmeaBuf) > 10) && ((!strncmp(m_nmeaBuf,"$GPGGA",6)) || (!strncmp(m_nmeaBuf,"$GPGLL",6)))) {		
					if (m_nmeaDlg != NULL) {
						m_nmeaDlg->m_dumpString = m_nmeaBuf;
						m_nmeaDlg->UpdateData(FALSE);
					}
					if (m_serialConnection2 != true) {
						m_serialConnection2 = true; UpdateData(false);
					}
				}
				sprintf(m_nmeaBuf,"");
			} else {
				sprintf(m_nmeaBuf,"%s%c",m_nmeaBuf,tempBuf[i]);
			}
		}
	}
	
	if (m_devRtcmIn != NULL) {
		m_rtcmFailCount++;
		if ((m_rtcmFailCount % 5) == 4) {
			len = m_devRtcmIn->read(tempBuf, 256, 10);
			if ( len > 0 ) {
				TRACE("Got rtcm len %d: ",len);
				for (int k=0;k<len;k++) TRACE("%02x ",tempBuf[k]);
				TRACE("\n");
				m_rtcmFailCount = 0;
				if (m_serialConnection4 != true) {
					m_serialConnection4 = true; UpdateData(false);
				}
				m_recipient->setRtcmString(tempBuf,len);
			} 
		}
		if (m_rtcmFailCount > 20) {
			if (m_serialConnection4 != false) {
				m_serialConnection4 = false; UpdateData(false);
			}
		}
	}

	if (m_devUsbl != NULL) {
		/*
		Assuming that we've properly configured the Surveyor, we expect messages of the type:
		acoustic messages:  "6.1,FixNum,RxPitch,RxRoll,RxHeading,dcl,dcm\n"
		dgps (position) messages:  "6.2,FixNum,East,North\n"
		*/
		m_usblFailCount++;
		if (m_devUsbl->nRecvdBytes() > 0) {
			len = m_devUsbl->read(tempBuf, 256, 100);
			if ( len > 0 ) {
				if (m_serialConnection5 != true) {
					m_serialConnection5 = true; UpdateData(false);
				}
				long fixType, fixTypeB;
				TRACE("Got a USBL fix: %s",tempBuf);
				sscanf(tempBuf,"%d,%d,",&fixType,&fixTypeB);
				m_usblFailCount = 0;

				if ((fixType == 6) && (fixTypeB == 1)) {
					if (sscanf(tempBuf, "%d,%d,%d,%f,%f,%f,%f,%f\n", &fixType, &fixTypeB, &m_fix1, &m_rxPitch, &m_rxRoll, &m_rxHeading, &m_dcl, &m_dcm) != 8) m_fix1= -1;
				} else if ((fixType == 6) && (fixTypeB == 2)) {
					if (sscanf(tempBuf,"%d,%d,%d,%f,%f\n", &fixType, &fixTypeB, &m_fix2, &m_eastings, &m_northings) != 5) m_fix2 = -2;
				} else {
					char buf[64];
					sscanf(tempBuf,"%s\n",buf);
				}

				if (m_fix1 == m_fix2) {
					m_recipient->sendUSBLFix(m_fix1, m_rxPitch, m_rxRoll, m_rxHeading, m_dcl, m_dcm, m_eastings, m_northings);
					m_fix1 = -1;
					m_fix2 = -2;
				}
			}
		}
		if (m_usblFailCount > 20) {
			if (m_serialConnection5 != false) {
					m_serialConnection5 = false; UpdateData(false);
				}
		}
	}

	

	COleVariant t = m_MessageGuageControl.GetValue();
	t.dblVal *= 0.95;
	m_MessageGuageControl.SetValue(t);
}


void CCommsDlg::initializeModemSystem()
{
	if (CONNECT_REMOTE) {
		try {

			// Initialize modem system
			Assert( m_pModemBroker == NULL);
			m_pModemBroker = new ModemBroker();

		} catch (Exception* e) {
			m_dialog->MessageBox(e->msg);
			if (m_pModemBroker) delete m_pModemBroker;

			m_pModemBroker = NULL;
			delete e;
		}
	}
}

void CCommsDlg::splitIPAddress(char *address,BYTE *b1,BYTE *b2,BYTE *b3,BYTE *b4)
{
	char *token;
	char addr[32];
	strcpy(addr,address);
	token = strtok(addr,".");
	*b1 = (BYTE) atoi(token);
	token = strtok(NULL,".");
	*b2 = (BYTE) atoi(token);
	token = strtok(NULL,".");
	*b3 = (BYTE) atoi(token);
	token = strtok(NULL,".");
	*b4 = (BYTE) atoi(token);
}

BEGIN_MESSAGE_MAP(CCommsDlg, CDialog)
	//{{AFX_MSG_MAP(CCommsDlg)
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_BN_CLICKED(IDC_NMEABUTTON, OnNmeabutton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCommsDlg message handlers

BEGIN_EVENTSINK_MAP(CCommsDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CCommsDlg)
	ON_EVENT(CCommsDlg, IDC_SERIAL_ON1, 1 /* ValueChanged */, OnValueChangedSerialOn1, VTS_BOOL)
	ON_EVENT(CCommsDlg, IDC_SERIAL_ON2, 1 /* ValueChanged */, OnValueChangedSerialOn2, VTS_BOOL)
	ON_EVENT(CCommsDlg, IDC_SERIAL_ON3, 1 /* ValueChanged */, OnValueChangedSerialOn3, VTS_BOOL)
	ON_EVENT(CCommsDlg, IDC_SOCKET_ON1, 1 /* ValueChanged */, OnValueChangedSocketOn1, VTS_BOOL)
	ON_EVENT(CCommsDlg, IDC_SOCKET_ON2, 1 /* ValueChanged */, OnValueChangedSocketOn2, VTS_BOOL)
	ON_EVENT(CCommsDlg, IDC_SERIAL_ON4, 1 /* ValueChanged */, OnValueChangedSerialOn4, VTS_BOOL)
	ON_EVENT(CCommsDlg, IDC_SERIAL_ON5, 1 /* ValueChanged */, OnValueChangedSerialOn5, VTS_BOOL)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CCommsDlg::OnOK() 
{
	// TODO: Add extra validation here
	//m_active = FALSE;
	UpdateData(TRUE);
	m_active = FALSE;
	stopRequests();
	SaveSettings();
	storeConfiguration();
	CDialog::OnOK();
}


void CCommsDlg::OnConnect() 
{
	// TODO: Add your control notification handler code here
	Assert(m_recipient);
	m_recipient->requestData(MMAgentRequest::Single,ModemMessage::tACK,-1);
}



// User Interface Methods

void CCommsDlg::OnValueChangedSocketOn1(BOOL Value) 
{
	if (Value) {
		if (m_active) {
			UpdateData(True);
		}
		BYTE b1, b2, b3, b4;
		m_socket1.GetAddress(b1,b2,b3,b4);
		if (b1 != 0) sprintf(m_socketAddress1,"%d.%d.%d.%d",b1,b2,b3,b4);
		addSocketModem1(m_socketAddress1);
		m_socket1.EnableWindow(FALSE);
	} else {
		disconnectSocket1();
		m_socket1.EnableWindow(TRUE);
		m_socketConnection1 = FALSE;
	}	
	if (m_active) UpdateData(FALSE);
}


void CCommsDlg::OnValueChangedSocketOn2(BOOL Value) 
{
	if (Value) {
		if (m_active) {
			UpdateData(True); 
		}
		BYTE b1, b2, b3, b4;
		m_socket2.GetAddress(b1,b2,b3,b4);
		if (b1 != 0) sprintf(m_socketAddress2,"%d.%d.%d.%d",b1,b2,b3,b4);
		addSocketModem2(m_socketAddress2);
		m_socket2.EnableWindow(FALSE);
	} else {
		disconnectSocket2();
		m_socket2.EnableWindow(TRUE);
		m_socketConnection2 = FALSE;
	}	
	if (m_active) UpdateData(FALSE);
}

void CCommsDlg::OnValueChangedSerialOn1(BOOL Value) 
{
	if (Value) {
		if (m_active) {
			UpdateData(True);
		}
		addSerialModem1(m_serialPort1,m_baudSelection1);
		m_serialCombo1.EnableWindow(FALSE);
		m_baudCombo1.EnableWindow(FALSE);
	} else {
		disconnectSerial1();
		m_serialCombo1.EnableWindow(TRUE);
		m_baudCombo1.EnableWindow(TRUE);
		m_serialConnection1 = FALSE;
	}
	if (m_active) UpdateData(FALSE);
}

void CCommsDlg::OnValueChangedSerialOn2(BOOL Value) 
{
	if (Value) {
		if (m_active) {
			UpdateData(True);
		}
		openSerialDriver(&m_devNmeaIn,m_serialPort2,m_baudSelection2);
		m_serialCombo2.EnableWindow(FALSE);
		m_baudCombo2.EnableWindow(FALSE);
	} else {
		disconnectSerialDriver(&m_devNmeaIn);
		m_serialCombo2.EnableWindow(TRUE);
		m_baudCombo2.EnableWindow(TRUE);
		m_serialConnection2 = FALSE;
	}
	if (m_active) UpdateData(FALSE);
}

void CCommsDlg::OnValueChangedSerialOn3(BOOL Value) 
{
	if (Value) {
		if (m_active) {
			UpdateData(True);
		}
		openSerialDriver(&m_devNmeaOut,m_serialPort3,m_baudSelection3);
		m_serialCombo3.EnableWindow(FALSE);
		m_baudCombo3.EnableWindow(FALSE);
	} else {
		disconnectSerialDriver(&m_devNmeaOut);
		m_serialCombo3.EnableWindow(TRUE);
		m_baudCombo3.EnableWindow(TRUE);
		m_serialConnection3 = FALSE;
	}
	if (m_active) UpdateData(FALSE);
}

void CCommsDlg::OnValueChangedSerialOn4(BOOL Value) 
{
	if (Value) {
		if (m_active) {
			UpdateData(True);	
		}
		openSerialDriver(&m_devRtcmIn,m_serialPort4,m_baudSelection4);
		m_serialCombo4.EnableWindow(FALSE);
		m_baudCombo4.EnableWindow(FALSE);
	} else {
		disconnectSerialDriver(&m_devRtcmIn);
		m_serialCombo4.EnableWindow(TRUE);
		m_baudCombo4.EnableWindow(TRUE);
		m_serialConnection4 = FALSE;
	}
	if (m_active) UpdateData(FALSE);
}

void CCommsDlg::OnNmeabutton() 
{
	// TODO: Add your control notification handler code here
	Assert(m_nmeaDlg != NULL);
	//m_nmeaDlg->SetParent(this);
	m_nmeaDlg->ShowWindow(SW_SHOWNORMAL);
}


void CCommsDlg::OnValueChangedSerialOn5(BOOL Value) 
{

	if (Value) {
		if (m_active) {
			UpdateData(True);	
		}
		openSerialDriver(&m_devUsbl,m_serialPort5,m_baudSelection5);
		
		
		// initialize surveyor
		char buf[64];
		sprintf(buf,"select,1\n"); // turn off transponder messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,2\n"); // turn off ship messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,3\n"); // turn off sensor messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,4\n"); // turn off riser angle monitoring messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,5\n"); // turn off analogue measurement messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,6.1,FixNum,RxPitch,RxRoll,RxHeading,l,m\n"); // set acoustic messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,6.2,FixNum,East,North\n"); // set dgps (position) messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,6.3\n"); // turn off depth messages
		m_devUsbl->write(buf,strlen(buf));
		sprintf(buf,"select,6.4n"); // turn off attitude messages
		m_devUsbl->write(buf,strlen(buf));

		m_serialCombo5.EnableWindow(FALSE);
		m_baudCombo5.EnableWindow(FALSE);
	} else {
		disconnectSerialDriver(&m_devUsbl);
		m_serialCombo5.EnableWindow(TRUE);
		m_baudCombo5.EnableWindow(TRUE);
		m_serialConnection4 = FALSE;
	}
	if (m_active) UpdateData(FALSE);
}


//  Topside Serial Commands

void CCommsDlg::openSerialDriver(SerialDevice** device, const char *port, int baudRate)
{
	try {
			if (*device != NULL) disconnectSerialDriver(device);
			// Initialize the device.
			*device= new SerialDevice(port);

			(*device)->setLineFormat(baudRate, 8, 1, "NONE" );
			(*device)->raw();
			int b = (*device)->blocking();
			(*device)->clearPort();
	} catch (Exception e) {
		MessageBox(e.msg);
	}
}

void CCommsDlg::disconnectSerialDriver(SerialDevice** device)
{
	try{
		if (*device != NULL) {
			delete *device;
			*device = NULL;
		}
	} catch (Exception e) {
		MessageBox(e.msg);
	}
}



// Vehicle Modem System Commands

////////////////////////////////////////////////////
void CCommsDlg::addSocketModem1(const char *address)
{
	try {
		m_socketAlive1 = false;
		strcpy(m_socketAddress1,address);
		disconnectSocket1();
		m_pModemSocket1 = new ModemSocket(m_socketAddress1,10000000); // approx b
		m_pModemBroker->addModem( m_pModemSocket1 );
		//m_recipient->requestData(MMAgentRequest::Single,ModemMessage::tACK,-1);
		m_socketAlive1 = true;
	} catch (Exception e) {
		m_dialog->MessageBox(e.msg);
	}
}

////////////////////////////////////////////////////
void CCommsDlg::disconnectSocket1()
{
	m_socketAlive1 = false;
	if (m_pModemSocket1) {
		m_pModemBroker->removeModem(m_pModemSocket1);
		while ( (m_pModemSocket1->getWriteStatus() == Modem::sPENDING) | m_cycle )
			Sleep(5);
		((ModemFork *) m_pModemSocket1)->stop();
		delete m_pModemSocket1;
		m_pModemSocket1 = NULL;
	}
}

////////////////////////////////////////////////////
void CCommsDlg::addSocketModem2(const char *address)
{
	try {
		m_socketAlive2 = false;
		strcpy(m_socketAddress2,address);
		disconnectSocket2();
		m_pModemSocket2 = new ModemSocket(m_socketAddress2,57600); // approx baud
		m_pModemBroker->addModem( m_pModemSocket2 );
		//m_recipient->requestData(MMAgentRequest::Single,ModemMessage::tACK,-1);
		m_socketAlive2 = true;
	} catch (Exception e) {
		m_dialog->MessageBox(e.msg);
	}
}

////////////////////////////////////////////////////
void CCommsDlg::disconnectSocket2()
{
	m_socketAlive2 = false;
	if (m_pModemSocket2) {
		m_pModemBroker->removeModem(m_pModemSocket2);
		while ( (m_pModemSocket2->getWriteStatus() == Modem::sPENDING) | m_cycle )
			Sleep(5);
		((ModemFork *) m_pModemSocket2)->stop();
		delete m_pModemSocket2;
		m_pModemSocket2 = NULL;
	}
}


////////////////////////////////////////////////////
void CCommsDlg::addSerialModem1(const char *port, int baud)
{
	try {
		m_serialAlive1 = false;
		disconnectSerial1();
		m_pModemSerial1 = new ModemSerial(port,baud);
		m_pModemBroker->addModem( m_pModemSerial1 );
		//m_recipient->requestData(MMAgentRequest::Single,ModemMessage::tACK,-1);
		m_serialAlive1 = true;
	} catch (Exception e) {
		m_dialog->MessageBox(e.msg);
	}
}

////////////////////////////////////////////////////
void CCommsDlg::disconnectSerial1()
{
	m_serialAlive1 = false;
	if (m_pModemSerial1) {
		m_pModemBroker->removeModem(m_pModemSerial1);
		while ( (m_pModemSerial1->getWriteStatus() == Modem::sPENDING) | m_cycle)
			Sleep(5);
		((ModemFork *) m_pModemSerial1)->stop();
		delete m_pModemSerial1;
		m_pModemSerial1 = NULL;
	}
}

void CCommsDlg::SendSerialString(char * str)
{
	if (m_devNmeaOut != NULL) {
		char temp[256];
		strcpy(temp,str);
		m_devNmeaOut->write(temp, strlen(temp));
	}
}


void CCommsDlg::gotMessage(const ModemMessage* mm)
{
	char str[128];
	sprintf(str,"RX: Message type %d\r\n",mm->getType());
//	m_MessageWatcher.SetRedraw(false);
	if (m_MessageWatcherString.GetLength() > 300) m_MessageWatcherString.Delete(0,50);
	m_MessageWatcherString+=str;
	if (m_active) { m_mw = true; UpdateData(FALSE); m_mw = false;}
	m_MessageWatcher.LineScroll(m_MessageWatcher.GetLineCount());
//	m_MessageWatcher.SetRedraw(true);

	COleVariant test = m_MessageGuageControl.GetValue();
	test.dblVal += mm->nActualBytes();

	m_MessageGuageControl.SetValue(test);
}	

void CCommsDlg::sentMessage(const ModemMessage* mm)
{
	char str[128];
	sprintf(str,"TX: Message type %d\r\n",mm->getType());
	//m_MessageWatcher.SetRedraw(false);
	if (m_MessageWatcherString.GetLength() > 100) m_MessageWatcherString.Delete(0,50);
	m_MessageWatcherString+=str;
	if (m_active) { m_mw = true; UpdateData(FALSE); m_mw = false;}
	m_MessageWatcher.LineScroll(m_MessageWatcher.GetLineCount());
	//m_MessageWatcher.SetRedraw(true);

	COleVariant test = m_MessageGuageControl.GetValue();
	test.dblVal += mm->nActualBytes();

	m_MessageGuageControl.SetValue(test);
}	

///////////////////////////// Utilities //////////////////////////////////

void CCommsDlg::EnumerateSerialPorts(CUIntArray& ports)
{
  //Make sure we clear out any elements which may already be in the array
  ports.RemoveAll();

  //Determine what OS we are running on
  OSVERSIONINFO osvi;
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  BOOL bGetVer = GetVersionEx(&osvi);

  //On NT use the QueryDosDevice API
  if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT))
  {
    //Use QueryDosDevice to look for all devices of the form COMx. This is a better
    //solution as it means that no ports have to be opened at all.
    TCHAR szDevices[65535];
    DWORD dwChars = QueryDosDevice(NULL, szDevices, 65535);
    if (dwChars)
    {
      int i=0;

      for (;;)
      {
        //Get the current device name
        TCHAR* pszCurrentDevice = &szDevices[i];

        //If it looks like "COMX" then
        //add it to the array which will be returned
        int nLen = _tcslen(pszCurrentDevice);
        if (nLen > 3 && _tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0)
        {
          //Work out the port number
          int nPort = _ttoi(&pszCurrentDevice[3]);
          ports.Add(nPort);
        }

        // Go to next NULL character
        while(szDevices[i] != _T('\0'))
          i++;

        // Bump pointer to the next string
        i++;

        // The list is double-NULL terminated, so if the character is
        // now NULL, we're at the end
        if (szDevices[i] == _T('\0'))
          break;
      }
    }
    else
      TRACE(_T("Failed in call to QueryDosDevice, GetLastError:%d\n"), GetLastError());
  }
  else
  {
    //On 95/98 open up each port to determine their existence

    //Up to 255 COM ports are supported so we iterate through all of them seeing
    //if we can open them or if we fail to open them, get an access denied or general error error.
    //Both of these cases indicate that there is a COM port at that number. 
    for (UINT i=1; i<256; i++)
    {
      //Form the Raw device name
      CString sPort;
      sPort.Format(_T("\\\\.\\COM%d"), i);

      //Try to open the port
      BOOL bSuccess = FALSE;
      HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
      if (hPort == INVALID_HANDLE_VALUE)
      {
        DWORD dwError = GetLastError();

        //Check to see if the error was because some other app had the port open or a general failure
        if (dwError == ERROR_ACCESS_DENIED || dwError == ERROR_GEN_FAILURE)
          bSuccess = TRUE;
      }
      else
      {
        //The port was opened successfully
        bSuccess = TRUE;

        //Don't forget to close the port, since we are going to do nothing with it anyway
        CloseHandle(hPort);
      }

      //Add the port number to the array which will be returned
      if (bSuccess)
        ports.Add(i);
    }
  }
}

