
// MRTU_MasterDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MRTU_Master.h"
#include "MRTU_MasterDlg.h"

char caParity[]={'N','O','E'};

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMRTU_MasterDlg dialog




CMRTU_MasterDlg::CMRTU_MasterDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMRTU_MasterDlg::IDD, pParent)
{
	m_ip = _T("");
	m_port = 0;
	m_rcoilfrom = 0;
	m_rcoilr = _T("");
	m_rcoilto = 0;
	m_rregsfrom = 0;
	m_rInputbitr = _T("");
	m_rInputbitfrom=0;
	m_rInpubitto=0;
	m_rInpregsr= _T("");
	m_rInputregfrom=0;
	m_rInpuregto=0;
	m_rregsr = _T("");
	m_rregsto = 0;
	m_wcoil = 0;
	m_wcoils = 0;
	m_wreg = 0;
	m_wregv = 0;
	m_com = 0;
	m_databit = 0;
	m_parity = 0;
	m_baud = 0;
	m_stopbit = 0;
	m_tcptime = 0;
	m_rtutime = 0;
	m_reConnectCount = _T("");
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMRTU_MasterDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_IP, m_ip);
	DDX_Text(pDX, IDC_PORT, m_port);
	DDX_Text(pDX, IDC_RCOILFROM, m_rcoilfrom);
	DDX_Text(pDX, IDC_RCOILR, m_rcoilr);
	DDX_Text(pDX, IDC_RCOILTO, m_rcoilto);
	DDX_Text(pDX, IDC_RINPBITFROM, m_rInputbitfrom);
	DDX_Text(pDX, IDC_RINPBITTO, m_rInpubitto);	
	DDX_Text(pDX, IDC_RINPBITR, m_rInputbitr);	
	DDX_Text(pDX, IDC_RREGSFROM, m_rregsfrom);
	DDX_Text(pDX, IDC_RREGSR, m_rregsr);
	DDX_Text(pDX, IDC_RREGSTO, m_rregsto);
	DDX_Text(pDX, IDC_RINPREGSR, m_rInpregsr);
	DDX_Text(pDX, IDC_RINPREGSFROM, m_rInputregfrom);
	DDX_Text(pDX, IDC_RINPREGSTO, m_rInpuregto);

	DDX_Text(pDX, IDC_WCOIL, m_wcoil);
	DDX_Text(pDX, IDC_WCOILS, m_wcoils);
	DDX_Text(pDX, IDC_WREG, m_wreg);
	DDX_Text(pDX, IDC_WREGV, m_wregv);
	DDX_Text(pDX, IDC_COM, m_com);
	DDX_Text(pDX, IDC_DataBit, m_databit);
	DDX_Text(pDX, IDC_Parity, m_parity);
	DDX_Text(pDX, IDC_Baud, m_baud);
	DDX_Text(pDX, IDC_StopBit, m_stopbit);
	DDX_Text(pDX, IDC_TCPTime, m_tcptime);
	DDX_Text(pDX, IDC_RTUTime, m_rtutime);
	DDX_Text(pDX, IDC_EDIT1, m_reConnectCount);
}

BEGIN_MESSAGE_MAP(CMRTU_MasterDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON1, &CMRTU_MasterDlg::OnBnClickedButton1)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_MBTCPRADIO, &CMRTU_MasterDlg::OnBnClickedMbtcpradio2)
	ON_BN_CLICKED(IDC_MBRTURADIO, &CMRTU_MasterDlg::OnBnClickedMbrturadio)
	ON_BN_CLICKED(IDC_BUTTON2, &CMRTU_MasterDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON4, &CMRTU_MasterDlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &CMRTU_MasterDlg::OnBnClickedButton5)
//	ON_BN_CLICKED(IDC_RREGSB, &CMRTU_MasterDlg::OnBnClickedRregsb)
	ON_BN_CLICKED(IDC_WCOILB, &CMRTU_MasterDlg::OnBnClickedWcoilb)
	ON_BN_CLICKED(IDC_WREGB, &CMRTU_MasterDlg::OnBnClickedWregb)
	ON_BN_CLICKED(IDC_RREGSB, &CMRTU_MasterDlg::OnBnClickedRregsb)
	ON_BN_CLICKED(IDC_RREGSB2, &CMRTU_MasterDlg::OnBnClickedRregsb2)
	ON_BN_CLICKED(IDC_BUTTON3, &CMRTU_MasterDlg::OnBnClickedButton3)
