// ModbucfgView.cpp : implementation of the CModbucfgView class
//

#include "stdafx.h"
#include "Modbucfg.h"

#include "ModbucfgDoc.h"
#include "ModbucfgView.h"
#include ".\modbucfgview.h"


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

/////////////////////////////////////////////////////////////////////////////
// CModbucfgView

IMPLEMENT_DYNCREATE(CModbucfgView, CFormView)

BEGIN_MESSAGE_MAP(CModbucfgView, CFormView)
	//{{AFX_MSG_MAP(CModbucfgView)
	ON_BN_CLICKED(IDC_CHK_Enable_Poll, OnchkEnablePoll)
	ON_EN_CHANGE(IDC_EDIT_INTERVAL, OnChangeEditInterval)
	ON_BN_CLICKED(IDC_CMD_WRITE, OnCmdWrite)
	//}}AFX_MSG_MAP
	ON_CBN_SELCHANGE(IDC_CBO_READ_FUNCTION, OnCbnSelchangeCboReadFunction)
	ON_CBN_SELCHANGE(IDC_CBO_WRITE_FUNCTION, OnCbnSelchangeCboWriteFunction)
	ON_COMMAND(ID_APP_MEM_MAP, OnAppMemMap)
	ON_EN_CHANGE(IDC_EDIT_QUANT, OnEnChangeEditQuant)
	ON_EN_CHANGE(IDC_EDIT_ADDR, OnEnChangeEditAddr)
	ON_EN_CHANGE(IDC_EDIT_QUANT_2, OnEnChangeEditQuant2)
	ON_LBN_SELCHANGE(IDC_LIST5, OnLbnSelchangeList5)
	ON_LBN_SELCHANGE(IDC_LST_VALUES, OnLbnSelchangeLstValues)
	ON_EN_CHANGE(IDC_EDIT_ADDR_WRI, OnEnChangeEditAddrWri)
	ON_EN_CHANGE(IDC_EDIT_VALUE, OnEnChangeEditValue)
	ON_WM_VSCROLL()
	ON_BN_CLICKED(IDC_CMD_READ, OnCmdRead)
//	ON_EN_CHANGE(IDC_EDIT16, OnEnChangeEdit16)
	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
	ON_BN_CLICKED(IDC_CMD_WRITE2, OnCmdStart)
	ON_BN_CLICKED(IDC_CMD_WRITE3, OnCmdStop)
	ON_BN_CLICKED(IDC_CMD_WRITE4, OnCmdPause)
	ON_BN_CLICKED(IDC_CMD_WRITE5, OnButtonReprise)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CModbucfgView construction/destruction

CModbucfgView::CModbucfgView()
	: CFormView(CModbucfgView::IDD)
/*	, m_edtQuant2(false)
	, m_edtQuant2(_T(""))*/
	, m_spinIndex(0)
{
	//{{AFX_DATA_INIT(CModbucfgView)
	//}}AFX_DATA_INIT
	// TODO: add construction code here

}

CModbucfgView::~CModbucfgView()
{
}

void CModbucfgView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CModbucfgView)
	DDX_Control(pDX, IDC_CBO_DATA_TYPE, m_cboDataType);
	DDX_Control(pDX, IDC_EDIT_INTERVAL, m_edtInterval);
	DDX_Control(pDX, IDC_CHK_Enable_Poll, m_butPollEnable);
	DDX_Control(pDX, IDC_STAT_STATUS, m_statStatus);
	DDX_Control(pDX, IDC_STAT_ERROR, m_staError);
	DDX_Control(pDX, IDC_LST_VALUES, m_lstValues);
	DDX_Control(pDX, IDC_CBO_WRITE_FUNCTION, m_cboWriteFunctions);
	DDX_Control(pDX, IDC_CBO_READ_FUNCTION, m_cboReadFunctions);
	DDX_Control(pDX, IDC_CBO_CONNECTION, m_cboConnections);
	DDX_Control(pDX, IDC_EDIT_VALUE, m_edtValue);
	DDX_Control(pDX, IDC_EDIT_QUANT, m_edtQuant);
	DDX_Control(pDX, IDC_EDIT_DEVICE, m_edtDevice);
	DDX_Control(pDX, IDC_EDIT_ADDR_WRI, m_edtWriteAddr);
	DDX_Control(pDX, IDC_EDIT_ADDR, m_edtReadAddr);
	DDX_Control(pDX, IDC_CMD_WRITE, m_cmdWrite);
	//}}AFX_DATA_MAP
	DDX_Control(pDX, IDC_EDIT_QUANT_2, m_edtQuant2);
	//	DDX_Control(pDX, IDC_LIST5, m_list5Values);
	DDX_Control(pDX, IDC_EDIT6, m_edtIndex);
	DDX_Text(pDX, IDC_EDIT6, m_spinIndex);
	DDX_Control(pDX, IDC_EDIT3, m_readEil);
	DDX_Control(pDX, IDC_EDIT5, m_readSVd);
	DDX_Control(pDX, IDC_EDIT7, m_readSVfin);
	DDX_Control(pDX, IDC_EDIT8, m_readSV1);
	DDX_Control(pDX, IDC_EDIT9, m_readSV2);
	DDX_Control(pDX, IDC_EDIT10, m_readdtp);
	DDX_Control(pDX, IDC_EDIT11, m_readdt);
	DDX_Control(pDX, IDC_EDIT12, m_readdP);
	DDX_Control(pDX, IDC_EDIT13, m_readdPsecu);
	DDX_Control(pDX, IDC_EDIT14, m_readSVil);
	DDX_Control(pDX, IDC_EDIT15, m_readSleil);
	DDX_Control(pDX, IDC_EDIT16, m_readSTc);
	DDX_Control(pDX, IDC_EDIT17, m_readNbal_max);
	DDX_Control(pDX, IDC_EDIT18, m_readFr);
	DDX_Control(pDX, IDC_EDIT19, m_readN_cur);
	DDX_Control(pDX, IDC_CMD_READ, m_cmdRead);
	DDX_Control(pDX, IDC_EDIT4, m_readNil);
	DDX_Control(pDX, IDC_EDIT20, m_readNil_stat);
	DDX_Control(pDX, IDC_EDIT21, m_readP_last);
	DDX_Control(pDX, IDC_EDIT22, m_readN_last);
	DDX_Control(pDX, IDC_EDIT23, m_readdPil);
	DDX_Control(pDX, IDC_EDIT24, m_readV_cur);
	DDX_Control(pDX, IDC_EDIT25, m_readPic);
	DDX_Control(pDX, IDC_EDIT26, m_readTimer);
	DDX_Control(pDX, IDC_EDIT27, m_readNbal);
	DDX_Control(pDX, IDC_EDIT28, m_readP_cde);
	DDX_Control(pDX, IDC_EDIT29, m_readPp);
	DDX_Control(pDX, IDC_EDIT30, m_readStat_C_1);
	DDX_Control(pDX, IDC_EDIT31, m_readStat_C_2);
	DDX_Control(pDX, IDC_EDIT32, m_readStat_C_3);
	DDX_Control(pDX, IDC_EDIT33, m_readStat_C_4);
	DDX_Control(pDX, IDC_EDIT34, m_readStat_C_5);
	DDX_Control(pDX, IDC_EDIT35, m_readStat_C_6);
	DDX_Control(pDX, IDC_EDIT36, m_readStat_C_7);
	DDX_Control(pDX, IDC_EDIT37, m_readStat_C_8);
	DDX_Control(pDX, IDC_EDIT38, m_readNum_C1a);
	DDX_Control(pDX, IDC_EDIT39, m_readNum_C1b);
	DDX_Control(pDX, IDC_EDIT40, m_readNum_C2a);
	DDX_Control(pDX, IDC_EDIT41, m_readNum_C2b);
	DDX_Control(pDX, IDC_EDIT42, m_readNum_C3a);
	DDX_Control(pDX, IDC_EDIT43, m_readNum_C3b);
	DDX_Control(pDX, IDC_EDIT44, m_readNum_C4a);
	DDX_Control(pDX, IDC_EDIT45, m_readNum_C4b);
	DDX_Control(pDX, IDC_EDIT54, m_readN_Seqcond);
	DDX_Control(pDX, IDC_EDIT57, m_readMAP);
	DDX_Control(pDX, IDC_EDIT46, m_readTemp_cond_1);
	DDX_Control(pDX, IDC_EDIT47, m_readTemp_cond_2);
	DDX_Control(pDX, IDC_EDIT48, m_readTemp_cond_3);
	DDX_Control(pDX, IDC_EDIT49, m_readTemp_cond_4);
	DDX_Control(pDX, IDC_EDIT50, m_readTemp_cond_5);
	DDX_Control(pDX, IDC_EDIT51, m_readTemp_cond_6);
	DDX_Control(pDX, IDC_EDIT52, m_readTemp_cond_7);
	DDX_Control(pDX, IDC_EDIT53, m_readTemp_cond_8);
	DDX_Control(pDX, IDC_EDIT58, m_readStat_C_9);
	DDX_Control(pDX, IDC_EDIT59, m_readStat_C_10);
	DDX_Control(pDX, IDC_EDIT60, m_readStat_C_11);
	DDX_Control(pDX, IDC_EDIT61, m_readStat_C_12);
	DDX_Control(pDX, IDC_EDIT62, m_readTemp_cond_9);
	DDX_Control(pDX, IDC_EDIT63, m_readTemp_cond_10);
	DDX_Control(pDX, IDC_EDIT64, m_readTemp_cond_11);
	DDX_Control(pDX, IDC_EDIT65, m_readTemp_cond_12);
	DDX_Control(pDX, IDC_CMD_WRITE2, m_cmdStart);
	DDX_Control(pDX, IDC_CMD_WRITE3, m_cmdStop);
	DDX_Control(pDX, IDC_CMD_WRITE4, m_cmdPause);
	DDX_Control(pDX, IDC_EDIT66, m_readMode);
	DDX_Control(pDX, IDC_EDIT56, m_readDateD);
	DDX_Control(pDX, IDC_EDIT55, m_readHeureD);
	DDX_Control(pDX, IDC_CMD_WRITE5, m_cmdReprise);
}

