📄 xxxopcsrvdlg.cpp
字号:
// XXXOPCSRVDlg.cpp : implementation file
//
#include "stdafx.h"
#include "xxxOPCSRV.h"
#include "xxxOPCSRVDlg.h"
#include "localmodbus.h"
#include "commparameters.h"
#include "eventview.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DEVICE_ID 1
CCriticalSection s_lkDrv;
CEventView *s_pEventView;
CLocalModbus *s_pLMBus ;
int callsvr(HINSTANCE hInstance, unsigned *nTerminate, BOOL bEmbedding, unsigned nRegister );
void LogMsg (UINT nResID, LPCSTR format, ...);
/////////////////////////////////////////////////////////////////////////////
// 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()
};
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()
/////////////////////////////////////////////////////////////////////////////
// CXXXOPCSRVDlg dialog
CXXXOPCSRVDlg::CXXXOPCSRVDlg(CWnd* pParent /*=NULL*/)
: CDialog(CXXXOPCSRVDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CXXXOPCSRVDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bEmbedding = FALSE;
m_nRegister = FALSE;
m_nTerminateThread = 0;
m_pThread = NULL;
}
void CXXXOPCSRVDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CXXXOPCSRVDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CXXXOPCSRVDlg, CDialog)
//{{AFX_MSG_MAP(CXXXOPCSRVDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(ID_BTN_STOP, OnBtnStop)
ON_BN_CLICKED(IDC_BTN_START, OnBtnStart)
ON_BN_CLICKED(IDC_BTN_SETTINGS, OnBtnSettings)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXXXOPCSRVDlg message handlers
BOOL CXXXOPCSRVDlg::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
// Split this window into to two panes, one on top of the other. Top
// pane will be "data view", and bottowm will be "event view". Return
// FALSE if fail.
RECT rc;
GetClientRect (&rc);
rc.left = 0;
rc.top = 43;
s_pEventView = new CEventView();
s_pEventView->Create( 0L, "Event", WS_VISIBLE|WS_VSCROLL|WS_HSCROLL|WS_BORDER, rc, this, ID_VIEW_EVENT );
s_pLMBus = new CLocalModbus();
//Get cfg file path
char szModule[_MAX_PATH+1] = {0};
GetModuleFileName( AfxGetInstanceHandle(), szModule, _MAX_PATH);
// Convert to short path
char szModuleShort[_MAX_PATH+1];
GetShortPathName( szModule, szModuleShort, _MAX_PATH);
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath( szModuleShort, drive, dir, fname, ext );
_makepath( szModuleShort, drive, dir, "", "" );
m_strCfgFile.Format( "%s%s", szModuleShort, "tsiopcsrv.cfg");
//get settings from cfg file
CFile af;
if ( af.Open(m_strCfgFile, CFile::modeRead ) )
{
CArchive ar( &af, CArchive::load );
s_pLMBus->Serialize( ar );
ar.Close();
af.Close();
LogMsg( tEventInformation, "Read previous configurations OK");
}
else //set default value
{
LogMsg( tEventInformation, "Using default configuration");
}
//open com port
if ( !s_pLMBus->IsActive() )
s_pLMBus->UpdateSerialConfig( s_pLMBus->ComPort(), s_pLMBus->BaudRate(), s_pLMBus->Parity() ) ;
if (!s_pLMBus->IsActive())
{
LogMsg( tEventError, "Failed to open Com%d", s_pLMBus->ComPort() );
}
else
{
LogMsg( tEventInformation, "Opened Com%d", s_pLMBus->ComPort() );
}
StartServer() ;
if ( m_bEmbedding )
ShowWindow( SW_MINIMIZE );
return TRUE; // return TRUE unless you set the focus to a control
}
void CXXXOPCSRVDlg::StartServer( BOOL bFlag )
{
if ( bFlag )
{
if ( m_pThread )
return; //already started
LogMsg( tEventInformation, "Server starting...");
m_nTerminateThread = 0;
m_pThread = AfxBeginThread( ThreadLoop, (LPVOID) this );
}
else
{
if ( !m_pThread )
return; //not started
m_nTerminateThread = 1;
LogMsg( tEventInformation, "Server aborting...");
}
}
/////////////////////////////////////////////////////////////////////////////
UINT CXXXOPCSRVDlg::ThreadLoop(LPVOID pParam)
{
CXXXOPCSRVDlg *pDlg = (CXXXOPCSRVDlg *)pParam;
ASSERT( pDlg );
//if ( s_pLMBus->LoopbackTest( DEVICE_ID ) )
// LogMsg( tEventError, "Modbus salve device not found on Com%d", s_pLMBus->ComPort() );
//enter service loop
callsvr( AfxGetInstanceHandle(), &(pDlg->m_nTerminateThread), pDlg->m_bEmbedding, pDlg->m_nRegister );
//release resources
pDlg->m_pThread = NULL;
pDlg->PostMessage( WM_CLOSE );
return 0;
}
void CXXXOPCSRVDlg::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 CXXXOPCSRVDlg::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 CXXXOPCSRVDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//driver functions called by opc server
WORD GetDrvData( WORD nAddr, WORD nPDU, WORD nPos, WORD *pData )
{
ASSERT ( s_pLMBus );
CSafeLock sf (&s_lkDrv);
WORD wErr = 0;
switch( nPDU )
{
case 1:
{
BYTE ba;
CByteArray ary;
ary.Add( ba );
wErr = s_pLMBus->ReadOutputStatus( nAddr, nPos, 1, ary );
*pData = ary[0];
}
break;
case 2:
{
BYTE ba;
CByteArray ary;
ary.Add( ba );
wErr = s_pLMBus->ReadInputStatus( nAddr, nPos, 1, ary );
*pData = ary[0];
}
break;
case 3:
{
WORD wa;
CWordArray ary;
ary.Add( wa );
wErr = s_pLMBus->ReadOutputRegisters( nAddr, nPos, 1, ary );
*pData = ary[0];
}
break;
case 4:
{
WORD wa;
CWordArray ary;
ary.Add( wa );
wErr = s_pLMBus->ReadInputRegisters( nAddr, nPos, 1, ary );
*pData = ary[0];
}
break;
default:
wErr = 1;
}
return (wErr == 0);
}
WORD GetDrvData10( WORD nAddr, WORD nPDU, WORD nPos, WORD *pData )
{
ASSERT ( s_pLMBus );
CSafeLock sf (&s_lkDrv);
WORD wErr = 0;
#define nCount 10
switch( nPDU )
{
case 1:
{
BYTE ba[nCount];
CByteArray ary;
for (int i = 0 ; i < nCount; i++ )
ary.Add( ba[i] );
wErr = s_pLMBus->ReadOutputStatus( nAddr, nPos, nCount, ary );
for ( i = 0 ; i < nCount; i++ )
*pData++ = ary[i];
}
break;
case 2:
{
BYTE ba[nCount];
CByteArray ary;
for (int i = 0 ; i < nCount; i++ )
ary.Add( ba[i] );
wErr = s_pLMBus->ReadInputStatus( nAddr, nPos, nCount, ary );
for ( i = 0 ; i < nCount; i++ )
*pData++ = ary[i];
}
break;
case 3:
{
WORD wa[nCount];
CWordArray ary;
for (int i = 0 ; i < nCount; i++ )
ary.Add( wa[i] );
wErr = s_pLMBus->ReadOutputRegisters( nAddr, nPos, nCount, ary );
for ( i = 0 ; i < nCount; i++ )
*pData++ = ary[i];
}
break;
case 4:
{
WORD wa[nCount];
CWordArray ary;
for (int i = 0 ; i < nCount; i++ )
ary.Add( wa[i] );
wErr = s_pLMBus->ReadInputRegisters( nAddr, nPos, nCount, ary );
for ( i = 0 ; i < nCount; i++ )
*pData++ = ary[i];
}
break;
default:
wErr = 1;
}
return (wErr == 0);
}
BOOL SetDrvData( WORD nAddr, WORD nPDU, WORD nPos, WORD wA )
{
ASSERT ( s_pLMBus );
CSafeLock sf (&s_lkDrv);
WORD wErr = 0;
switch( nPDU )
{
case 1:
{
wErr = s_pLMBus->ForceSingleCoil( nAddr, nPos, wA == 0 ? 0 : 1 );
}
break;
case 3:
{
wErr = s_pLMBus->PresetSingleRegister( nAddr, nPos, wA );
}
break;
default:
return 1;
}
return (wErr == 0);
}
void CXXXOPCSRVDlg::OnBtnStop()
{
// TODO: Add your control notification handler code here
StartServer( FALSE );
}
void CXXXOPCSRVDlg::OnBtnStart()
{
// TODO: Add your control notification handler code here
StartServer();
}
void CXXXOPCSRVDlg::OnCancel()
{
if ( !m_bEmbedding && s_pLMBus || m_pThread )
if ( !(AfxMessageBox("Server is running, Exit anyway?", MB_OKCANCEL) == IDOK) )
return;
m_nTerminateThread = 1;
//waitting for termination of service
UINT nTick = GetTickCount();
while ( m_pThread && ( GetTickCount() - nTick < 1000 ))
Sleep( 20 );
delete s_pLMBus;
delete s_pEventView;
CDialog::OnCancel();
}
void CXXXOPCSRVDlg::OnBtnSettings()
{
// TODO: Add your control notification handler code here
if ( !s_pLMBus )
return;
CCommParameters dlgSetting;
dlgSetting.m_pLModbus = s_pLMBus;
if ( dlgSetting.DoModal() == IDOK )
{
//save settings to cfg file
CFile af;
if ( af.Open( m_strCfgFile, CFile::modeCreate | CFile::modeWrite ) )
{
CArchive ar( &af, CArchive::store );
s_pLMBus->Serialize( ar );
AfxMessageBox("To ensure that changes take effect, please restart server.");
ar.Close();
af.Close();
}
else
AfxMessageBox("Failed to save changes.");
}
}
void LogMsg (UINT nResID, LPCSTR format, ...)
{
ASSERT( s_pEventView );
va_list data;
char cMsgBuffer[ MAX_PATH ];
va_start(data, format);
int msgLen =_vsnprintf(cMsgBuffer, MAX_PATH-3, format, data);
if (msgLen == -1)
return ;
// Add the message to the queue.
s_pEventView->LogMsg ((EVENTTYPE)nResID, cMsgBuffer);
// Reset additional arguments pointer:
va_end(data);
}
BOOL CXXXOPCSRVDlg::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
// re-direct menu messages to event view
if (( nID == ID_VIEW_CLEAR || nID == ID_VIEW_ERRORONLY) && !nCode )
s_pEventView->SendMessage( WM_COMMAND, nID, 0L );
return CDialog::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -