123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909 |
- // CSerialProcess.cpp
- #include "stdafx.h"
- #include "SerialProcess.h"
- //#include <windows.h>
- #include <cstdio>
- #include <process.h>
- #include "AutoRobot.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- BOOL gb_send = FALSE;
- // 引用全局对象;
- extern DWORD g_dwCID;
- extern HWND ghWnd;
- extern CRITICAL_SECTION g_cs_vt;
- #define USE_INSERT_AUTORAISE 1 // 支持插入命令时,自增容器大小 ;
- #define USE_THREADRUN_INSERT 1 // 支持采集线程运行插入命令;
- #define USE_POSTMESSAGE 1 // 是否支持线程向窗口发送消息;
- /************************************************************************/
- /*
- 函数:构造函数
- */
- /************************************************************************/
- CSerialProcess::CSerialProcess( )
- {
- m_hCom = INVALID_HANDLE_VALUE;
- m_bOpen = FALSE;
- m_hRunCtrl = NULL;
- m_hCollectCtrl = NULL;
- m_hResponsetime = NULL;
- m_bCollected = FALSE;
-
- m_nResponseTime = 200; // 默认响应时间500ms;
- m_nAFrequency = 1000; // 默认采集频率3000ms;
- m_iSLSize = 0;
- // 如何设置得太小了,会在线程里出现第m_iSLSize中断几秒的现象;
- // 这个size可以在构造时传入;
- // ccomprocess cp( int nszie );
- // m_iSLSize = nSize;
- // m_iSLSize = 40;
- //m_sendlist.reserve(m_iSLSize); // 预设容器最大容量;
- }
- /************************************************************************/
- /*
- 函数:析构函数
- */
- /************************************************************************/
- CSerialProcess::~CSerialProcess()
- {
- CloseComm();
- }
- /************************************************************************/
- /*
- 函数:设置容器大小;
- 参数:
- nSize: 要设置的值;
- */
- /************************************************************************/
- void CSerialProcess::SetSize(const int &nSize)
- {
- m_iSLSize = nSize;
- m_sendlist.reserve(nSize);
- }
- /************************************************************************/
- /*
- 函数:自增容器大小
- */
- /************************************************************************/
- void CSerialProcess::RaiseSize()
- {
- m_sendlist.reserve(++m_iSLSize);
- }
- /************************************************************************/
- /*
- 函数:打开串口;
- 参数:
- iCommPort: 串口号;
- iRate: 波特率;
- iDataBit: 数据位;
- iStopBit: 停止位;
- iParity: 校验码;
- iResponsetime: 响应时间;
- iInterval: 采集频率;
-
- */
- /************************************************************************/
- BOOL CSerialProcess::OpenComm(
- const int &iCommPort, // 1.串口;
- const int &iRate, // 2.波特率;
- const int &iDataBit, // 3.数据位;
- const int &iStopBit, // 4.停止位;
- const int &iParity, // 5.校验码;
- const int &iResponsetime, // 6.响应时间;
- const int &iInterval) // 7.采集频率;
- {
- m_bOpen = FALSE;
- //ASSERT(iCommPort!=0); // 这个在debug下会出错,很奇怪?iCommPort的值明明是不是为0,却依旧在Debug下出错了.
- if(iCommPort == 0)
- return FALSE;
- int temp=0;
- char tmp[20]="\\\\.\\com";
- char buffer[20];
- m_iPort = iCommPort;
- _itoa(m_iPort,buffer,10);
- strcat(tmp,buffer);
- // 1.打开指定串口
- m_hCom = CreateFile(
- tmp, // 串口名称(COMx)
- GENERIC_READ | GENERIC_WRITE, // 串口属性为可读/写
- 0, // 串口设备必须被独占性的访问
- NULL, // 无安全属性
- OPEN_EXISTING, // 串口设备必须使用OPEN_EXISTING参数
- NULL , // 同步式 I/O
- NULL // 对于串口设备而言此参数必须为0
- );
- if(m_hCom == INVALID_HANDLE_VALUE)
- {
- // 如果该串口不存在或者正被另外一个应用程序使用, 则打开失败,程序退出
- LOG4C((LOG_NOTICE,"串口损坏或正在使用,打开串口%d失败",iCommPort));
- return FALSE;
- }
- m_nResponseTime = iResponsetime;
- m_nAFrequency = iInterval;
- BOOL result;
- // 2.设置端口的I/O缓冲区大小;
- result = SetupComm(m_hCom,1024,1024);
- ASSERT(result);
- if(!result)
- return FALSE;
- // 3.清除端口I/O;(清除接收/发送缓冲区)
- result = PurgeComm(m_hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
- ASSERT(result);
- if(!result)
- return FALSE;
- // 4.设置串口参数:波特率、数据位、校验位、停止位等信息(DCB结构体)
- COMMTIMEOUTS timeout;
- DCB dcb;
- // 5.获取该端口的默认参数
- result = GetCommState(m_hCom, &dcb);
- ASSERT(result);
- if(!result)
- return FALSE;
- // 6.修改串口参数;
- dcb.Parity = iParity;
- if(dcb.Parity == NOPARITY)
- dcb.fParity = FALSE;
- else
- dcb.fParity = TRUE;
- dcb.BaudRate = iRate;
- dcb.ByteSize = iDataBit;
- dcb.StopBits = iStopBit;
- if(dcb.ByteSize == 8)
- dcb.StopBits = ONESTOPBIT;
- // 7.重新设置参数
- result = SetCommState(m_hCom, &dcb);
- ASSERT(result);
- if(!result)
- return FALSE;
- // 8.获取该端口的默认超时参数
- result = GetCommTimeouts(m_hCom, &timeout);
- ASSERT(result);
- if(!result)
- return FALSE;
- // 9.修改超时结构;
- timeout.ReadIntervalTimeout = MAXDWORD;
- timeout.ReadTotalTimeoutMultiplier = 0;
- timeout.ReadTotalTimeoutConstant = 0;
- timeout.WriteTotalTimeoutMultiplier = 0;
- timeout.WriteTotalTimeoutConstant = 0;
- // 10.重新设置端口的默认超时参数
- result = SetCommTimeouts(m_hCom,&timeout);
- ASSERT( result );
- if( !result )
- return FALSE;
- m_bOpen = TRUE;
- // 11.创建一永久性无信号事件,用于ReadFile前设备的响应时间等待;
- m_hResponsetime = CreateEvent(NULL,TRUE,FALSE,NULL); // 无信号事件;
- return TRUE;
- }
- /************************************************************************/
- /*
- 函数:关闭串口,并释放资源;
- */
- /************************************************************************/
- BOOL CSerialProcess::CloseComm()
- {
- SetEvent(m_hFrequencyCtrl);
- gb_send = TRUE;
- Sleep(50); // 等待最后一次SendMessage完成;
- if ( m_hCollectCtrl != NULL)
- if ( WaitForSingleObject( m_hCollectCtrl ,INFINITE) == WAIT_OBJECT_0)
- ResetEvent(m_hCollectCtrl);
- if ( m_hRunCtrl != NULL )
- {
- SetEvent(m_hRunCtrl);
- if ( m_hThreaObj != NULL)
- {
- if (WaitForSingleObject(m_hThreaObj,INFINITE) != WAIT_FAILED)
- {
- CloseHandle(m_hThreaObj);
- m_hThreaObj = NULL;
- m_bCollected = FALSE;
- }
- }
- CloseHandle( m_hRunCtrl );
- m_hRunCtrl = NULL;
- }
- if ( m_hCollectCtrl != NULL)
- {
- CloseHandle(m_hCollectCtrl);
- m_hCollectCtrl = NULL;
- }
- RemoveAllSendCommand();
- RemoveAllRecvCommand();
- m_bOpen = FALSE;
- if( m_hCom != INVALID_HANDLE_VALUE )
- {
- BOOL bResult = CloseHandle( m_hCom );
- if( !bResult )
- {
- gb_send = FALSE;
- return FALSE;
- }
- m_hCom = INVALID_HANDLE_VALUE;
- }
- if ( m_hResponsetime )
- {
- CloseHandle(m_hResponsetime);
- m_hResponsetime = NULL;
- }
- if ( m_hFrequencyCtrl )
- {
- CloseHandle(m_hFrequencyCtrl);
- m_hFrequencyCtrl = NULL;
- }
- gb_send = FALSE;
- LOG4C((LOG_NOTICE,"关闭串口成功"));
- return TRUE;
- }
- /************************************************************************/
- /*
- 函数:对串口进行读取数据;
- 参数:
- pBuf: 存储读串口时返回的数据;
- len: 读串口数据的长度;
- 返回值:返回实际串口读到的长度;
- */
- /************************************************************************/
- int CSerialProcess::Read(BYTE *pBuf, int len)
- {
- //DWORD nTick = GetTickCount();
- if(m_hCom == INVALID_HANDLE_VALUE)
- return 0;
- if( pBuf == NULL || !::AfxIsValidAddress(pBuf, len, FALSE ) )
- return 0;
- if( !m_bOpen )
- return 0;
- BOOL bReadStatus;
- DWORD dwBytesRead, dwErrorFlags;
- COMSTAT ComStat;
- ClearCommError( m_hCom, &dwErrorFlags, &ComStat );
- if ( WaitForSingleObject(m_hResponsetime,m_nResponseTime) == WAIT_TIMEOUT)
- ClearCommError(m_hCom,&dwErrorFlags,&ComStat);
- if( !ComStat.cbInQue ) return( 0 );
- dwBytesRead = (DWORD) ComStat.cbInQue;
- if( len < (int) dwBytesRead ) dwBytesRead = (DWORD) len;
- // ReadFile成功读到数据,返回非0值,否则返回0;
- bReadStatus = ReadFile( m_hCom, pBuf, dwBytesRead, &dwBytesRead , NULL);
- #if 0
- if( !bReadStatus )
- {
- PurgeComm(m_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
- return 0;
- }
- PurgeComm(m_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
- return( (int) dwBytesRead );
- #else
- PurgeComm(m_hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
- return (bReadStatus ? dwBytesRead : 0);
- #endif
- }
- /************************************************************************/
- /*
- 函数:对串口进行写数据;
- 参数:
- pBuf: 写串口的数据;
- len: 写串口的数据长度;
- 返回值:返回实现写串口的长度;
- */
- /************************************************************************/
- int CSerialProcess::Write(const BYTE *pBuf, int len)
- {
- if( !m_bOpen )
- return 0;
- if(m_hCom == INVALID_HANDLE_VALUE || len<=0)
- return 0;
- DWORD dwResult = 0;
- BOOL bResult = WriteFile( m_hCom, pBuf, (DWORD)len, &dwResult, NULL );
- if(bResult)
- return dwResult;
- else
- return 0;
- }
- // 挂起之前,得让采集线程完成一次采集.(Write与read)
- /************************************************************************/
- /*
- 函数:外掊接口函数:写命令;
- 参数:
- szCommand: 要对串口进行写的数据;
- iLen: 要对串口进行写的数据长度;
- iAddr: 串口地址;
- */
- /************************************************************************/
- BOOL CSerialProcess::SetCommand(const BYTE *szCommand, int iLen, int iAddr)
- {
- if( !m_bOpen )
- return 0;
- if(m_hCom == INVALID_HANDLE_VALUE )
- return 0;
- SetEvent(m_hFrequencyCtrl);
- gb_send = TRUE;
- Sleep(50);
- BOOL bResult = FALSE;
- if ( m_hCollectCtrl != NULL)
- {
- //while ( WaitForSingleObject( m_hCollectCtrl,INFINITE) == WAIT_OBJECT_0 )//
- while ( WaitForSingleObject( m_hCollectCtrl,500) == WAIT_OBJECT_0 )//
- {
- ResetEvent( m_hCollectCtrl );
- // **其实这一步可以不需要了,只有将m_hCollectCtrl信号获取了就可以了;
- // **那样,即使线程在运行,也不会对串口进行读写操作了;
- ::SuspendThread( m_hThreaObj );
- Sleep(3000);
- bResult = TRUE;
- // 挂起线程后,进行设置;
- int RWlen = Write(szCommand,iLen);
- #if USE_POSTMESSAGE
- SendMessage(ghWnd,WM_SHOWWRITEDATA,RWlen,(LPARAM)szCommand);
- #endif
- BYTE temp[1024] = {0};
- int RRlen = Read(temp,1024);
- #if USE_POSTMESSAGE
- SendMessage(ghWnd,WM_SHOWREADDATA,RRlen,(LPARAM)temp);
- #endif
- // 设置完毕,恢复线程;
- ::ResumeThread( m_hThreaObj );
- SetEvent( m_hCollectCtrl );
- break;
- }
- }
- else
- {
- bResult = TRUE;
- Write(szCommand,iLen);
- BYTE temp[1024] = {0};
- Read(temp,1024);
- }
- gb_send = FALSE;
- ResetEvent(m_hFrequencyCtrl);
- return bResult;
- }
- /************************************************************************/
- /*
- 函数:采集线程(关于线程,如果可以,应该使线程尽量简单,这样稳定性高于一切);
- 参数:
- lpParamter: 类对象本身;
- 注意:
- 1.Sendmessage在线程里,会使线程不稳定.因为SendMessage是阻塞的,要等待函数完成才返回,造成线程等待,CPU高涨;
- 所以在线程中,最好使用PostMessage或PostThreadMessage;
- 2.在线程外部动态 添加命 令或 删除命令,会使线程对vector的遍历产生影响,迭代器会指乱,有可能会产生线程内for死循环;
- 所以,禁止外部在线程运行时操作容器;
- */
- /************************************************************************/
- DWORD WINAPI CSerialProcess::CollectThreadProc(LPVOID lpParamter)
- {
- CSerialProcess *pCommProc = (CSerialProcess*)lpParamter;
- if ( pCommProc->m_hCom == NULL || pCommProc->m_hCom == INVALID_HANDLE_VALUE )
- return 0;
- if ( pCommProc->m_sendlist.size() == 0 )
- return 0;
- HANDLE hRunCtrl = pCommProc->m_hFrequencyCtrl;
- vector <STSendCommand>::iterator it_SendCommand;
- vector <STRecvMessage>::iterator it_RecvMessage;
- STSendCommand ST_SendCommand = {0};
- STRecvMessage ST_RecvMessage = {0};
- do
- {
- for ( it_SendCommand = pCommProc->m_sendlist.begin(); it_SendCommand != pCommProc->m_sendlist.end(); it_SendCommand++)
- {
- if ( WaitForSingleObject( pCommProc->m_hCollectCtrl ,10) == WAIT_OBJECT_0)
- {
- ResetEvent( pCommProc->m_hCollectCtrl );
- ST_SendCommand = *it_SendCommand;
- int iRWLine = pCommProc->Write( ST_SendCommand.bySend, ST_SendCommand.iSLen );
- #if USE_POSTMESSAGE
- if( !gb_send )// 线程给窗口发送消息,最好不要用PostThreadMessage,直接使用PostMessage;
- PostMessage(ghWnd,WM_SHOWWRITEDATA,iRWLine,(LPARAM)ST_SendCommand.bySend);
- #endif
- // 是否保存返回的数据;
- if ( ST_SendCommand.bRecv == TRUE)
- {
- ZeroMemory(&ST_RecvMessage,sizeof(STRecvMessage));
- ST_RecvMessage.iPort = pCommProc->m_iPort;
- ST_RecvMessage.iAddr = ST_SendCommand.iAddr;
- ST_RecvMessage.dwSID = ST_SendCommand.dwSID;
- ST_RecvMessage.iRLen = 0;
- memcpy( ST_RecvMessage.szCheck, ST_SendCommand.szCheck, strlen(ST_SendCommand.szCheck) );
- memcpy( ST_RecvMessage.szMark, ST_SendCommand.szMark, strlen(ST_SendCommand.szMark) );
- ST_RecvMessage.iRLen = pCommProc->Read(ST_RecvMessage.byRecv,MAX_RECVSIZE);
- #if USE_POSTMESSAGE
- if( !gb_send )
- PostMessage(ghWnd,WM_SHOWREADDATA,(WPARAM)&ST_RecvMessage,0);
- #endif
- // .判断相应的数据元素是否存在;
- BOOL bExist = FALSE;
- if( g_vtRecv.size() != 0)
- {
- for( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); it_RecvMessage++)
- {
- if( ST_RecvMessage.dwSID == ((STRecvMessage)*it_RecvMessage).dwSID )
- {
- // 若存在,直接赋值;
- EnterCriticalSection( &g_cs_vt );
- *it_RecvMessage = ST_RecvMessage;//memcpy(it_RecvMessage,&ST_RecvMessage,sizeof(STRecvMessage));
- LeaveCriticalSection( &g_cs_vt );
- bExist = TRUE;
- break;
- }
- }
- }
- else // 第一次插入;
- {
- bExist = TRUE;
- EnterCriticalSection( &g_cs_vt );
- g_vtRecv.push_back( ST_RecvMessage );
- LeaveCriticalSection( &g_cs_vt );
- }
- if( !bExist ) // 不存在;
- {
- EnterCriticalSection( &g_cs_vt );
- g_vtRecv.push_back( ST_RecvMessage );
- LeaveCriticalSection( &g_cs_vt );
- }
- }
- else
- {
- BYTE temp[1024] = {0};
- int iRRlen = pCommProc->Read(temp,1024);
- #if 0
- if( !gb_send )
- PostMessage(ghWnd,WM_SHOWREADDATA,iRRlen,(LPARAM)temp);
- #endif
- }
- SetEvent( pCommProc->m_hCollectCtrl ); // 信号在这里设置为有,使线程能够完成一次数据采集;
- }
- else
- {
- LOG4C((LOG_NOTICE,"->线程内循环被停止"));
- break;//如果事件无信号,直接退出循环,解决for循环的无效次数;
- }
- // 线程等待采集时间过后,才进行采集(采集频率);
- WaitForSingleObject( hRunCtrl,pCommProc->m_nAFrequency );
- }
- }while (WaitForSingleObject(pCommProc->m_hRunCtrl,10) != WAIT_OBJECT_0); // 这样使用线程,!= WAIT_OBJECT_0 在结束线程时,比使用== WAIT_TIMEOUT要快结束 ;
- //while (WaitForSingleObject(pCommProc->m_hRunCtrl,10) == WAIT_TIMEOUT); // 这里等待的时间不能为0,如果为0就马上返回,
- // 对线程的控制就变得有点缓慢了;
- LOG4C((LOG_NOTICE,"线程结束"));
- return 0;
- }
- /************************************************************************/
- /*
- 函数:启动采集线程;
- */
- /************************************************************************/
- int CSerialProcess::AutoCollect()
- {
- if ( m_bCollected )
- return 0;
- if ( m_hCom == NULL || m_hCom == INVALID_HANDLE_VALUE )
- return 0;
- m_hRunCtrl = CreateEvent(NULL,TRUE,FALSE,NULL); // 无信号事件;
- if ( m_hRunCtrl == NULL )
- return -1;
- m_hCollectCtrl = CreateEvent(NULL, TRUE ,TRUE ,NULL);
- if ( m_hCollectCtrl == NULL )
- return -1;
- m_hFrequencyCtrl = CreateEvent(NULL,TRUE,FALSE,NULL); // 无信号事件;
- if ( m_hFrequencyCtrl == NULL )
- return -1;
- m_hThreaObj = CreateThread(NULL,0,CollectThreadProc,this,0,&m_dwThreadID);
- if ( m_hThreaObj == NULL )
- return -1;
- m_bCollected = TRUE;
- return 0;
- }
- /************************************************************************/
- /*
- 函数:停止采集线程;
- */
- /************************************************************************/
- int CSerialProcess::StopCollect()
- {
- if ( m_hCom == NULL || m_hCom == INVALID_HANDLE_VALUE )
- return 0;
- if ( m_hRunCtrl )
- {
- SetEvent( m_hRunCtrl );
- }
- if (WaitForSingleObject(m_hRunCtrl,INFINITE) != WAIT_TIMEOUT)
- {
- CloseHandle(m_hThreaObj);
- m_hThreaObj = NULL;
- }
- CloseHandle( m_hRunCtrl );
- m_hRunCtrl = NULL;
- CloseHandle( m_hCollectCtrl );
- m_hCollectCtrl = NULL;
- m_bCollected = FALSE;
- return 0;
- }
- /************************************************************************/
- /*
- 函数:插入发送命令;
- 参数:
- szCommand: 要插入的数据;
- iLen: 要插入的数据长度;
- iAddr: 串口地址;
- szMark: 命令的特征码;
- szCheck: 命令的校验方式;
- iSNum: 命令的发送顺序;
- bRecv: 是否保存命令读取的数据;
-
- 注意:
- 1.对命令的添加,会影响到采集线程的安全性与稳定性,建议在添加前,先停止线程;
- 盖因线程for循环时,有可能在插入新的元素后,迭代器指向的元素就不是下一个,出现漏取的现象;
- 所以,要么在for完整循环后插入元素,要么停止线程;
- */
- /************************************************************************/
- int CSerialProcess::InsertCommand(const BYTE *szCommand, int iLen, int iAddr,const char *szMark, const char *szCheck, int iSNum, bool bRecv)
- {
- #if !USE_THREADRUN_INSERT
- if ( m_bCollected )
- {
- return -1;
- }
- #endif
- if( !m_bOpen )
- {
- LOG4C((LOG_NOTICE,"串口未打开"));
- return 0;
- }
- if(m_hCom == INVALID_HANDLE_VALUE )
- {
- LOG4C((LOG_NOTICE,"串口句柄无效"));
- return 0;
- }
- vector <STSendCommand>::const_iterator it_SendCommand;
- for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end(); it_SendCommand++ )
- {
- STSendCommand ST_SendCommand = *it_SendCommand;
- #if 0
- // 应用命令特征码来作比较 ;
- if ( strcmp( (char*)szCommand,(char*)(ST_SendCommand.bySend)) == 0 ) // 这里的比较 有问题,'0'隔开了两部分,前相等,后不相等.
- {
- LOG4C((LOG_NOTICE,"命令已存在!"));
- return -1;
- }
- #else
- if ( memcmp((char*)szCommand,(char*)(ST_SendCommand.bySend),iLen) == 0)
- {
- LOG4C((LOG_NOTICE,"命令已存在!"));
- return -1;
- }
- #endif
- }
- // before it ,check the command wasn't exist;
- STSendCommand ST_SendCommand ={0};
- //ST_SendCommand.iSNum = iSNum;
- ST_SendCommand.bRecv = bRecv;
- ST_SendCommand.iSLen = iLen;
- ST_SendCommand.dwSID = g_dwCID++;
- ST_SendCommand.iAddr = iAddr;
- //memset( ST_SendCommand.szMark, 0, MAX_MARKSIZE );
- memcpy( ST_SendCommand.szMark, szMark, strlen(szMark) );
- //memset( ST_SendCommand.bySend, 0, MAX_SENDSIZE );
- memcpy( ST_SendCommand.bySend, szCommand, iLen );
- memcpy(ST_SendCommand.szCheck,szCheck,strlen(szCheck));
- #if !USE_INSERT_AUTORAISE
- if ( m_sendlist.size() == m_sendlist.capacity() )
- {
- LOG4C((LOG_NOTICE,"插入的容器容量小 = %d,扩大10",m_sendlist.capacity()));
- m_sendlist.resize(m_sendlist.capacity() + 10);
- }
- #endif
- if ( m_bCollected )
- {
- LOG4C((LOG_NOTICE,"线程在运行当中,添加命令"));
- if ( m_hCollectCtrl != NULL)
- {
- gb_send = TRUE;
- Sleep(50); // 等待SendMessage完成最后一次操作;
- SetEvent(m_hCollectCtrl);
- while ( WaitForSingleObject( m_hCollectCtrl,INFINITE) == WAIT_OBJECT_0 )
- {
- ResetEvent( m_hCollectCtrl );
- ::SuspendThread( m_hThreaObj );
- Sleep(100);
-
- m_sendlist.push_back( ST_SendCommand );
- LOG4C((LOG_NOTICE,"线程在运行当中,添加命令结束"));
- ::ResumeThread( m_hThreaObj );
- SetEvent( m_hCollectCtrl );
- break;
- }
- gb_send = FALSE;
- }
- }
- else
- m_sendlist.push_back( ST_SendCommand );
- return 0;
- }
- /************************************************************************/
- /*
- 函数:删除指定的命令,同时删除数据池中对应的元素;
- 参数:
- szCommand: 具体的命令;
- 注意:
- 1.对命令的删除,会影响到采集线程的安全性与稳定性,建议在删除前,先停止线程
- */
- /************************************************************************/
- int CSerialProcess::RemoveCommand(const BYTE *szCommand)
- {
- #if !USE_THREADRUN_INSERT
- if ( m_bCollected )
- {
- return -1;
- }
- #endif
- vector <STSendCommand>::iterator it_SendCommand;
- for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end(); it_SendCommand++ )
- {
- STSendCommand ST_SendCommand = *it_SendCommand;
- if ( strcmp( (char*)szCommand,(char*)(ST_SendCommand.bySend)) == 0 )
- {
- m_sendlist.erase(it_SendCommand); // 必须得先删除发送的命令,才可以删除数据池的元素;
- vector <STRecvMessage>::iterator it_RecvMessage;
- for ( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); it_RecvMessage++)
- {
- STRecvMessage ST_RecvMessage = *it_RecvMessage;
- if ( ST_RecvMessage.dwSID = ST_SendCommand.dwSID)
- {
- g_vtRecv.erase(it_RecvMessage);
- break;
- }
- }
- break;;
- }
- }
- return 0;
- }
- /************************************************************************/
- /*
- 函数:删除该地址下所有设备命令,并且也删除对应数据池的元素;
- 参数:
- addr: 指定的设备地址;
- 注意:
- 1.对命令的删除,会影响到采集线程的安全性与稳定性,建议在删除前,先停止线程
- */
- /************************************************************************/
- void CSerialProcess::RemoveDeivce(const int &addr)
- {
- #if !USE_THREADRUN_INSERT
- if ( m_bCollected )
- {
- return;
- }
- #endif
- if( !m_bOpen )
- {
- LOG4C((LOG_NOTICE,"串口未打开"));
- return ;
- }
- if(m_hCom == INVALID_HANDLE_VALUE )
- {
- LOG4C((LOG_NOTICE,"串口句柄无效"));
- return ;
- }
- gb_send = TRUE;
- Sleep(50); // 等待SendMessage完成最后一次操作;
- if ( m_hCollectCtrl != NULL)
- {
- SetEvent(m_hCollectCtrl);
- while ( WaitForSingleObject( m_hCollectCtrl,INFINITE) == WAIT_OBJECT_0 )
- {
- ResetEvent( m_hCollectCtrl );
- ::SuspendThread( m_hThreaObj );
- Sleep(100);
- vector <STSendCommand>::iterator it_SendCommand;
- for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end(); )
- {
- STSendCommand ST_SendCommand = *it_SendCommand;
- if ( ST_SendCommand.iAddr == addr)
- {
- vector <STRecvMessage>::iterator it_RecvMessage;
- for ( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); it_RecvMessage++)
- {
- STRecvMessage ST_RecvMessage = *it_RecvMessage;
- if ( ST_RecvMessage.dwSID = ST_SendCommand.dwSID)
- {
- g_vtRecv.erase(it_RecvMessage);
- break;
- }
- }
- it_SendCommand = m_sendlist.erase(it_SendCommand);
- LOG4C((LOG_NOTICE,"串口%d 删除地址%d命令成功",m_iPort,addr));
- }
- else
- it_SendCommand++;
- }
- // 设置完毕,恢复线程;
- ::ResumeThread( m_hThreaObj );
- SetEvent( m_hCollectCtrl );
- break;
- }
- }
- gb_send = FALSE;
- LOG4C((LOG_NOTICE,"删除设备完成"));
- }
- /************************************************************************/
- /*
- 函数:返回容器的大小;
- */
- /************************************************************************/
- int CSerialProcess::GetCommandsCount()
- {
- return m_sendlist.size();
- }
- /************************************************************************/
- /*
- 函数:删除所有发送命令;
- 注意:
- 1.erase的返回值是迭代器指向的下一元素,for循环不需要迭代器++自增;
- 2.对命令的删除,会影响到采集线程的安全性与稳定性;
- */
- /************************************************************************/
- void CSerialProcess::RemoveAllSendCommand()
- {
- vector<STSendCommand>::iterator it_SendCommand;
- for ( it_SendCommand = m_sendlist.begin(); it_SendCommand != m_sendlist.end();)
- it_SendCommand = m_sendlist.erase(it_SendCommand);
- }
- /************************************************************************/
- /*
- 函数:删除该串口在数据池中的元素;
- 注意:
- 1.erase的返回值是迭代器指向的下一元素;
- 如果条件真,删除的元素将erase的返回值指向迭代器本身,否则自增++;
- 2.对数据池的操作,会影响到采集线程的安全性与稳定性;
- */
- /************************************************************************/
- void CSerialProcess::RemoveAllRecvCommand()
- {
- vector<STRecvMessage>::iterator it_RecvMessage;
- STRecvMessage ST_RecvMessage;
- for ( it_RecvMessage = g_vtRecv.begin(); it_RecvMessage != g_vtRecv.end(); )
- {
- ST_RecvMessage = *it_RecvMessage;
- if ( m_iPort == ST_RecvMessage.iPort )
- {
- EnterCriticalSection( &g_cs_vt );
- it_RecvMessage = g_vtRecv.erase(it_RecvMessage);
- LeaveCriticalSection( &g_cs_vt );
- }
- else
- it_RecvMessage++ ;
- }
- }
|