BOOL CModbucfgView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CFormView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CModbucfgView diagnostics

#ifdef _DEBUG
void CModbucfgView::AssertValid() const
{
	CFormView::AssertValid();
}

void CModbucfgView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

CModbucfgDoc* CModbucfgView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CModbucfgDoc)));
	return (CModbucfgDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CModbucfgView message handlers

void CModbucfgView::OnInitialUpdate() 
{
	CFormView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	LoadControls();

	//Dans le cas d'une CFormView, les ascenseurs apparaissent automatiquement dès que 
	//la surface cliente de la fenêtre devient trop petite par rapport à la surface réelle.
	//pour ne pas avoir à gérer les ascenseurs, je les supprime: une CFormView hérite de la classe CSCrollView 
	//qui dispose de la fonction SetScaleToFitSize pour adapter la surface de la fenêtre à la taille fenêtrée
	CRect Rect;
    GetParentFrame()->GetWindowRect(&Rect);
    SIZE size;
    size.cx=Rect.Width();
    size.cy=Rect.Height();
    SetScaleToFitSize(size);

	//controle spin
	CSpinButtonCtrl* pSpin=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN2);
	pSpin->SetRange(0,100);//plage du control : 0-100
	pSpin->SetPos((int)m_spinIndex * 1);//valeur initiale 1

	//tableaux pour les write multiple
	m_bValueMultiple.SetSize(100);
	m_sValueMultiple.SetSize(100);
	m_wValueMultiple.SetSize(100);
	m_fValueMultiple.SetSize(100);
	m_dValueMultiple.SetSize(100);

}

void CModbucfgView::LoadControls()
{
	CString str;
	CString sKey;
	CConnection* pConnection;
	POSITION pos;

	//Read functions 
	m_cboReadFunctions.AddString(CString("LoopbackTest"));
	m_cboReadFunctions.AddString(CString("Holding Registers"));
	m_cboReadFunctions.AddString(CString("Input Registers"));
	m_cboReadFunctions.AddString(CString("Coil Status"));
	m_cboReadFunctions.AddString(CString("Discrete Inputs"));
	m_cboReadFunctions.SetCurSel(1);
	
	//Write Functions 
	m_cboWriteFunctions.AddString(CString("Single Register"));
	m_cboWriteFunctions.AddString(CString("Single Coil"));
	m_cboWriteFunctions.AddString(CString("Multiple Registers"));
	m_cboWriteFunctions.AddString(CString("Multiple Coils"));
	m_cboWriteFunctions.SetCurSel(0);


	pos = gConnections.GetStartPosition();
	
	m_cboConnections.ResetContent();

	while (NULL!=pos) {
		gConnections.GetNextAssoc(pos,sKey,pConnection);
		m_cboConnections.AddString(sKey);
	}

	m_cboConnections.SetCurSel(0);


	//Default Values 
	str=_T("1");
    m_edtDevice.SetWindowText(str);
	
	str=_T("0");
	m_edtValue.SetWindowText(str);
	m_edtWriteAddr.SetWindowText(str);
	m_edtReadAddr.SetWindowText(str);

	str=_T("10");
	m_edtQuant.SetWindowText(str);

	str=_T("1000");
	m_edtInterval.SetWindowText(str);

	str=_T("10");
	m_edtQuant2.SetWindowText(str);

	//Data Type 
	m_cboDataType.AddString(CString("char"));
	m_cboDataType.AddString(CString("signed - 16"));
	m_cboDataType.AddString(CString("unsigned - 16"));
	m_cboDataType.AddString(CString("float - 32"));
	m_cboDataType.AddString(CString("float - 32 reverse"));
	m_cboDataType.AddString(CString("double - 64"));
	m_cboDataType.AddString(CString("double - 64 reverse"));
	m_cboDataType.SetCurSel(1);

	//associe la variable m_readVacuum à la ressource IDC_LIST2
	m_readVacuum = (CListCtrl*)GetDlgItem (IDC_LIST2);
	//
	m_readVacuum->SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
	//ajout des titres
	m_readVacuum->InsertColumn(0,_T("Name"),LVCFMT_CENTER,50);
	m_readVacuum->InsertColumn(1,_T("value"),LVCFMT_CENTER,100);
	m_readVacuum->SetBkColor(RGB(202,202,255));
	//nb de lignes
//	m_readVacuum->SetItemCount(12);
	//init tableau
	for (int i=0;i < 12;i++)
	{
		str.Format(TEXT("V%d"), i+1);
		// Insert the item, select every other item.
		m_readVacuum->InsertItem(LVIF_TEXT|LVIF_STATE, i, str, 
      (i%2)==0 ? LVIS_SELECTED : 0, LVIS_SELECTED,0, 0);
		m_readVacuum->SetItemText(i,1,"0");
	}

	//associe la variable m_readCondParam à la ressource IDC_LIST3
	m_readCondParam = (CListCtrl*)GetDlgItem (IDC_LIST3);
	//
	m_readCondParam->SetExtendedStyle(LVS_REPORT | LVS_EX_FULLROWSELECT);
	//ajout des titres
	m_readCondParam->InsertColumn(0,_T("step number"),LVCFMT_CENTER,40);
	m_readCondParam->InsertColumn(1,_T("Pi_min"),LVCFMT_CENTER,50);
	m_readCondParam->InsertColumn(1,_T("Pi_max"),LVCFMT_CENTER,50);
	m_readCondParam->InsertColumn(1,_T("Tn_max"),LVCFMT_CENTER,50);
	m_readCondParam->InsertColumn(1,_T("Tp_max"),LVCFMT_CENTER,50);
	m_readCondParam->InsertColumn(1,_T("Ln"),LVCFMT_CENTER,50);
	//init tableau
	for (int i=0;i < 12;i++)
	{
		str.Format(TEXT("%d"), i+1);
		// Insert the item, select every other item.
		m_readCondParam->InsertItem(LVIF_TEXT|LVIF_STATE, i, str, 
      (i%2)==0 ? LVIS_SELECTED : 0, LVIS_SELECTED,0, 0);
	}
}

