#include "vision.h" #include "manage.h" #include "log.h" #include "ops.h" //结束符 static const char* _endstr = ";"; static const int _endlen = (int)strlen(_endstr); CVision::CVision() { _len = 0; _ires = 0; _port = VPORT; _skt = INVALID_SKT; _size = MAX_BUF_LEN; _msg = new char[_size]; memset(_msg, 0, _size); _status = SOCKET_DISCONNECTED; _hReply = sys_CreateEvent(TRUE, FALSE, NULL); _hSection = sys_InitializeCriticalSection(); } CVision::~CVision(void) { Deinit(); delete _msg; sys_CloseHandle(_hReply); sys_DeleteCriticalSection(_hSection); } int CVision::Init(const char* pszip, ushort port) {//任务开始 sys_EnterCriticalSection(_hSection); if (INVALID_SKT == _skt) { _port = port; Disconnect(); REPORT("%d 等待连接", _port); _skt = skt_client(pszip, port); } sys_LeaveCriticalSection(_hSection); return 0; } int CVision::Deinit() {//关闭任务 sys_EnterCriticalSection(_hSection); if (INVALID_SKT != _skt) { Disconnect(); skt_close(_skt); _skt = INVALID_SKT; REPORT("%d 关闭连接", _port); } ClearMsg(); sys_LeaveCriticalSection(_hSection); return 0; } void CVision::Connect() {//等待连接 sys_EnterCriticalSection(_hSection); if (INVALID_SKT != _skt && SOCKET_CONNECTED != _status && SOCKET_CONNECTED == skt_status(_skt)) { _status = SOCKET_CONNECTED; _socket = skt_get_socket(_skt); REPORT("%d 已连接", _port); } sys_LeaveCriticalSection(_hSection); } void CVision::Disconnect() {//断开处理 ZERO_CHK(SOCKET_CONNECTED == _status); _len = 0; _index = 0; _socket = 0; sys_SetEvent(_hReply); _ires = ERR_NO_CONNECT; _status = SOCKET_DISCONNECTED; } int CVision::Process() {//拍照处理,等待拍照结果返回 0标识成功 内部阻塞 TOpsCfg cfg; ops_get_cfg(&cfg); RETURN_CHK_NOPRT(!cfg.offVision, 0); sys_EnterCriticalSection(_hSection); _ires = ERR_NO_CONNECT; if (IsConn()) { _index = 0; ClearMsg(); sys_ResetEvent(_hReply); SendMsg("M"); } sys_LeaveCriticalSection(_hSection); sys_WaitForSingleObject(_hReply, 5000); return _ires; } int CVision::WaitResult(char* s, int timeout) {//接收处理结果 一旦接收成功,_res将清空 TOpsCfg cfg; char* pmsg = NULL; int ret = ERR_NO_CONNECT; uint ct = sys_GetTickCount(); RETURN_CHK_NOPRT(s, ERR_INPUT_PARAM); ops_get_cfg(&cfg); if (cfg.offVision) {//禁用 sprintf(s, "0"); return 0; } while (ret && IsConn()) { if (sys_GetTickCount() > ct + timeout) {//超时 return ERR_TIMEOUT; } sys_WaitForSingleObject(_hReply, 50); sys_EnterCriticalSection(_hSection); if (IsConn() && !_lstmsg.empty()) { ret = 0; pmsg = _lstmsg.front(); _lstmsg.pop_front(); strcpy(s, pmsg); delete pmsg; } if (_lstmsg.empty()) sys_ResetEvent(_hReply); sys_LeaveCriticalSection(_hSection); } return ret; } void CVision::RecvMsg(char* s, int nsize) {//接收消息 -- 由线程执行 sys_EnterCriticalSection(_hSection); RecvMsgB(s, nsize); sys_LeaveCriticalSection(_hSection); } int CVision::Send(const char* s) {//发送消息 int ret = 0; RETURN_CHK_NOPRT(s && *s, ERR_INPUT_PARAM); RETURN_CHK_NOPRT(IsConn(), ERR_NO_CONNECT); sys_EnterCriticalSection(_hSection); ret = SendMsg(s); sys_LeaveCriticalSection(_hSection); return ret; } int CVision::SendMsg(const char *pszFormat, ...) { int len = 0; int ret = 0; va_list args; char buff[MAX_BUF_LEN] = {0}; va_start(args, pszFormat); len = vsnprintf(buff, MAX_BUF_LEN-1, pszFormat, args); va_end(args); RETURN_CHK_NOPRT(len > 0, ERR_INPUT_PARAM); len += sprintf(buff + len, "%s", _endstr); //增加结束符 ret = skt_send(_skt, buff, len); if (ERR_NO_CONNECT == ret) {//已经断开 Disconnect(); REPORT("%d 已断开连接", _port); return ret; } if (ins->visionLog()) LOG_INF1("%d send: %s", _port, buff); return 0; } int CVision::FindEnd(char* pszmsg) { char* ptmp = NULL; ptmp = strstr(pszmsg, _endstr); if (!ptmp) return -1; *ptmp = 0; return (int)(ptmp - pszmsg); } void CVision::ClearMsg() { while (!_lstmsg.empty()) { FREE_ANY(_lstmsg.front()); _lstmsg.pop_front(); } } void CVision::RecvMsgB(char* s, int nsize) {//接收消息 int len = 0; char* pdest = NULL; ZERO_CHK(SOCKET_CONNECTED == _status); //len = skt_recv(_skt, _msg + _len, _size - 1 - _len, 0); len = sys_Recv(_socket, _msg + _len, _size - 1 - _len); if (ERR_NO_CONNECT == len) {//已经断开 Disconnect(); REPORT("%d 已断开连接", _port); return; } ZERO_CHK(len > 0); //error if (ins->visionLog()) LOG_INF1("%d recv: %s", _port, _msg + _len); _len += len; //消息长度 if (_size - 1 == _len) {//缓冲区不够了 +大 _size += MAX_BUF_LEN; pdest = new char[_size]; memset(pdest, 0, _size); memcpy(pdest, _msg, _len); delete _msg; _msg = pdest; } pdest = _msg; while(_len > 0) { len = FindEnd(pdest); //查找结束符 if (len < 0) break; //未找到结束符 //新消息 if (!s) ParseMsg(pdest); else {//需要拷贝到外部 if (nsize < len + 2) {//buffer 不够 REPORT("%d 接收视觉缓冲区不够,消息不完全接收", _port); } else {//copy nsize -= len + 1; s = comm_strcpy(s, pdest); s = comm_strcpy(s, ";"); } } len += _endlen; //加上结束符长度 _len -= len; pdest += len; } if (_len > 0 && pdest != _msg) {//不等,标识前面已经解析过消息,后面剩余消息需要前移 mem_forward(pdest, _len + 1, (uint)(pdest - _msg)); } } int CVision::ParseMsg(char* pszmsg) { int nlen = 0; char* ptmp = NULL; RETURN_CHK_NOPRT(pszmsg, ERR_INPUT_PARAM); if (ins->visionLog()) LOG_INF1("%d parse msg: %s", _port, pszmsg); ptmp = sys_strtok(NULL, ",", &pszmsg); RETURN_CHK_NOPRT(ptmp && *ptmp, ERR_INPUT_PARAM); if (strcmp(ptmp, "M")) {//不是拍照返回消息 REPORT("%d 接收到异常指令: %s", _port, ptmp); return ERR_INPUT_PARAM; } RETURN_CHK_NOPRT(pszmsg && *pszmsg, 0); if (0 == _index) {//首次返回拍照结果 RETURN_CHK_NOPRT(EMSTR_INT == get_str_type(pszmsg), ERR_INPUT_PARAM); _ires = atoi(pszmsg); //结果 sys_SetEvent(_hReply); _index++; return 0; } //二次返回、多次返回 ptmp = new char[strlen(pszmsg) + 1]; comm_strcpy(ptmp, pszmsg); _lstmsg.push_back(ptmp); sys_SetEvent(_hReply); return 0; }