// mfcAppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "mfcApp.h"
#include "mfcAppDlg.h"
#include "LocalModbus.h"

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


CLocalModbus cMod;

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

public:
        /// <summary>
        /// "ExampleSetting" Structure contains connection parameters of power meter.The parameters are set by user interface or console inpute.
        /// In this programm, ExampleSetting member's values are either index or amount of units to set power meter parameters. 
        /// They are not actually the real values of Modbus Holding Registers which specified in hardware manual.
        /// </summary>
        struct ExampleSetting 
        {
            byte PortName;
            int BaudRate;
            byte Modbus_slave_ID; 
            int StopBit;
            int PT;
            int CT;
            int Meter_Ratio; // const value: 500
        };


};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMfcAppDlg dialog

CMfcAppDlg::CMfcAppDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMfcAppDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMfcAppDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMfcAppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMfcAppDlg)
	DDX_Control(pDX, IDC_EDIT44, m_kVah4);
	DDX_Control(pDX, IDC_EDIT43, m_kVah3);
	DDX_Control(pDX, IDC_EDIT42, m_kVah2);
	DDX_Control(pDX, IDC_EDIT41, m_kVah1);
	DDX_Control(pDX, IDC_EDIT40, m_kvarh4);
	DDX_Control(pDX, IDC_EDIT39, m_kvarh3);
	DDX_Control(pDX, IDC_EDIT38, m_kvarh2);
	DDX_Control(pDX, IDC_EDIT37, m_kvarh1);
	DDX_Control(pDX, IDC_EDIT36, m_kWh4);
	DDX_Control(pDX, IDC_EDIT35, m_kWh3);
	DDX_Control(pDX, IDC_EDIT34, m_kWh2);
	DDX_Control(pDX, IDC_EDIT33, m_kWh1);
	DDX_Control(pDX, IDC_EDIT32, m_PF4);
	DDX_Control(pDX, IDC_EDIT31, m_PF3);
	DDX_Control(pDX, IDC_EDIT30, m_PF2);
	DDX_Control(pDX, IDC_EDIT29, m_PF1);
	DDX_Control(pDX, IDC_EDIT28, m_kVA4);
	DDX_Control(pDX, IDC_EDIT27, m_kVA3);
	DDX_Control(pDX, IDC_EDIT26, m_kVA2);
	DDX_Control(pDX, IDC_EDIT25, m_kVA1);
	DDX_Control(pDX, IDC_EDIT24, m_kVar4);
	DDX_Control(pDX, IDC_EDIT23, m_kVar3);
	DDX_Control(pDX, IDC_EDIT22, m_kVar2);
	DDX_Control(pDX, IDC_EDIT21, m_kVar1);
	DDX_Control(pDX, IDC_EDIT20, m_kW4);
	DDX_Control(pDX, IDC_EDIT19, m_kW3);
	DDX_Control(pDX, IDC_EDIT18, m_kW2);
	DDX_Control(pDX, IDC_EDIT17, m_kW1);
	DDX_Control(pDX, IDC_EDIT16, m_Current4);
	DDX_Control(pDX, IDC_EDIT15, m_Current3);
	DDX_Control(pDX, IDC_EDIT14, m_Current2);
	DDX_Control(pDX, IDC_EDIT13, m_Current1);
	DDX_Control(pDX, IDC_EDIT12, m_Voltage4);
	DDX_Control(pDX, IDC_EDIT11, m_Voltage3);
	DDX_Control(pDX, IDC_EDIT10, m_Voltage2);
	DDX_Control(pDX, IDC_EDIT9, m_Voltage1);
	DDX_Control(pDX, IDC_EDIT8, m_slave);
	DDX_Control(pDX, IDC_EDIT7, m_regCt);
	DDX_Control(pDX, IDC_EDIT6, m_regPt);
	DDX_Control(pDX, IDC_EDIT1, m_port);
	DDX_Control(pDX, IDC_COMBO2, m_baudrate);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMfcAppDlg, CDialog)
	//{{AFX_MSG_MAP(CMfcAppDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, OpenCOM)
	ON_BN_CLICKED(IDC_BUTTON1, CloseCom)
	ON_BN_CLICKED(IDC_BUTTON2, ReadHolding)
	ON_BN_CLICKED(IDC_BUTTON4, ReadMeasurements)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMfcAppDlg message handlers

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

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 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
	
	// TODO: Add extra initialization here
	int nIndex=-1;
    CString str;

    // port
	m_port.SetWindowText("1");

	// slave
	m_slave.SetWindowText("1");

	// baudrate
    nIndex=m_baudrate.AddString("9600");
    m_baudrate.SetItemData( nIndex,CBR_9600);

    nIndex=m_baudrate.AddString("19200");
    m_baudrate.SetItemData( nIndex,CBR_19200);

    nIndex=m_baudrate.AddString("38400");
    m_baudrate.SetItemData( nIndex,CBR_38400);

    nIndex=m_baudrate.AddString("115200");
    m_baudrate.SetItemData( nIndex,CBR_115200);

	m_baudrate.SetCurSel(1);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMfcAppDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 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 CMfcAppDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (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 to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMfcAppDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMfcAppDlg::OpenCOM() 
{
     int sBit=0,nIndex=0,comPort=0;
	 int funcReturnValue=0;
	 DWORD dwBaudRate;
	 DWORD dwStopBit;
	 DWORD dwTimeout;
	 CString str;

     //com port 
	 m_port.GetWindowText(str);
	 comPort = atoi(str);
	 if (comPort<1) {
	    AfxMessageBox("Invalid com port");
        return;
	 }

	 //Specifies the baud rate 
	 nIndex=m_baudrate.GetCurSel();
	 dwBaudRate=m_baudrate.GetItemData(nIndex);

	 //number of stop bits. 
	 cMod.StopBits((BYTE)ONESTOPBIT);

	 //Specifies the number of bits in the bytes transmitted and received 
	 cMod.ByteSize(8);

	 //message timeout in ms.
	 cMod.Timeout(1000);

	 cMod.TransmissionMode(CLocalModbus::MODE_RTU);

	 //Opens a com port or or updates port parameters.
	 //TRUE if function succeeds and FALSE if fails.
     funcReturnValue =(int) cMod.UpdateSerialConfig(comPort,dwBaudRate,NOPARITY);

     if(!funcReturnValue)
       AfxMessageBox(cMod.ErrorMessage(funcReturnValue));//("Com port open fail!");
}

void CMfcAppDlg::CloseCom() 
{
	 int funcReturnValue=1;

	 //Closes a serial port
	 //TRUE if function succeeds and FALSE if fails.
	 if(cMod.IsActive())
     funcReturnValue = cMod.CloseCommPort(); 

     if(!funcReturnValue)
       AfxMessageBox("Com port close fail!");
}

void CMfcAppDlg::ReadHolding() 
{
	 int mbID=0,funcReturnValue=0;
	 CString str;
	 char cha[256];
	 
	 CWordArray wArray;
     wArray.SetSize(2);

	 m_slave.GetWindowText(str);
     mbID = atoi(str);
	 funcReturnValue = cMod.ReadOutputRegisters((BYTE)mbID,0x1003,2,wArray);			

	 itoa(wArray.ElementAt(0)/100,cha,10);
     m_regPt.SetWindowText(cha);

	 itoa(wArray.ElementAt(1),cha,10);
	 m_regCt.SetWindowText(cha);

     if(funcReturnValue)
       AfxMessageBox(cMod.ErrorMessage(funcReturnValue));//("Read Holding Registers fail!");

}
/*
void CMfcAppDlg::WriteHolding() 
{
	 int mbID=0,funcReturnValue=0;
	 CString str;
	 
	 CWordArray wArray;
     wArray.SetSize(2);	

     m_regPt.GetWindowText(str);
     wArray.SetAt(0, atoi(str));

     m_regCt.GetWindowText(str);
     wArray.SetAt(1, atoi(str));

	 //If change Baudrate or Stopbit, 
     //function PresetMultipleRegisters always return fail !
	 //Because orignal baudrate or stopbitthe of the port changed. 
	 m_slave.GetWindowText(str);
     mbID = atoi(str);
	 funcReturnValue = cMod.PresetMultipleRegisters(mbID, 0x1003, 2 , wArray);
  
     //if(funcReturnValue)
       //AfxMessageBox("Write Holding Registers fail!");

	 if(cMod.IsActive())
     funcReturnValue = cMod.CloseCommPort(); 
}*/

void CMfcAppDlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	CMfcAppDlg::CloseCom();
	CDialog::OnCancel();
}

void CMfcAppDlg::ReadMeasurements() 
{
   int comPort=0,mbID=0,funcReturnValue=0;
   CString str;
   char cha[256];
   float buffer[36];
   CWordArray wArray,bArray;
   wArray.SetSize(72);
   bArray.SetSize(72);

   m_slave.GetWindowText(str);
   mbID = atoi(str);

   if(cMod.IsActive())
   funcReturnValue = cMod.ReadInputRegisters(mbID, 0x1100, 72, wArray);

   if(funcReturnValue)
     AfxMessageBox(cMod.ErrorMessage(funcReturnValue));//("Read Measurement Registers fail!");
   
   /*unsigned short *w,*b;
   int last = 72 -1;
   w = wArray.GetData();
   b = bArray.GetData();
   b = b+ last;
   // Converts two WORD-type values into a IEEE 32 floating point format 
	    for(int i=0; i< 72 ; i++,w++,b--)
		{
	        memcpy( (unsigned short *)b,(unsigned short *)w,2 );
		}	
        float *f = (float*)b;
	    for(i=0; i< 36 ; i++)
		{
	        buffer[36-1-i] = *(f++);
		}	*/

    unsigned short *w;
    w = wArray.GetData();
   
    // Converts two WORD-type values into a IEEE 32 floating point format 
	for(int i=0; i< 36 ; i++)
	{
		memcpy( &buffer[i], &w[i*2], 4);
	}	


   // output Voltage   
   sprintf(cha,"%.3f",buffer[0]);
   m_Voltage1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[9]);
   m_Voltage2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[18]);
   m_Voltage3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[27]);
   m_Voltage4.SetWindowText(cha);

   // output Current
   sprintf(cha,"%.3f",buffer[1]);
   m_Current1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[10]);
   m_Current2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[19]);
   m_Current3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[28]);
   m_Current4.SetWindowText(cha);

   // output kWt
   sprintf(cha,"%.3f",buffer[2]);
   m_kW1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[11]);
   m_kW2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[20]);
   m_kW3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[29]);
   m_kW4.SetWindowText(cha);

   // output kVar
   sprintf(cha,"%.3f",buffer[3]);
   m_kVar1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[12]);
   m_kVar2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[21]);
   m_kVar3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[30]);
   m_kVar4.SetWindowText(cha);

   // output kVA
   sprintf(cha,"%.3f",buffer[4]);
   m_kVA1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[13]);
   m_kVA2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[22]);
   m_kVA3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[31]);
   m_kVA4.SetWindowText(cha);

   // output PF
   sprintf(cha,"%.3f",buffer[5]);
   m_PF1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[14]);
   m_PF2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[23]);
   m_PF3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[32]);
   m_PF4.SetWindowText(cha);

   // output kWh
   sprintf(cha,"%.3f",buffer[6]);
   m_kWh1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[15]);
   m_kWh2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[24]);
   m_kWh3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[33]);
   m_kWh4.SetWindowText(cha);

   // output kvarh
   sprintf(cha,"%.3f",buffer[7]);
   m_kvarh1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[16]);
   m_kvarh2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[25]);
   m_kvarh3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[34]);
   m_kvarh4.SetWindowText(cha);

   // output kVah
   sprintf(cha,"%.3f",buffer[8]);
   m_kVah1.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[17]);
   m_kVah2.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[26]);
   m_kVah3.SetWindowText(cha);
   sprintf(cha,"%.3f",buffer[35]);
   m_kVah4.SetWindowText(cha);
}