void CModbucfgView::StartWork()
{
	SCODE sc = ::CoInitializeEx(NULL,COINIT_MULTITHREADED);
	//SCODE sc = ::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); 

	if (FAILED(sc))
	{
		// warn about non-NULL success codes
		TRACE1("Warning: OleInitialize returned scode = %x",sc);
	}

	m_dwCount=0;
	m_dwSum=0;
	m_dwErrors=0;
}

void CModbucfgView::DoWork()
{
	ldiv_t div_result;
    float fUpdateSpeed;
	DWORD dwTime;
	CString str;
	WORD nError;
	static int iFunction=0;
    
	int iNumLoops=10;
	
	
	fUpdateSpeed=0.0;
	
	if ((m_cboReadFunctions.GetCurSel()>=LOOP_BACK_TEST)&&
		(m_cboReadFunctions.GetCurSel()<=READ_INPUT_STATUS)){
		
		m_dwCount++;
//		nError=ExecuteReadFunction(m_cboReadFunctions.GetCurSel(),dwTime,str);
		nError=ExecuteReadFunction(iFunction++,dwTime,str);
		if (iFunction==6)iFunction=0;
		m_dwSum +=dwTime;  
		
		div_result = ldiv(m_dwCount,iNumLoops);
		
		if (CModbus::ERR_OK!=nError){
			m_dwErrors++;
		}
		
		if (0==div_result.rem){
			fUpdateSpeed=(float)(iNumLoops*1000)/(float)m_dwSum;
			m_dwSum=0; 
		}
		else {
			fUpdateSpeed=(float)(1*1000)/(float)dwTime;
		}

		m_staError.SetWindowText(str);
		str.Format("%d Errors=%d  %4.2f(Up./s) ",m_dwCount,m_dwErrors,fUpdateSpeed);  
		m_statStatus.SetWindowText(str);
	}
	
			
}

void CModbucfgView::EndWork()
{
	::CoUninitialize();
}

void CModbucfgView::OnchkEnablePoll() 
{
	CString sText;
	DWORD dwInterval=0;

	m_edtInterval.GetWindowText(sText);
	dwInterval=DWORD(atol(sText));
	
//	if (dwInterval>10000) {
	if ((dwInterval>10000) || (dwInterval<200)) {
		AfxMessageBox("Max. is 10000 ms and Min. is 200 ms");
		dwInterval=10000;
		sText.Format("%d",dwInterval);
		m_edtInterval.SetWindowText(sText);
		return;
	}

	if (0!=m_butPollEnable.GetCheck()) {
		if (!IsBusy()) {
			CreateThread(0,0,NULL,dwInterval);
		}
		m_butPollEnable.SetCheck(1);
	}
	else {
		Stop();
	}
}


WORD CModbucfgView::ExecuteReadFunction(int iFunction,DWORD& dwTime, CString& rErrorMessage)
{
	CModbus* pModbus;
	CShortArray aValues;
	CByteArray abCoilValues;
	
	CFloatArray afValues;
	CDblArray adValues;

    CString str;
	CString sAux;
    WORD nError;
	int i;
	BOOL bRegisters;
	DWORD dwStart;
	CString sKey;
	CConnection* pConnection =NULL;
	BYTE byDevice;
	WORD wQuant;
	WORD wAddr;
	int nIndex;
	int nPreviusCount;
	int iDataType;

	CListCtrl* vacuum = (CListCtrl*)GetDlgItem (IDC_LIST2);
	CListCtrl* parameters = (CListCtrl*)GetDlgItem (IDC_LIST3);

	i=m_cboConnections.GetCurSel();
	if (i<0) {
		return 0;
	}
	else {
		m_cboConnections.GetLBText(i,sKey);
		
		if (gConnections.Lookup(sKey,pConnection)) {
		
			pModbus=pConnection->m_pModbus;
		}
		else {
			ASSERT(FALSE);
			return 0;
		}
	}

	m_edtDevice.GetWindowText(str);
	byDevice=BYTE(atoi(str));

	switch (iFunction)
	{
	case 0:
	//coils : case READ_OUTPUT_STATUS
	wQuant=13;
	abCoilValues.SetSize(wQuant);
	wAddr=3000;
	nError=pModbus->ReadOutputStatus(byDevice,wAddr,wQuant, abCoilValues);

	str.Format("%d",abCoilValues[0]);
	m_readEil.SetWindowText(str);
	str.Format("%d",abCoilValues[1]);
	m_readStat_C_1.SetWindowText(str);		
	str.Format("%d",abCoilValues[2]);
	m_readStat_C_2.SetWindowText(str);		
	str.Format("%d",abCoilValues[3]);
	m_readStat_C_3.SetWindowText(str);		
	str.Format("%d",abCoilValues[4]);
	m_readStat_C_4.SetWindowText(str);		
	str.Format("%d",abCoilValues[5]);
	m_readStat_C_5.SetWindowText(str);		
	str.Format("%d",abCoilValues[6]);
	m_readStat_C_6.SetWindowText(str);		
	str.Format("%d",abCoilValues[7]);
	m_readStat_C_7.SetWindowText(str);		
	str.Format("%d",abCoilValues[8]);
	m_readStat_C_8.SetWindowText(str);		
	str.Format("%d",abCoilValues[9]);
	m_readStat_C_9.SetWindowText(str);		
	str.Format("%d",abCoilValues[10]);
	m_readStat_C_10.SetWindowText(str);		
	str.Format("%d",abCoilValues[11]);
	m_readStat_C_11.SetWindowText(str);		
	str.Format("%d",abCoilValues[12]);
	m_readStat_C_12.SetWindowText(str);		
	break;

	case 1:
	//holdings : case READ_OUTPUT_REGISTERS:		
//	iDataType = DATA_UNSIGNED_16;
	wQuant=125;
	aValues.SetSize(wQuant);
	wAddr=2000;
	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, aValues);

//	str.Format("%d",aValues[0]);
	str.Format("%u",(WORD)aValues[0]);
	m_readSVd.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[1]);
	m_readSVfin.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[2]);
	m_readSV1.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[3]);
	m_readSV2.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[4]);
	m_readdtp.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[5]);
	m_readdt.SetWindowText(str);
	str.Format("%u",(WORD)aValues[20]);
	m_readSVil.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[25]);
	m_readNbal_max.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[26]);
	m_readFr.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[27]);
	m_readN_cur.SetWindowText(str);	

