You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
6.9 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}