END_MESSAGE_MAP()


// CMRTU_MasterDlg message handlers

BOOL CMRTU_MasterDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	CenterWindow(GetDesktopWindow());	// center to the screen
	// TODO: Add extra initialization here
	m_check = FALSE;	//For Modbus TCP
	m_check2 = FALSE;	//For Modbus RTU
	m_which = TRUE;	//Modbus RTU

	m_port =502;
	m_ip.Format(_T("%S"),"10.1.0.42");
	m_rcoilfrom = 0;
	m_rcoilto = 5;

	m_rInputbitfrom=0;
	m_rInpubitto=1;

	m_rregsfrom = 0;
	m_rregsto = 4;

	m_rInputregfrom=0;
	m_rInpuregto=4;

	m_wcoil = 6;
	m_wcoils = 1;
	m_wreg = 5;
    m_wregv = 12345;
	
	m_com = 3;
	m_baud = 19200;
	m_parity = 0;
	m_databit = 8;
	m_stopbit = 1;

	m_tcptime = 500;
	m_rtutime = 200;

	SetTimer(1,1000,NULL);

	((CButton*)GetDlgItem(IDC_MBRTURADIO))->SetCheck(1);
	((CEdit*)GetDlgItem(IDC_IP))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_PORT))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_TCPTime))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_COM))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_Baud))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_Parity))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_DataBit))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_StopBit))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_RTUTime))->EnableWindow(1);
	
	UpdateData(FALSE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMRTU_MasterDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMRTU_MasterDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CMRTU_MasterDlg::OnBnClickedButton1()
{
	// TODO: Add your control notification handler code here
	unsigned long ultimeout=0;
	UpdateData();


	if(m_which){ //rtu
		char tmp[64];

		sprintf(tmp,"COM%d",m_com);
		ctx = modbus_new_rtu(tmp, m_baud, caParity[m_parity], m_databit, m_stopbit); //Create a Modbus RTU context
        modbus_set_slave(ctx, 1); //Set slave ID
		ultimeout=m_rtutime*1000; //ms --> us
	}
	else{ //tcp
		int length=m_ip.GetLength();
		char str[128];
		memset(str, 0, 128);
		WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK|WC_DEFAULTCHAR,m_ip.GetBuffer(length),length+1, str,128,0,0);

		ctx = modbus_new_tcp(str, m_port); //Create a Modbus TCP context
		modbus_set_slave(ctx, 1); //Set slave ID
		ultimeout=m_tcptime*1000; //ms --> us

	}

	if(ctx!=NULL){
		if (modbus_connect(ctx) == -1) { //Establish a connection

			fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
			printf("Connection failed:%d %s\n", errno, modbus_strerror(errno));
			modbus_free(ctx); //Free libmodbus context
			if(m_which) //rtu
				m_check2 = FALSE;
			else
				m_check=FALSE;
			//return -1;
		}
		else
		{
			//modbus_set_response_timeout(ctx,0,ultimeout); // set timeout for response			
			if(m_which) //rtu
			{
				m_check2 = TRUE;
				AfxMessageBox(_T("RTU Create Success!"));
			}
			else
			{
				m_check=TRUE;
				AfxMessageBox(_T("TCP Create Success!"));
			}
		}
	}
	else{
		AfxMessageBox(_T("Create Failure!"));
		m_check = FALSE;
	}

	UpdateData(FALSE);
}

void CMRTU_MasterDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Add your message handler code here and/or call default
	int rr;
	if(m_check2 == TRUE || m_check == TRUE)
	{
		UpdateData();
		unsigned char *tab_bit;
		int nbpoints=(m_rcoilto-m_rcoilfrom+1);

		tab_bit = (unsigned char *) malloc(nbpoints * sizeof(unsigned char));
		memset(tab_bit, 0, nbpoints * sizeof(unsigned char));
	
		//printf("m_rcoilfrom=%d, nbpoints=%d\r\n",m_rcoilfrom,nbpoints);
		rr = modbus_read_bits(ctx, m_rcoilfrom, nbpoints, tab_bit); //The function uses the Modbus function code 0x01 (read coil status).
		if(rr>0)
		{
			printf(".");		
		}
		else
		{			
			
		}
		UpdateData(FALSE);
	}
	CDialog::OnTimer(nIDEvent);
}