/*201011 : voir + bas, si mode!=pulsing griser les boutons start/stop/pause/reprise..
	//..sinon fonction de RetMAPR
	switch (aValues[28]){//RetMAPR
	case 0://conditionnement arreté
		m_readMAP.SetWindowText("stop");
		m_cmdStop.EnableWindow(FALSE);//bouton stop
		m_cmdPause.EnableWindow(FALSE);//bouton pause
		m_cmdReprise.EnableWindow(FALSE);//bouton reprise
		m_cmdStart.EnableWindow(TRUE);//bouton start
		break;
	case 2: case 3://conditionnement démarré ou repris
		m_readMAP.SetWindowText("start");
		m_cmdStart.EnableWindow(FALSE);//bouton start
		m_cmdReprise.EnableWindow(FALSE);//bouton reprise
		m_cmdStop.EnableWindow(TRUE);//bouton stop
		m_cmdPause.EnableWindow(TRUE);//bouton pause
		break;
	case 1://conditionnement en pause
		m_readMAP.SetWindowText("pause");
		m_cmdPause.EnableWindow(FALSE);//bouton pause
		m_cmdStart.EnableWindow(FALSE);//bouton start
		m_cmdReprise.EnableWindow(TRUE);//bouton reprise
		m_cmdStop.EnableWindow(TRUE);//bouton stop
		break;
	}
	*/
	switch (aValues[49]){
	case 0://station en mode init
		m_readMode.SetWindowText("init");
		break;
	case 1://station en mode off
		m_readMode.SetWindowText("off");
		break;
	case 2://station en mode heater
		m_readMode.SetWindowText("heater");
		break;
	case 3://station en mode standby
		m_readMode.SetWindowText("standby");
		break;
	case 4://station en mode pulsing=conditionnement
		m_readMode.SetWindowText("pulsing");
		break;
	case 5://station en mode off
		m_readMode.SetWindowText("stop");
		break;
	}
	if (aValues[49] != 4)//201011 : on n'est pas ds le mode pulsing
	{
		m_cmdStart.EnableWindow(FALSE);//bouton start
		m_cmdStop.EnableWindow(FALSE);//bouton stop
		m_cmdPause.EnableWindow(FALSE);//bouton pause
		m_cmdReprise.EnableWindow(FALSE);//bouton reprise	
		m_readMAP.SetWindowText("stop");
	}
	else
	{//mode pulsing
		switch (aValues[28]){//RetMAPR
		case 0://conditionnement arreté
			m_readMAP.SetWindowText("stop");
			m_cmdStop.EnableWindow(FALSE);//bouton stop
			m_cmdPause.EnableWindow(FALSE);//bouton pause
			m_cmdReprise.EnableWindow(FALSE);//bouton reprise
			m_cmdStart.EnableWindow(TRUE);//bouton start
			break;
		case 2: case 3://conditionnement démarré ou repris
			m_readMAP.SetWindowText("start");
			m_cmdStart.EnableWindow(FALSE);//bouton start
			m_cmdReprise.EnableWindow(FALSE);//bouton reprise
			m_cmdStop.EnableWindow(TRUE);//bouton stop
			m_cmdPause.EnableWindow(TRUE);//bouton pause
			break;
		case 1://conditionnement en pause
			m_readMAP.SetWindowText("pause");
			m_cmdPause.EnableWindow(FALSE);//bouton pause
			m_cmdStart.EnableWindow(FALSE);//bouton start
			m_cmdReprise.EnableWindow(TRUE);//bouton reprise
			m_cmdStop.EnableWindow(TRUE);//bouton stop
			break;
		}
		if (aValues[28] != aValues[48])//message affiché
		{
			CString sAux;
			int nIndex;
			int nCount;
			nIndex=m_lstValues.GetCurSel();
			nCount=m_lstValues.GetCount();
			m_lstValues.SetRedraw(FALSE);
			sAux.Format("nI=%d nC=%d,RetMAPR=%d not equal to MAPR=%d",nIndex,nCount,aValues[28],aValues[48]);
			if (nCount%5) 
			{
				m_lstValues.SetCurSel(0);
			}
			m_lstValues.InsertString(nIndex,sAux);
			m_lstValues.SetRedraw(TRUE);
	//		m_lstValues.Invalidate(FALSE);
		}
		else//pas de message
		{
			int nIndex;
			int nCount;
			nIndex=m_lstValues.GetCurSel();
			nCount=m_lstValues.GetCount();
			for(i=0;i<nCount;++i) {
				m_lstValues.DeleteString(i);
			}
			m_lstValues.SetRedraw(TRUE);
	//		m_lstValues.Invalidate(FALSE);
		}
	}//fin mode pulsing

	str.Format("%u",(WORD)aValues[30]);
	m_readNil.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[31]);
	m_readNil_stat.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[34]);
	m_readN_last.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[37]);
	m_readV_cur.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[40]<<16)+(WORD)aValues[41]);//2 mots de 16 bits
	m_readTimer.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[42]);
	m_readNbal.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[47]);
	m_readN_Seqcond.SetWindowText(str);		
	/*101011 : on se sert de RetMAPR à l'adresse 2028
	switch (aValues[48]){
	case 0://conditionnement arreté
//		str.Format("%d",aValues[48]);
		m_readMAP.SetWindowText("stop");
		m_cmdStop.EnableWindow(FALSE);//bouton stop
		m_cmdPause.EnableWindow(FALSE);//bouton pause
		m_cmdStart.EnableWindow(TRUE);//bouton start
		break;
	case 2://conditionnement démarré
		m_readMAP.SetWindowText("start");
		m_cmdStart.EnableWindow(FALSE);//bouton start
		m_cmdStop.EnableWindow(TRUE);//bouton stop
		m_cmdPause.EnableWindow(TRUE);//bouton pause
		break;
	case 1://conditionnement en pause
		m_readMAP.SetWindowText("pause");
		m_cmdPause.EnableWindow(FALSE);//bouton pause
		m_cmdStart.EnableWindow(TRUE);//bouton start
		m_cmdStop.EnableWindow(TRUE);//bouton stop
		break;
	}
	*/
//	str.Format("%d",aValues[49]);
//	m_readMode.SetWindowText(str);		
	/*201011 : voir + haut, si mode!=pulsing griser les boutons start/stop/pause/reprise..
	//..sinon fonction de RetMAPR
	switch (aValues[49]){
	case 0://station en mode init
		m_readMode.SetWindowText("init");
		break;
	case 1://station en mode off
		m_readMode.SetWindowText("off");
		break;
	case 2://station en mode heater
		m_readMode.SetWindowText("heater");
		break;
	case 3://station en mode standby
		m_readMode.SetWindowText("standby");
		break;
	case 4://station en mode pulsing=conditionnement
		m_readMode.SetWindowText("pulsing");
		break;
	case 5://station en mode off
		m_readMode.SetWindowText("stop");
		break;
	}*/
	str.Format("%u",(WORD)aValues[50]);
	m_readNum_C1a.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[51]);
	m_readNum_C1b.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[52]);
	m_readNum_C2a.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[53]);
	m_readNum_C2b.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[54]);
	m_readNum_C3a.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[55]);
	m_readNum_C3b.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[56]);
	m_readNum_C4a.SetWindowText(str);		
	str.Format("%u",(WORD)aValues[57]);
	m_readNum_C4b.SetWindowText(str);		
/*
	str.Format("%u",((WORD)aValues[58]<<16)+(WORD)aValues[59]);//2 mots de 16 bits
	m_readTemp_cond_1.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[60]<<16)+(WORD)aValues[61]);//2 mots de 16 bits
	m_readTemp_cond_2.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[62]<<16)+(WORD)aValues[63]);//2 mots de 16 bits
	m_readTemp_cond_3.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[64]<<16)+(WORD)aValues[65]);//2 mots de 16 bits
	m_readTemp_cond_4.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[66]<<16)+(WORD)aValues[67]);//2 mots de 16 bits
	m_readTemp_cond_5.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[68]<<16)+(WORD)aValues[69]);//2 mots de 16 bits
	m_readTemp_cond_6.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[70]<<16)+(WORD)aValues[71]);//2 mots de 16 bits
	m_readTemp_cond_7.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[72]<<16)+(WORD)aValues[73]);//2 mots de 16 bits
	m_readTemp_cond_8.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[74]<<16)+(WORD)aValues[75]);//2 mots de 16 bits
	m_readTemp_cond_9.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[76]<<16)+(WORD)aValues[77]);//2 mots de 16 bits
	m_readTemp_cond_10.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[78]<<16)+(WORD)aValues[79]);//2 mots de 16 bits
	m_readTemp_cond_11.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[80]<<16)+(WORD)aValues[81]);//2 mots de 16 bits
	m_readTemp_cond_12.SetWindowText(str);
*/
	str.Format("%u",((WORD)aValues[58]));//1 mot de 16 bits
	m_readTemp_cond_1.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[59]));//1 mot de 16 bits
	m_readTemp_cond_2.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[60]));//1 mot de 16 bits
	m_readTemp_cond_3.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[61]));//1 mot de 16 bits
	m_readTemp_cond_4.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[62]));//1 mot de 16 bits
	m_readTemp_cond_5.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[63]));//1 mot de 16 bits
	m_readTemp_cond_6.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[64]));// 1 mot de 16 bits
	m_readTemp_cond_7.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[65]));//1 mot de 16 bits
	m_readTemp_cond_8.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[66]));//1 mot de 16 bits
	m_readTemp_cond_9.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[67]));// mots de 16 bits
	m_readTemp_cond_10.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[68]));//1 mot de 16 bits
	m_readTemp_cond_11.SetWindowText(str);		
	str.Format("%u",((WORD)aValues[69]));//1 mot de 16 bits
	m_readTemp_cond_12.SetWindowText(str);

	break;
