From cba2694c0ce8b7c24e82ac08a22dfb84f2dffa19 Mon Sep 17 00:00:00 2001 From: TAO Cheng Date: Wed, 12 Nov 2014 08:58:34 +0800 Subject: [PATCH] TCPIP SERVER --- .../Msi/Hsi/SevenOcean/So7_TCPIP_Server.cpp | 121 ++++++++++++++---- .../Msi/Hsi/SevenOcean/So7_TCPIP_Server.h | 3 +- .../Hsi/Tools/UsbUtility/UsbUtil/Mv_Util.rc | 14 +- .../Tools/UsbUtility/UsbUtil/So7_Option.cpp | 1 + .../UsbUtil/So7_Util_PLC_TCPIP_SERVER.cpp | 13 +- .../Hsi/Tools/UsbUtility/UsbUtil/resource.h | 2 + .../Hsi/Tools/UsbUtility/UsbUtil_VS2010.suo | Bin 159744 -> 156160 bytes 7 files changed, 123 insertions(+), 31 deletions(-) diff --git a/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.cpp b/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.cpp index 5e2f1a0..58e76b6 100644 --- a/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.cpp +++ b/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.cpp @@ -10,9 +10,10 @@ const int WSA_MINOR_VERSION = 1; const BYTE CommHeader[]={0x46,0x49,0x4E,0x53}; const BYTE HandShaking[]={0X46,0X49,0X4E,0X53,0X00,0X00,0X00,0X10,0X00,0X00,0X00,0X01,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0X00,0X00,0X00,0X05}; -const BYTE DRW_SData[]={0X46,0X49,0X4E,0X53,0X00,0X00,0X00,0X18,0X00,0X00,0X00,0X02,0X00,0X00,0X00,0X00,0XC0,0X00,0X02,0X00,0X03,0X00,0X00,0X05,0X00,0XFF,0X01,0X01,0X00,0X00}; +const BYTE DRW_SData[]={0X46,0X49,0X4E,0X53,0X00,0X00,0X00,0X16,0X00,0X00,0X00,0X02,0X00,0X00,0X00,0X00,0XC0,0X00,0X02,0X00,0X03,0X00,0X00,0X05,0X00,0XFF,0X01,0X01,0X00,0X00}; const int DRW_SDataIndexDataSize=7; +const int DRW_SDataHeadDataSize=8; const int DRW_SDataIndexData=30; const int DRW_RDataIndexDA1=20; @@ -42,7 +43,10 @@ CSo7_TCPIP_Server::CSo7_TCPIP_Server() m_hMsgWnd=NULL; m_ServerStarted=FALSE; m_Socket=INVALID_SOCKET; - m_SreverIPAddress; + m_SreverIPAddress.S_un.S_un_b.s_b1=127; + m_SreverIPAddress.S_un.S_un_b.s_b2=0; + m_SreverIPAddress.S_un.S_un_b.s_b3=0; + m_SreverIPAddress.S_un.S_un_b.s_b4=1; m_iServerPortNumber=static_cast(0); for (int i=0;i(0); + for (int i=0;i>8) & 0x0ff; m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i+1]=iData & 0x0ff; } - m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData+2*_datasize); - m_TCPIPBuf[CH_SEND]._size=sizeof(HandShaking); + m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData-DRW_SDataHeadDataSize+_datasize); + m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+_datasize*2; SendBuffer(); @@ -300,8 +339,8 @@ BOOL CSo7_TCPIP_Server::Response_Sensor_State(short _datasize) { m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+i]=m_TCPIPServerState._PLCSensorState[i]; } - m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData+2*_datasize); - m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+2*_datasize; + m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData-DRW_SDataHeadDataSize+_datasize); + m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+_datasize*2; SendBuffer(); return TRUE; @@ -318,15 +357,20 @@ BOOL CSo7_TCPIP_Server::Response_CCD_DATA(short _Addr,short _datasize) memcpy(m_TCPIPBuf[CH_SEND]._buffer,DRW_SData,sizeof(DRW_SData)); int iData(0); - for (int i=_Addr;i<_Addr+_datasize;i++) + BYTE DM_Data[4]={0,0,0,0}; + for (int i=0;i<_datasize;i++) { - iData=m_CCDData[i]; - m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i]=(iData>>8) & 0x0ff; - m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i+1]=iData & 0x0ff; + iData=m_CCDData_D10000[_Addr+i/2]; + DM_Data[2]=(iData>>24) & 0x0ff; + DM_Data[3]=(iData>>16) & 0x0ff; + DM_Data[0]=(iData>>8) & 0x0ff; + DM_Data[1]=iData & 0x0ff; + m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i]=DM_Data[2*(i%2)+0]; + m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i+1]=DM_Data[2*(i%2)+1]; } - m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData+2*_datasize); + m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData-DRW_SDataHeadDataSize+_datasize); - m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+2*_datasize; + m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+_datasize*2; SendBuffer(); @@ -520,8 +564,16 @@ void CSo7_TCPIP_Server::m_ProcessSocketReadEvent(SOCKET s) else if (m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCMD1]==0x01 &&m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCMD2]==0x01) { - short iAddr=(m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr1]<<8)+m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr2]; - short iDataSize=(m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCh1]<<8)+m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCh2]; + short iAddr(0); + short iDataSize(0); + BYTE bData[2]={0,0}; + bData[0]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr1]; + bData[1]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr2]; + iAddr=(bData[0]<<8)+bData[1]; + bData[0]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr1]; + bData[1]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr2]; + iDataSize=(bData[0]<<8)+bData[1]; + if (iAddr>=20000) { iPara=RESPONSE_READ_ERRCODE; @@ -531,10 +583,6 @@ void CSo7_TCPIP_Server::m_ProcessSocketReadEvent(SOCKET s) Response_CCD_DATA((iAddr-10060),iDataSize); iPara=RESPONSE_READ_CCD_DATA; } - else if (iAddr>=8000) - { - iPara=RESPONSE_WRITE_PLC_STATE; - } else if (iAddr>=5000) { Response_PLC_State(1); @@ -542,12 +590,41 @@ void CSo7_TCPIP_Server::m_ProcessSocketReadEvent(SOCKET s) } else { + RESPONSE_UNKNOWN_State(); iPara=RESPONSE_UNKNOWN; } } + else if (m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCMD1]==0x01 + &&m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCMD2]==0x02) + { + short iAddr(0); + short iDataSize(0); + BYTE bData[2]={0,0}; + bData[0]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr1]; + bData[1]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr2]; + iAddr=(bData[0]<<8)+bData[1]; + bData[0]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr1]; + bData[1]=m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr2]; + iDataSize=(bData[0]<<8)+bData[1]; + if (iAddr>=8000) + { + RESPONSE_UNKNOWN_State(); + iPara=RESPONSE_WRITE_PLC_STATE; + } + else + { + RESPONSE_UNKNOWN_State(); + iPara=RESPONSE_UNKNOWN; + } + } + } m_TCPIPBuf[CH_RECV]._CompletedSize = 0; m_TCPIPBuf[CH_RECV]._hProtoPending=FALSE; - ::PostMessage(m_hMsgWnd,WM_TCPIP_MSG,FD_READ,iPara); + + if (iPara!=RESPONSE_READ_PLC_STATE) + { + ::PostMessage(m_hMsgWnd,WM_TCPIP_MSG,FD_READ,iPara); + } } diff --git a/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.h b/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.h index ed24d31..5914097 100644 --- a/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.h +++ b/PcDmis/Base/Interfac/Msi/Hsi/SevenOcean/So7_TCPIP_Server.h @@ -93,7 +93,7 @@ public: static struct_so7_tcpip_buff m_TCPIPBuf[lChannelSize]; static s_tcpip_state m_TCPIPServerState; - int m_CCDData[MAX_CCD_ADDR]; + int m_CCDData_D10000[MAX_CCD_ADDR]; BOOL StartServer(HWND _hWnd,short _nPort); BOOL StopServer(); @@ -103,6 +103,7 @@ public: BOOL Response_Sensor_State(short _datasize); BOOL Response_CCD_DATA(short _Addr,short _datasize); + BOOL RESPONSE_UNKNOWN_State(); LRESULT OnSocket(WPARAM wParam, LPARAM lParam); private: diff --git a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/Mv_Util.rc b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/Mv_Util.rc index 8267414..6a1165d 100644 --- a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/Mv_Util.rc +++ b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/Mv_Util.rc @@ -16,7 +16,7 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// 中文(简体,中国) resources +// Chinese (Simplified, PRC) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED @@ -1072,8 +1072,8 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "Exit",IDCANCEL,512,305,39,14 GROUPBOX "TCP/IP Server Control",IDC_STATIC,17,12,87,81 - PUSHBUTTON "Start",IDC_BUTTON_PLC_TCPIP_SERVER_START,28,32,63,18 - PUSHBUTTON "Stop",IDC_BUTTON_PLC_TCPIP_SERVER_STOP,28,65,63,18 + PUSHBUTTON "Start",IDC_BUTTON_PLC_TCPIP_SERVER_START,29,49,63,18 + PUSHBUTTON "Stop",IDC_BUTTON_PLC_TCPIP_SERVER_STOP,29,73,63,18 EDITTEXT IDC_EDIT_MSG,342,14,201,273,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL PUSHBUTTON "Update",IDC_BUTTON_PLC_TCPIP_SERVER_UPDATESTATE,277,70,40,14 GROUPBOX "DM DATA",IDC_STATIC,110,12,214,81 @@ -1091,6 +1091,8 @@ BEGIN CONTROL "",IDC_LIST_PLC_TCPIP_SERVER_CCDDATA,"SysListView32",LVS_REPORT | WS_BORDER | WS_TABSTOP,24,110,294,166 GROUPBOX "Static",IDC_STATIC,17,97,307,214 PUSHBUTTON "Update",IDC_BUTTON_PLC_TCPIP_SERVER_UPDATEDATA,277,291,40,14 + EDITTEXT IDC_EDIT_PLC_TCPIP_SERVER_PORTNUMBER,51,30,40,14,ES_AUTOHSCROLL + LTEXT "Port",IDC_STATIC,29,33,14,8 END @@ -1728,12 +1730,12 @@ BEGIN IDS_SO7_ABOUTBOX "&About Utility for SO7..." END -#endif // 中文(简体,中国) resources +#endif // Chinese (Simplified, PRC) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// 英语(美国) resources +// English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US @@ -2692,7 +2694,7 @@ BEGIN END END -#endif // 英语(美国) resources +#endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Option.cpp b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Option.cpp index bf3f8f8..ef3083f 100644 --- a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Option.cpp +++ b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Option.cpp @@ -464,6 +464,7 @@ void CSo7_Option::OnBnClickedOk() CSo7_Util_PLC_TCPIP_SERVER* pSo7_Util_PLC_TCPIP_SERVER=new CSo7_Util_PLC_TCPIP_SERVER(); pSo7_Util_PLC_TCPIP_SERVER->DoModal(); delete pSo7_Util_PLC_TCPIP_SERVER; + pSo7_Util_PLC_TCPIP_SERVER=NULL; if (g_pSo7_TCPIP_Server) { delete g_pSo7_TCPIP_Server; diff --git a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Util_PLC_TCPIP_SERVER.cpp b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Util_PLC_TCPIP_SERVER.cpp index 5c8f51a..3b332d3 100644 --- a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Util_PLC_TCPIP_SERVER.cpp +++ b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/So7_Util_PLC_TCPIP_SERVER.cpp @@ -89,6 +89,9 @@ BOOL CSo7_Util_PLC_TCPIP_SERVER::OnInitDialog() GetDlgItem(IDC_EDIT_PLC_TCPIP_SERVER_STATE_LASER2)->SetWindowTextW(str); str.Format(_T("%d"),g_pSo7_TCPIP_Server->m_TCPIPServerState._PLCRunningState); GetDlgItem(IDC_EDIT_PLC_TCPIP_SERVER_PLC_STATE)->SetWindowTextW(str); + + GetDlgItem(IDC_EDIT_PLC_TCPIP_SERVER_PORTNUMBER)->SetWindowTextW(_T("9600")); + m_UpdateListControl(E_LISTCTRL_TITLE); UpdateData(FALSE); @@ -99,9 +102,15 @@ BOOL CSo7_Util_PLC_TCPIP_SERVER::OnInitDialog() void CSo7_Util_PLC_TCPIP_SERVER::OnBnClickedButtonPlcTcpipServerStart() { + CString str; + UpdateData(TRUE); + USES_CONVERSION; + GetDlgItem(IDC_EDIT_PLC_TCPIP_SERVER_PORTNUMBER)->GetWindowText(str); + const char* cTempValue=T2A(str); + short sPortNumber=static_cast(atoi(cTempValue)); if (g_pSo7_TCPIP_Server) { - g_pSo7_TCPIP_Server->StartServer(m_hWnd,9600); + g_pSo7_TCPIP_Server->StartServer(m_hWnd,sPortNumber); m_csMSG=_T(" ok."); OutputWithScroll(m_csMSG,m_edMSG); } @@ -194,7 +203,7 @@ void CSo7_Util_PLC_TCPIP_SERVER::m_UpdateListControl(int _type) cTmp=T2A(csTmp); if (g_pSo7_TCPIP_Server) { - g_pSo7_TCPIP_Server->m_CCDData[iRow]=atoi(cTmp); + g_pSo7_TCPIP_Server->m_CCDData_D10000[iRow]=atoi(cTmp); } } break; diff --git a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/resource.h b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/resource.h index dd83e23..74c9e04 100644 --- a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/resource.h +++ b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil/resource.h @@ -1073,6 +1073,8 @@ #define IDC_EDIT_PLC_TCPIP_SERVER_PLC_STATE 1899 #define IDC_BUTTON_PLC_TCPIP_SERVER_UPDATESTATE2 1900 #define IDC_BUTTON_PLC_TCPIP_SERVER_UPDATEDATA 1900 +#define IDC_EDIT__PLC_TCPIP_PORTNUMBER2 1901 +#define IDC_EDIT_PLC_TCPIP_SERVER_PORTNUMBER 1901 #define IDC_LIST_PLC_TCPIP_SERVER_CCDDATA 1902 #define IDC_IPADDRESS_PLC_TCPIP 1903 #define IDC_BUTTON_DIY_EXIT_BUTTON 32740 diff --git a/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil_VS2010.suo b/PcDmis/Base/Interfac/Msi/Hsi/Tools/UsbUtility/UsbUtil_VS2010.suo index d05cb0fd5458e66c2d134d323ab533c889784812..2dbd0d9803efffec9468ee0f996d5d3dc917ad2f 100644 GIT binary patch delta 3665 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