void CMRTU_MasterDlg::OnBnClickedMbtcpradio2()
{
	// TODO: Add your control notification handler code here
	((CButton*)GetDlgItem(IDC_MBTCPRADIO))->SetCheck(1);
	((CButton*)GetDlgItem(IDC_MBRTURADIO))->SetCheck(0);
	((CEdit*)GetDlgItem(IDC_IP))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_PORT))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_TCPTime))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_COM))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_Baud))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_Parity))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_DataBit))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_StopBit))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_RTUTime))->EnableWindow(0);
	m_which =FALSE;
}

void CMRTU_MasterDlg::OnBnClickedMbrturadio()
{
	// TODO: Add your control notification handler code here
	((CButton*)GetDlgItem(IDC_MBRTURADIO))->SetCheck(1);
	((CButton*)GetDlgItem(IDC_MBTCPRADIO))->SetCheck(0);
	((CEdit*)GetDlgItem(IDC_IP))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_PORT))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_TCPTime))->EnableWindow(0);
	((CEdit*)GetDlgItem(IDC_COM))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_Baud))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_Parity))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_DataBit))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_StopBit))->EnableWindow(1);
	((CEdit*)GetDlgItem(IDC_RTUTime))->EnableWindow(1);
	m_which = TRUE;
}

void CMRTU_MasterDlg::OnBnClickedButton2()
{
	// TODO: Add your control notification handler code here
	UpdateData();
	if(m_which){ //rtu
		if(m_check2 == FALSE){
			AfxMessageBox(_T("The COM port has been closed!"));
		}
		else{
			modbus_close(ctx);  //Close a connection
			modbus_free(ctx);  //Free libmodbus context
			m_check2 = FALSE;
			AfxMessageBox(_T("The COM port closed!"));
		}
	}
	else{ //tcp
		if(m_check == FALSE){
				AfxMessageBox(_T("The TCP socket has been closed!"));
		}
		else{
			modbus_close(ctx);  //Close a connection
			modbus_free(ctx);  //Free libmodbus context
			m_check = FALSE;
			AfxMessageBox(_T("The TCP socket closed!"));
		}
	}

	UpdateData(FALSE);
}

void CMRTU_MasterDlg::OnBnClickedButton4()
{
	// TODO: Add your control notification handler code here
	int rr;
	if(m_check2 == TRUE || m_check == TRUE)
	{
		UpdateData();
		unsigned char *tab_bit;
		int nbpoints=(m_rcoilto-m_rcoilfrom+1);

		tab_bit = (unsigned char *) malloc(nbpoints * sizeof(unsigned char));
		memset(tab_bit, 0, nbpoints * sizeof(unsigned char));
	
		printf("m_rcoilfrom=%d, nbpoints=%d\r\n",m_rcoilfrom,nbpoints);
		rr = modbus_read_bits(ctx, m_rcoilfrom, nbpoints, tab_bit); //The function uses the Modbus function code 0x01 (read coil status).
		if(rr>0)
		{
			CString str;
			m_rcoilr = _T("");
			for(int i=0;i<nbpoints;i++)
			{					
				str.Format(_T("0x%x "),tab_bit[i]);
				m_rcoilr.Append(str);
			}
				//printf("rr=%d ,failed: %s\n", rr,modbus_strerror(errno));			
		}
		else
		{			
			CString aa;
			aa.Format(_T("modbus_read_bits failed: %S"), modbus_strerror(errno));
			AfxMessageBox(aa);			
		}
		UpdateData(FALSE);
	}
	else{
		AfxMessageBox(_T("Please create a connection first!!"));
	}
}


void CMRTU_MasterDlg::OnBnClickedButton5()
{
	// TODO: Add your control notification handler code here
	int rr;

	if(m_check2 == TRUE || m_check == TRUE)
	{
		UpdateData();
		unsigned char *tab_bit;
		int nbpoints=(m_rInpubitto-m_rInputbitfrom+1); 

		tab_bit = (unsigned char *) malloc(nbpoints * sizeof(unsigned char));
		memset(tab_bit, 0, nbpoints * sizeof(unsigned char));

		rr = modbus_read_input_bits(ctx, m_rcoilfrom, nbpoints, tab_bit); //The function uses the Modbus function code 0x02 (read input status).
		if(rr>0)
		{
			CString str;
			m_rInputbitr = _T("");
			for(int i=0;i<nbpoints;i++)
			{					
				str.Format(_T("0x%x "),tab_bit[i]);
				m_rInputbitr.Append(str);
			}			
		}
		else
		{
	
			CString aa;
			aa.Format(_T("modbus_read_input_bits failed: %S"), modbus_strerror(errno));
			AfxMessageBox(aa);	
		}
		UpdateData(FALSE);
	}
	else
		AfxMessageBox(_T("Please create a connection first!!"));
}