/*	str.Format("%d",aValues[50]);
	m_readNum_C1a.SetWindowText(str);		
	str.Format("%d",aValues[51]);
	m_readNum_C1b.SetWindowText(str);		
	str.Format("%d",aValues[52]);
	m_readNum_C2a.SetWindowText(str);		
	str.Format("%d",aValues[53]);
	m_readNum_C2b.SetWindowText(str);		
	str.Format("%d",aValues[54]);
	m_readNum_C3a.SetWindowText(str);		
	str.Format("%d",aValues[55]);
	m_readNum_C3b.SetWindowText(str);		
	str.Format("%d",aValues[56]);
	m_readNum_C4a.SetWindowText(str);		
	str.Format("%d",aValues[57]);
	m_readNum_C4b.SetWindowText(str);		
	str.Format("%d",(aValues[58]<<16)+aValues[59]);//2 mots de 16 bits
	m_readTemp_cond_1.SetWindowText(str);		
	str.Format("%d",(aValues[60]<<16)+aValues[61]);//2 mots de 16 bits
	m_readTemp_cond_2.SetWindowText(str);		
	str.Format("%d",(aValues[62]<<16)+aValues[63]);//2 mots de 16 bits
	m_readTemp_cond_3.SetWindowText(str);		
	str.Format("%d",(aValues[64]<<16)+aValues[65]);//2 mots de 16 bits
	m_readTemp_cond_4.SetWindowText(str);		
	str.Format("%d",(aValues[66]<<16)+aValues[67]);//2 mots de 16 bits
	m_readTemp_cond_5.SetWindowText(str);		
	str.Format("%d",(aValues[68]<<16)+aValues[69]);//2 mots de 16 bits
	m_readTemp_cond_6.SetWindowText(str);		
	str.Format("%d",(aValues[70]<<16)+aValues[71]);//2 mots de 16 bits
	m_readTemp_cond_7.SetWindowText(str);		
	str.Format("%d",(aValues[72]<<16)+aValues[73]);//2 mots de 16 bits
	m_readTemp_cond_8.SetWindowText(str);		
	str.Format("%d",(aValues[74]<<16)+aValues[75]);//2 mots de 16 bits
	m_readTemp_cond_9.SetWindowText(str);		
	str.Format("%d",(aValues[76]<<16)+aValues[77]);//2 mots de 16 bits
	m_readTemp_cond_10.SetWindowText(str);		
	str.Format("%d",(aValues[78]<<16)+aValues[79]);//2 mots de 16 bits
	m_readTemp_cond_11.SetWindowText(str);		
	str.Format("%d",(aValues[80]<<16)+aValues[81]);//2 mots de 16 bits
	m_readTemp_cond_12.SetWindowText(str);		
	break;
*/

	case 2:
	//holdings : case READ_OUTPUT_REGISTERS:		
//	iDataType = DATA_FLOAT;
	wQuant=17;
	afValues.SetSize(wQuant);
	wAddr=2006;
//190412:: Normal->Reverse
//	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues);
	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues,CModbus::REAL_REVERSE);

	str.Format("%g",afValues[0]);
	m_readdP.SetWindowText(str);		
	str.Format("%g",afValues[1]);
	m_readdPsecu.SetWindowText(str);
	str.Format("%g",afValues[13]);
	m_readP_last.SetWindowText(str);
	str.Format("%g",afValues[16]);
	m_readPic.SetWindowText(str);
	break;

	case 3:
	//holdings : case READ_OUTPUT_REGISTERS:		
//	iDataType = DATA_FLOAT;
	wQuant=24;
	afValues.SetSize(wQuant);
	wAddr=2021;
//190412: Normal->Reverse
//	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues);
	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues,CModbus::REAL_REVERSE);

	str.Format("%g",afValues[0]);
	m_readSleil.SetWindowText(str);
	str.Format("%g",afValues[1]);
	m_readSTc.SetWindowText(str);
	str.Format("%g",afValues[7]);
	m_readdPil.SetWindowText(str);
	str.Format("%g",afValues[11]);
	m_readP_cde.SetWindowText(str);
	str.Format("%g",afValues[12]);
	m_readPp.SetWindowText(str);
	break;

	case 4:
	//holdings : case READ_OUTPUT_REGISTERS:		
//	iDataType = DATA_FLOAT;
	wQuant=24;
	afValues.SetSize(wQuant);
	wAddr=/*2108*//*2116*/2118;//060911
//190412: Normal->Reverse
//	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues);
	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues,CModbus::REAL_REVERSE);

	//Pi_max
	for (int i=0;i < 12;i++)
	{
		str.Format("%g",afValues[i]);
		parameters->SetItemText(i,4,str);
	}
	//Pi_min
	for (int i=12;i < 24;i++)
	{
		str.Format("%g",afValues[i]);
		parameters->SetItemText(i-12,5,str);
	}
	break;

	case 5:
	//holdings : case READ_OUTPUT_REGISTERS:		
//	iDataType = DATA_UNSIGNED_16;
	wQuant=125;
	aValues.SetSize(wQuant);
	wAddr=/*2080*/2082;//060911
	nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, aValues);
	//Ln
	for (int i=0;i < 12;i++)
	{
		str.Format("%u",(WORD)aValues[i]);
		parameters->SetItemText(i,1,str);
	}
	//Tn_max
	for (int i=12;i < 24;i++)
	{
		str.Format("%u",(WORD)aValues[i]);
		parameters->SetItemText(i-12,3,str);
	}
	//Tp_max : 12 mots de 16 bits ????
	for (int i=24;i < 36;i++)
	{
		str.Format("%u",(WORD)aValues[i]);
		parameters->SetItemText(i-24,2,str);
	}
	//DateHeureD : 6 mots de 16 bits
	str.Format("%u-%u-%u",(WORD)aValues[84],(WORD)aValues[85],(WORD)aValues[86]);
	m_readDateD.SetWindowText(str);		
	str.Format("%u:%u:%u",(WORD)aValues[87],(WORD)aValues[88],(WORD)aValues[89]);
	m_readHeureD.SetWindowText(str);		
	//vacuum
//	for (int i=90;i < 102;i++)
//	for (int i=88;i < 100;i++)//060911
	for (int i=98;i < 110;i++)//101011
	{
		str.Format("%u",(WORD)aValues[i]);
//		vacuum->SetItemText(i-90,1,str);
//		vacuum->SetItemText(i-88,1,str);
		vacuum->SetItemText(i-98,1,str);
	}
	break;
	}

	rErrorMessage=pModbus->ErrorMessage(nError);
	return nError;
}

void CModbucfgView::OnChangeEditInterval() 
{

	CString sText;
	DWORD dwInterval=0;

	m_edtInterval.GetWindowText(sText);
	dwInterval=DWORD(atol(sText));

//	if (dwInterval>10000) {
//		AfxMessageBox("Max. Interval is 10000 ms");
	if ((dwInterval>10000) || (dwInterval<200)) {
		AfxMessageBox("Max. is 10000 ms and Min. is 200 ms");
		dwInterval=10000;
		sText.Format("%d",dwInterval);
		m_edtInterval.SetWindowText(sText);
		return;
	}

	SetCycleTime(int(dwInterval));	
}

void CModbucfgView::OnCmdWrite() 
{
	BYTE byDevice=0;
	WORD wValue=0;
	WORD wAddr=0;
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	CString strValue;
	CString sVal;
	CWaitCursor WaitCursor;
	double dValue=0.0;

	WORD wQuant, wIndex;

	if (NULL==pModbus) {
		return;
	}

	m_edtValue.GetWindowText(strValue);
	sVal= strValue;
	wValue = (WORD)atoi(strValue);

	m_edtDevice.GetWindowText(strValue);
	byDevice = (BYTE)atoi(strValue);

	m_edtWriteAddr.GetWindowText(strValue);
	wAddr = (WORD)atoi(strValue);

	m_edtQuant2.GetWindowText(strValue);
	wQuant=(BYTE)(atoi(strValue));

	m_edtIndex.GetWindowText(strValue);
	wIndex=(BYTE)(atoi(strValue));

	switch (m_cboWriteFunctions.GetCurSel()) {
		
	case PRESET_SINGLE_REGISTER:

		switch(m_cboDataType.GetCurSel()) {
			
		case DATA_CHAR:
			sVal.TrimLeft();
			if (sVal.GetLength()>0) { 
				nError=pModbus->PresetSingleRegister(byDevice,wAddr,WORD(sVal[0]));
			}
			break;
		case DATA_SIGNED_16:			
		case DATA_UNSIGNED_16:
			if (sVal.GetLength()>0) { 
				nError=pModbus->PresetSingleRegister(byDevice,wAddr,WORD(atoi(sVal)));
			}
			break;
		case DATA_FLOAT:
			nError=pModbus->PresetSingleRegister(byDevice,wAddr,float(atof(sVal)));
			break;
		case DATA_FLOAT_REVERSE:
			nError=pModbus->PresetSingleRegister(byDevice,wAddr,float(atof(sVal)),CModbus::REAL_REVERSE);
			break;
		case DATA_DOUBLE:
			nError=pModbus->PresetSingleRegister(byDevice,wAddr,double(atof(sVal)));
		
			break;
		case DATA_DOUBLE_REVERSE:
			nError=pModbus->PresetSingleRegister(byDevice,wAddr,double(atof(sVal)),CModbus::REAL_REVERSE);
			break;
		}
		if(nError!=CModbus::ERR_OK){
			WaitCursor.Restore();
			AfxMessageBox(pModbus->ErrorMessage(nError));
		}
		break;

	case FORCE_SINGLE_COIL:
		nError=pModbus->ForceSingleCoil(byDevice,wAddr,(BOOL)wValue);
		if(nError!=CModbus::ERR_OK){
			WaitCursor.Restore();  
			AfxMessageBox(pModbus->ErrorMessage(nError));
		}
		break;

	case WRITE_MULTIPLE_REGISTERS:
		{
		//controle spin
		CSpinButtonCtrl* pSpin=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN2);

		switch(m_cboDataType.GetCurSel()) {			
		case DATA_CHAR:
			sVal.TrimLeft();
			if (sVal.GetLength()>0) { 
				m_sValueMultiple.SetAt(wIndex,wValue);
				nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_sValueMultiple);
			}
			break;
		case DATA_SIGNED_16:
		case DATA_UNSIGNED_16:
			if (sVal.GetLength()>0) { 
				m_wValueMultiple.SetAt(wIndex,wValue);
				nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_wValueMultiple);
			}
			break;
		case DATA_FLOAT:
			m_fValueMultiple.SetAt(wIndex,wValue);
			nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_fValueMultiple);
			break;
		case DATA_FLOAT_REVERSE:
			m_fValueMultiple.SetAt(wIndex,wValue);
			nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_fValueMultiple,CModbus::REAL_REVERSE);
			break;
		case DATA_DOUBLE:
			m_dValueMultiple.SetAt(wIndex,wValue);
			nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_dValueMultiple);
			break;
		case DATA_DOUBLE_REVERSE:
			m_dValueMultiple.SetAt(wIndex,wValue);
			nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_dValueMultiple,CModbus::REAL_REVERSE);
			break;
		}		
		if(nError!=CModbus::ERR_OK){
			WaitCursor.Restore();
			AfxMessageBox(pModbus->ErrorMessage(nError));
		}
		}
		break;

	case WRITE_MULTIPLE_COILS:
		{
		//controle spin
		CSpinButtonCtrl* pSpin=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN2);
//		pSpin->SetRange(0,100);//plage du control : 0-100

		m_bValueMultiple.SetAt(wIndex,((wValue!=0)?1:0));

		nError=pModbus->ForceMultipleCoils(byDevice,wAddr,wQuant,m_bValueMultiple);
		if(nError!=CModbus::ERR_OK){
			WaitCursor.Restore();  
			AfxMessageBox(pModbus->ErrorMessage(nError));
		}
		}
		break;
		
	}
	
}

CModbus* CModbucfgView::GetConnection()
{

	int i;
	CModbus* pModbus=NULL;
	CConnection* pConnection=NULL;
	CString sKey;

	i=m_cboConnections.GetCurSel();
	
	if (i<0) {
		ASSERT(FALSE);
		pModbus=NULL;
	}
	else {
		m_cboConnections.GetLBText(i,sKey);
		
		if (gConnections.Lookup(sKey,pConnection)) {
		
			pModbus=pConnection->m_pModbus;
		}
		else {
			ASSERT(FALSE);
			pModbus=NULL;
		}
	}
	
	return pModbus;
}