void CMRTU_MasterDlg::OnBnClickedRregsb()
{
	// TODO: Add your control notification handler code here
	int rr;

	if(m_check2 == TRUE || m_check == TRUE)
	{
		UpdateData();
		unsigned short *tab_bit;
		int nbpoints=(m_rregsto-m_rregsfrom+1);

		tab_bit = (unsigned short *) malloc(nbpoints * sizeof(unsigned short));
		memset(tab_bit, 0, nbpoints * sizeof(unsigned short));

		rr = modbus_read_registers(ctx, m_rcoilfrom, nbpoints, tab_bit); //The function uses the Modbus function code 0x02 (read input status).
		if(rr>0)
		{
			CString str;
			m_rregsr = _T("");
			for(int i=0;i<nbpoints;i++)
			{					
				str.Format(_T("%d "),tab_bit[i]);
				m_rregsr.Append(str);
			}
		}
		else
		{
	
			CString aa;
			aa.Format(_T("modbus_read_registers failed: %S"), modbus_strerror(errno));
			AfxMessageBox(aa);	
		}
		UpdateData(FALSE);
	}
	else
		AfxMessageBox(_T("Please create a connection first!!"));
}

void CMRTU_MasterDlg::OnBnClickedWcoilb()
{
	// TODO: Add your control notification handler code here
	int rr;
	if(m_check2 == TRUE || m_check == TRUE)
	{	
		UpdateData();
		rr=modbus_write_bit(ctx,m_wcoil,m_wcoils); //The function uses the Modbus function code 0x05 (force single coil).
		if(rr>0)
		{
			//m_rcoilr = _T("");
			//for(int i=0;i<nbpoints;i++)
			//	m_rInpregsr.Append(_T("0x%x "),tab_bit[i]);
			;
		}
		else
		{
	
			CString aa;
			aa.Format(_T("modbus_write_bit failed: %S"), modbus_strerror(errno));
			AfxMessageBox(aa);	
		}
		UpdateData(FALSE);
		
	}
	else
		AfxMessageBox(_T("Please create a connection first!!"));
}

void CMRTU_MasterDlg::OnBnClickedWregb()
{
	// TODO: Add your control notification handler code here	
	int rr;
	if(m_check2 == TRUE || m_check == TRUE)
	{	
		UpdateData();
		rr=modbus_write_register(ctx,m_wreg,m_wregv); //The function uses the Modbus function code 0x06 (preset single register).
		if(rr>0)
		{
			//m_rcoilr = _T("");
			//for(int i=0;i<nbpoints;i++)
			//	m_rInpregsr.Append(_T("0x%x "),tab_bit[i]);
			;
		}
		else
		{

			CString aa;
			aa.Format(_T("modbus_write_register failed: %S"), modbus_strerror(errno));
			AfxMessageBox(aa);	
		}
		UpdateData(FALSE);
		
	}
	else
		AfxMessageBox(_T("Please create a connection first!!"));
}


void CMRTU_MasterDlg::OnBnClickedRregsb2()
{
	// TODO: Add your control notification handler code here
	int rr;

	if(m_check2 == TRUE || m_check == TRUE)
	{
		UpdateData();
		unsigned short *tab_bit;
		int nbpoints=(m_rInpuregto-m_rInputregfrom+1);

		tab_bit = (unsigned short *) malloc(nbpoints * sizeof(unsigned short));
		memset(tab_bit, 0, nbpoints * sizeof(unsigned short));

		rr = modbus_read_input_registers(ctx, m_rcoilfrom, nbpoints, tab_bit); //The function uses the Modbus function code 0x04 (read input registers).
		if(rr>0)
		{
			CString str;
			m_rInpregsr = _T("");
			for(int i=0;i<nbpoints;i++)
			{					
				str.Format(_T("%d "),tab_bit[i]);
				m_rInpregsr.Append(str);
			}
		}
		else
		{
			CString aa;
			aa.Format(_T("modbus_read_input_registers failed: %S"), modbus_strerror(errno));
			AfxMessageBox(aa);
		}
		UpdateData(FALSE);
	}
	else
		AfxMessageBox(_T("Please create a connection first!!"));
	
}

void CMRTU_MasterDlg::OnBnClickedButton3()
{
	// TODO: Add your control notification handler code here
}