void CModbucfgView::OnCbnSelchangeCboReadFunction()
{
	// TODO : ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnCbnSelchangeCboWriteFunction()
{
	// TODO : ajoutez ici le code de votre gestionnaire de notification de contrôle
}


void CModbucfgView::OnAppMemMap()
{
	// TODO : ajoutez ici le code de votre gestionnaire de commande
	AfxMessageBox(_T("modbus memory map : \n\n -holding registers adr:0x2000 qty:300\n-coils adr:0x3000 qty:100\n-discrete inputs adr:0x1000 qty:4\n-input registers adr:0x4000 qty:4"));
}

void CModbucfgView::OnEnChangeEditQuant()
{
	// TODO :  S'il s'agit d'un contrôle RICHEDIT, le contrôle
	// n'enverra la notification que si vous substituez la fonction __super::OnInitDialog()
	// et l'appel CRichEditCtrl().SetEventMask()
	// par l'indicateur ENM_CHANGE assorti de l'opérateur OR dans le masque.

	// TODO :  Ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnEnChangeEditAddr()
{
	// TODO :  S'il s'agit d'un contrôle RICHEDIT, le contrôle
	// n'enverra la notification que si vous substituez la fonction __super::OnInitDialog()
	// et l'appel CRichEditCtrl().SetEventMask()
	// par l'indicateur ENM_CHANGE assorti de l'opérateur OR dans le masque.

	// TODO :  Ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnEnChangeEditQuant2()
{
	// TODO :  S'il s'agit d'un contrôle RICHEDIT, le contrôle
	// n'enverra la notification que si vous substituez la fonction __super::OnInitDialog()
	// et l'appel CRichEditCtrl().SetEventMask()
	// par l'indicateur ENM_CHANGE assorti de l'opérateur OR dans le masque.

	// TODO :  Ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnLbnSelchangeList5()
{
	// TODO : ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnLbnSelchangeLstValues()
{
	// TODO : ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnEnChangeEditAddrWri()
{
	// TODO :  S'il s'agit d'un contrôle RICHEDIT, le contrôle
	// n'enverra la notification que si vous substituez la fonction __super::OnInitDialog()
	// et l'appel CRichEditCtrl().SetEventMask()
	// par l'indicateur ENM_CHANGE assorti de l'opérateur OR dans le masque.

	// TODO :  Ajoutez ici le code de votre gestionnaire de notification de contrôle
}

void CModbucfgView::OnEnChangeEditValue()
{
	// TODO :  S'il s'agit d'un contrôle RICHEDIT, le contrôle
	// n'enverra la notification que si vous substituez la fonction __super::OnInitDialog()
	// et l'appel CRichEditCtrl().SetEventMask()
	// par l'indicateur ENM_CHANGE assorti de l'opérateur OR dans le masque.

	// TODO :  Ajoutez ici le code de votre gestionnaire de notification de contrôle
}



void CModbucfgView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO : ajoutez ici le code de votre gestionnaire de messages et/ou les paramètres par défaut des appels

	if (nSBCode == SB_ENDSCROLL)
	{
		return ;//rejeter les messages non validess
	}
	//treiter uniquement les messagse de défilement de IDC_SPIN2)
	if (pScrollBar->GetDlgCtrlID()==IDC_SPIN2)
	{
		CString strValue;
		strValue.Format("%d",(int)nPos);
		((CSpinButtonCtrl*)pScrollBar)->GetBuddy()->SetWindowText(strValue);
	}

	__super::OnVScroll(nSBCode, nPos, pScrollBar);
}


void CModbucfgView::OnCmdRead()
{
	ldiv_t div_result;
    float fUpdateSpeed;
	DWORD dwTime;
	CString str;
	WORD nError;
    
	int iNumLoops=10;
	
	
	fUpdateSpeed=0.0;
	
	if ((m_cboReadFunctions.GetCurSel()>=LOOP_BACK_TEST)&&
		(m_cboReadFunctions.GetCurSel()<=READ_INPUT_STATUS)){
		
		m_dwCount++;
		nError=ExecuteCmdReadFunction(m_cboReadFunctions.GetCurSel(),dwTime,str);
		m_dwSum +=dwTime;  
		
		div_result = ldiv(m_dwCount,iNumLoops);
		
		if (CModbus::ERR_OK!=nError){
			m_dwErrors++;
		}
		
		if (0==div_result.rem){
			fUpdateSpeed=(float)(iNumLoops*1000)/(float)m_dwSum;
			m_dwSum=0; 
		}
		else {
			fUpdateSpeed=(float)(1*1000)/(float)dwTime;
		}

		m_staError.SetWindowText(str);
		str.Format("%d Errors=%d  %4.2f(Up./s) ",m_dwCount,m_dwErrors,fUpdateSpeed);  
		m_statStatus.SetWindowText(str);
	}
	
}

WORD CModbucfgView::ExecuteCmdReadFunction(int iFunction,DWORD& dwTime, CString& rErrorMessage)
{
	CModbus* pModbus;
	CShortArray aValues;
	CByteArray abCoilValues;
	
	CFloatArray afValues;
	CDblArray adValues;

    CString str;
	CString sAux;
    WORD nError;
	int i;
	BOOL bRegisters;
	DWORD dwStart;
	CString sKey;
	CConnection* pConnection =NULL;
	BYTE byDevice;
	WORD wQuant;
	WORD wAddr;
	int nIndex;
	int nPreviusCount;
	int iDataType;
    
	i=m_cboConnections.GetCurSel();

	iDataType= m_cboDataType.GetCurSel();

	if (i<0) {
		return 0;
	}
	else {
		m_cboConnections.GetLBText(i,sKey);
		
		if (gConnections.Lookup(sKey,pConnection)) {
		
			pModbus=pConnection->m_pModbus;
		}
		else {
			ASSERT(FALSE);
			return 0;
		}
	}

	m_edtDevice.GetWindowText(str);
	
	byDevice=BYTE(atoi(str));

	m_edtQuant.GetWindowText(str);
	wQuant=BYTE(atoi(str));

	m_edtReadAddr.GetWindowText(str);
	wAddr=WORD(atoi(str));

	switch (iFunction) {

	case LOOP_BACK_TEST:
		dwStart=::timeGetTime();
		nError=pModbus->LoopbackTest(byDevice);
		dwTime=::timeGetTime()-dwStart;
		str="";
		bRegisters=FALSE;
		break;
	
	case READ_OUTPUT_REGISTERS:	
		dwStart=::timeGetTime();
		switch (iDataType) {			
		case DATA_CHAR:
		case DATA_SIGNED_16:
		case DATA_UNSIGNED_16:
			aValues.SetSize(wQuant);
			nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, aValues);
			break;
		case DATA_FLOAT:
			afValues.SetSize(wQuant);
			nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues);
			break;
		case DATA_FLOAT_REVERSE:
			afValues.SetSize(wQuant);
			nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, afValues,CModbus::REAL_REVERSE);
			break;
		case DATA_DOUBLE:
			adValues.SetSize(wQuant);
			nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, adValues);
			break;
		case DATA_DOUBLE_REVERSE:
			adValues.SetSize(wQuant);
			nError=pModbus->ReadOutputRegisters(byDevice,wAddr,wQuant, adValues,CModbus::REAL_REVERSE);
			break;
		}		
		dwTime=::timeGetTime()-dwStart;
		bRegisters=TRUE;	
		break;

		case READ_INPUT_REGISTERS:	
			dwStart=::timeGetTime();
			switch (iDataType) {				
			case DATA_CHAR:
			case DATA_SIGNED_16:
			case DATA_UNSIGNED_16:
				aValues.SetSize(wQuant);
				nError=pModbus->ReadInputRegisters(byDevice,wAddr,wQuant, aValues);
				break;
			case DATA_FLOAT:
				afValues.SetSize(wQuant);
				nError=pModbus->ReadInputRegisters(byDevice,wAddr,wQuant, afValues);
				break;
			case DATA_FLOAT_REVERSE:
				afValues.SetSize(wQuant);
				nError=pModbus->ReadInputRegisters(byDevice,wAddr,wQuant, afValues,CModbus::REAL_REVERSE);
				break;
			case DATA_DOUBLE:
				adValues.SetSize(wQuant);
				nError=pModbus->ReadInputRegisters(byDevice,wAddr,wQuant, adValues);
				break;
			case DATA_DOUBLE_REVERSE:
				adValues.SetSize(wQuant);
				nError=pModbus->ReadInputRegisters(byDevice,wAddr,wQuant, adValues,CModbus::REAL_REVERSE);
				break;
			}
			dwTime=::timeGetTime()-dwStart;
			bRegisters=TRUE;
			break;
			
		case READ_OUTPUT_STATUS:
			dwStart=::timeGetTime();
			abCoilValues.SetSize(wQuant);
			nError=pModbus->ReadOutputStatus(byDevice,wAddr,wQuant, abCoilValues);
			dwTime=::timeGetTime()-dwStart;
			bRegisters=FALSE;
			break;
				
		case READ_INPUT_STATUS:
			dwStart=::timeGetTime();
			abCoilValues.SetSize(wQuant);
			nError=pModbus->ReadInputStatus(byDevice,wAddr,wQuant, abCoilValues); 
			dwTime=::timeGetTime()-dwStart;
			bRegisters=FALSE;
			break;
	}

	nIndex=m_lstValues.GetCurSel();
	nPreviusCount=m_lstValues.GetCount();

	m_lstValues.SetRedraw(FALSE);
	
	if (bRegisters) {
		for(i=0;i<wQuant;++i) {
			switch (iDataType) {
			case DATA_CHAR:
				sAux.Format("[%u]=%c 0x%x",wAddr+i,(char)aValues[i],(WORD)aValues[i]);
			    break;
            case DATA_SIGNED_16:
				sAux.Format("[%u]=%d 0x%x",wAddr+i,aValues[i],(WORD)aValues[i]);
				break;
			case DATA_UNSIGNED_16:
				sAux.Format("[%u]=%d 0x%x",wAddr+i,(WORD)aValues[i],(WORD)aValues[i]);
				break;
            case DATA_FLOAT:
			case DATA_FLOAT_REVERSE:
				sAux.Format("[%u]=%g ",wAddr+2*i,afValues[i]);
				break;
			case DATA_DOUBLE:
			case DATA_DOUBLE_REVERSE:
				sAux.Format("[%u]=%g ",wAddr+4*i,adValues[i]);
				break;
			}			
			//sAux.Format("[%u]=%d  %d  0x%x  ",wAddr+i,aValues[i],(WORD)aValues[i],(WORD)aValues[i]);
			m_lstValues.DeleteString(i);
			m_lstValues.InsertString(i,sAux);
		}
	}
	else {		
		for(i=0;i<abCoilValues.GetSize();++i) {
			sAux.Format("[%u]=%d ",wAddr+i,abCoilValues[i]);
			m_lstValues.DeleteString(i);
			m_lstValues.InsertString(i,sAux);
		}
	}

	if (nPreviusCount>wQuant) {
		for (i=wQuant;i<nPreviusCount;i++){
			m_lstValues.DeleteString(wQuant);
		}
	}
	
	if ((nIndex>0)&&(nIndex<m_lstValues.GetCount())) {
		m_lstValues.SetCurSel(nIndex);
	}

	m_lstValues.SetRedraw(TRUE);
	m_lstValues.Invalidate(FALSE);
		
	rErrorMessage=pModbus->ErrorMessage(nError);
	return nError;
}

void CModbucfgView::OnEnChangeEdit16()
{
	BYTE byDevice=0;
	WORD wAddr=2023;
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	CString str, sVal;
	CWaitCursor WaitCursor;

	if (pModbus==NULL)
		return;

	m_edtDevice.GetWindowText(str);
	byDevice = (BYTE)atoi(str);

	GetDlgItem(IDC_EDIT16)->GetWindowText(sVal);
	AfxMessageBox("CModbucfgView::OnEnChangeEdit16()");	
	//case DATA_FLOAT:
	nError=pModbus->PresetSingleRegister(byDevice,wAddr,float(atof(sVal)));
	if(nError!=CModbus::ERR_OK){
		WaitCursor.Restore();  
		AfxMessageBox(pModbus->ErrorMessage(nError));
	}
}

void CModbucfgView::OnBnClickedButton1()
{
	CString OpenFilter;
	OpenFilter = "Text File (*.txt)|*.txt||";

	//créer l'instance avec le constructeur
	CFileDialog FileOpenDialog(
		TRUE,//ouverture de la boite de dialogue
		NULL,
		NULL,
		OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,
		OpenFilter, // filtre
		AfxGetMainWnd()); // la fenetre parent

	if(FileOpenDialog.DoModal()==IDOK)//affichage
	{// ouverture de fichier avec la structure suivante :
		//SVil Sleil STc Nbal_max Fr N_cur N_Seqcond Num_C(8x)
		unsigned int wTmpBuf;
		float fTmpBuf;
		CWordArray writeParamInit_120;
		CFloatArray writeParamInit_121;
		writeParamInit_120.SetSize(100);//pr les adresses modbus
		writeParamInit_121.SetSize(100);
		CString str;
		FILE* pFile = fopen (FileOpenDialog.GetPathName(), "r");	
		if(pFile == NULL)		
			return;	
		/* ptr au debut du fichier*/
		fseek( pFile, 0L, SEEK_SET );
		/* lecture a artir du fichier*/
		fscanf(pFile,"%d ",&wTmpBuf);
		writeParamInit_120.SetAtGrow(0,wTmpBuf);//SVil
		fscanf(pFile,"%f ",&fTmpBuf);
		writeParamInit_121.SetAtGrow(0,fTmpBuf);//Sleil
		fscanf(pFile,"%f ",&fTmpBuf);
		writeParamInit_121.SetAtGrow(1,fTmpBuf);//STc
		for (int i=3;i<14;i++){//nb de mots ds le fichier
			fscanf(pFile,"%d ",&wTmpBuf);
			if (i<5)
				writeParamInit_120.SetAtGrow(i+2,wTmpBuf);//Nbal_max/Fr
			else if (i==5)
				writeParamInit_120.SetAtGrow(i+22,wTmpBuf);//NSeq_cond
			else if (i>5)
				writeParamInit_120.SetAtGrow(i+24,wTmpBuf);//8xNum_C
		}
		fclose(pFile);

		str.Format("SVil=%d, Sleil=%f NSeqcond=%d",writeParamInit_120[0],writeParamInit_121[0],writeParamInit_120[27]);
		AfxMessageBox(str);

		//copie des buffers
		m_wValueMultiple.Copy( writeParamInit_120 );
		m_fValueMultiple.Copy( writeParamInit_121 );
	}
}

void CModbucfgView::OnBnClickedButton2()
{
	BYTE byDevice=0;
	WORD wAddr=0;
	CString strValue;
	CWaitCursor WaitCursor;

	WORD wQuant;

	m_edtDevice.GetWindowText(strValue);
	byDevice = (BYTE)atoi(strValue);

//	case DATA_UNSIGNED_16:
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	if (NULL==pModbus) {
		return;
	}
	wAddr = 2020;
	wQuant=38;
	nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_wValueMultiple);

//	case DATA_FLOAT:
	pModbus=GetConnection();
	if (NULL==pModbus) {
		return;
	}
	wAddr = 2021;
	wQuant=2;
	nError=pModbus->PresetMultipleRegisters(byDevice,wAddr,wQuant,m_fValueMultiple);
	
	if(nError!=CModbus::ERR_OK){
		WaitCursor.Restore();
		AfxMessageBox(pModbus->ErrorMessage(nError));
	}		
}


void CModbucfgView::OnCmdStart()
{	
	BYTE byDevice=0;
	WORD wAddr=2048;
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	CString strValue;
	CWaitCursor WaitCursor;

	if (NULL==pModbus) {
		return;
	}

	CString modeString;
	m_readMode.GetWindowText(modeString);
	if (strncmp("PULSING",modeString,8))//on n'est pas en mode conditionnement
	{
		return;
	}

	m_edtDevice.GetWindowText(strValue);
	byDevice = (BYTE)atoi(strValue);

	nError=pModbus->PresetSingleRegister(byDevice,wAddr,WORD(0x2));
	if(nError!=CModbus::ERR_OK){
		WaitCursor.Restore();
		AfxMessageBox(pModbus->ErrorMessage(nError));
	}
}

void CModbucfgView::OnCmdStop()
{
	BYTE byDevice=0;
	WORD wAddr=2048;
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	CString strValue;
	CWaitCursor WaitCursor;

	if (NULL==pModbus) {
		return;
	}

	CString modeString;
	m_readMode.GetWindowText(modeString);
	if (strncmp("PULSING",modeString,8))//on n'est pas en mode conditionnement
	{
		return;
	}

	m_edtDevice.GetWindowText(strValue);
	byDevice = (BYTE)atoi(strValue);

	nError=pModbus->PresetSingleRegister(byDevice,wAddr,WORD(0x0));
	if(nError!=CModbus::ERR_OK){
		WaitCursor.Restore();
		AfxMessageBox(pModbus->ErrorMessage(nError));
	}
}

void CModbucfgView::OnCmdPause()
{
	BYTE byDevice=0;
	WORD wAddr=2048;
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	CString strValue;
	CWaitCursor WaitCursor;

	if (NULL==pModbus) {
		return;
	}

	CString modeString;
	m_readMode.GetWindowText(modeString);
	if (strncmp("PULSING",modeString,8))//on n'est pas en mode conditionnement
	{
		return;
	}

	m_edtDevice.GetWindowText(strValue);
	byDevice = (BYTE)atoi(strValue);

	nError=pModbus->PresetSingleRegister(byDevice,wAddr,WORD(0x1));
	if(nError!=CModbus::ERR_OK){
		WaitCursor.Restore();
		AfxMessageBox(pModbus->ErrorMessage(nError));
	}
}

void CModbucfgView::OnButtonReprise()
{
	BYTE byDevice=0;
	WORD wAddr=2048;
	CModbus* pModbus=GetConnection();
	WORD nError=CModbus::ERR_OK;
	CString strValue;
	CWaitCursor WaitCursor;

	if (NULL==pModbus) {
		return;
	}

	CString modeString;
	m_readMode.GetWindowText(modeString);
	if (strncmp("PULSING",modeString,8))//on n'est pas en mode conditionnement
	{
		return;
	}

	m_edtDevice.GetWindowText(strValue);
	byDevice = (BYTE)atoi(strValue);

	nError=pModbus->PresetSingleRegister(byDevice,wAddr,WORD(0x3));
	if(nError!=CModbus::ERR_OK){
		WaitCursor.Restore();
		AfxMessageBox(pModbus->ErrorMessage(nError));
	}
}
