#include "log.h" #include "var.h" #include "test.h" #include "manage.h" #include "config.h" #include "control.h" //结束符 static const char* _endstr = "$"; static const int _endlen = (int)strlen(_endstr); CTest::CTest() { _p = NULL; _pvar = NULL; _result = 0; _csvInfo = ""; _failItems = ""; _testItems = ""; _skt = INVALID_SKT; _size = MAX_BUF_LEN; _msg = new char[_size]; memset(_msg, 0, _size); //_prvstatus = TestNoConn; _status = SOCKET_DISCONNECTED; memset(_client, 0, MAX_NAME_LEN); memset(&_data, 0, sizeof(_data)); memset(_daypath, 0, MAX_NAME_LEN); _hSend = sys_CreateEvent(FALSE, TRUE, NULL); _hReply = sys_CreateEvent(TRUE, TRUE, NULL); _hSection = sys_InitializeCriticalSection(); ClearFlag(); _data.benable = 1; //默认启用 _data.yield = 1; _data.pass = 0; _data.lastct = TESTCT; } CTest::~CTest() { Close(); delete _msg; sys_CloseHandle(_hSend); sys_CloseHandle(_hReply); sys_DeleteCriticalSection(_hSection); } void CTest::ClearFlag() { _len = 0; _index = 0; _regtm = 0; _socket = 0; _qstart = 0; _qstatus = 0; _startct = 0; _cmdres = 0; _notest = false; //_pass = 0; //_data.total = 0; //_data.yield = 1; unlock(); setReply(); } void CTest::loadCounter() { char buff[64] = { 0 }; sprintf(buff, "test_%s", _data.ate); _data.pass = get_cfg_int(buff, "pass"); _data.total = get_cfg_int(buff, "total"); _data.yield = _data.total > 0 ? ((float)_data.pass / _data.total) : 1; } void CTest::saveCounter() { char buff[64] = { 0 }; sprintf(buff, "test_%s", _data.ate); modify_cfg_int(buff, "pass", _data.pass); modify_cfg_int(buff, "total", _data.total); } void CTest::resetCounter() { _data.pass = 0; _data.total = 0; _data.yield = 1; saveCounter(); } void CTest::operator =(CTest &r) { if (INVALID_SKT != _skt) skt_close(_skt); _len = 0; _skt = r._skt; _index = r._index; _status = r._status; _socket = r._socket; _qstatus = r._qstatus; _startct = r._startct; memset(_msg, 0, _size); _csvTitle = r._csvTitle; strcpy(_client, r._client); _data.pass = r._data.pass; _data.total = r._data.total; _data.yield = r._data.yield; //strcpy(_data.sn, r._data.sn); _data.status = r._data.status; strcpy(_data.ate, r._data.ate); r.ClearFlag(); r._skt = INVALID_SKT; //把连接赋值到新对象 r._status = SOCKET_DISCONNECTED; r._data.status = TestNoConn; r._csvTitle = ""; //memset(r._data.sn, 0, MAX_NAME_LEN); memset(r._data.ate, 0, MAX_NAME_LEN); //清空机器编码 } void CTest::Open(const char* pszip) { static bool bhintOk = false; static bool bhintFail = false; ClearFlag(); _status = SOCKET_DISCONNECTED; _skt = skt_server(pszip, 6050); if (!bhintFail && INVALID_SKT == _skt) {//提示失败 bhintOk = false; bhintFail = true; REPORT("治具服务端创建失败,请检查端口是否被占用"); } else if (!bhintOk && INVALID_SKT != _skt) {//提示ok bhintOk = true; bhintFail = false; REPORT("治具服务端创建成功,等待连接..."); } } void CTest::Close() { ZERO_CHK(IsOpen()); skt_close(_skt); _skt = INVALID_SKT; UpdateStatus(TestNoConn); _status = SOCKET_DISCONNECTED; ClearFlag(); } int CTest::SetVarStatus(const char* szvar) { ipvar* p = get_ipvars(szvar); RETURN_CHK_NOPRT(p != _pvar, ERR_INPUT_PARAM); _pvar = p; if (p) p->seti(getStatus()); return 0; } cstr GetTestMode(cstr p) {//根据用户获取测试模式 if (0 == *p) return "Production"; if (!stricmp(p, "PM")) return "Audit"; if (!stricmp(p, "ADMIN")) return "Audit"; if (!stricmp(p, "ENG_MI")) return "Audit"; if (!stricmp(p, "ENGINEER")) return "Audit"; if (!stricmp(p, "ENG_VENDOR")) return "Audit"; if (!stricmp(p, "OP")) return "Production"; if (!stricmp(p, "DualTest")) return "Production"; if (!stricmp(p, "OPERATOR")) return "Production"; return p; } void CTest::PutProduct(CProduct* p) {//将产品数据移入治具 _p = p; //赋值 p->data.index = _index; p->data.pos = LocationTest; } //StartTest#SN#Machine#User#Config#Lot#Mode#SiteID#ProjectID#RetryMode#Mes#Mtcp$ int CTest::StartTest(CProduct* p, const char* machine, const char* pszcfg, const char* pszcfg2, const char* site, const char* project, int bmes, int bmtcp, int bdualmode,const char* sublotname,int bupnoise) {//通知治具开始测试,需要组包通信 if (_notest) {//仅作为缓存用 -- 仅一次有效 PutProduct(p); _notest = false; return 0; } RETURN_CHK_NOPRT(lock(), ERR_NOREADY); RETURN_CHK_NOPRT(IsReady(), ERR_NOREADY); resetReply(); _cmdres = ERR_TIMEOUT; _qstart = sys_GetTickCount(); cstr pszuser = get_cur_user(); if (!pszuser) pszuser = "OP"; if (!strcmp("DualTest", pszuser)) bdualmode = 1; //双模式 char rowcol[32] = {0}; CalcRowColumn(p->data.takeIndex, rowcol); SendMsg("%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%d#%d#%s#%d#%s#%s#%d", START, p->data.sn, machine, pszuser, pszcfg, p->data.lot, GetTestMode(pszuser), site, project, p->getRetryModelS(), bmes, bmtcp, pszcfg2, bdualmode, rowcol, sublotname, bupnoise); if (!waitReply()) {//指令未回复 unlock(); //释放 REPORT("%s 启动测试指令返回超时.", _data.ate); return ERR_TIMEOUT; } unlock(); //释放 if (!IsRunning()) {//指令未回复,或者未启动测试 REPORT("%s 启动测试失败.", _data.ate); return ERR_NOREADY; } ulong ct = sys_GetTickCount() - _qstart; if (ct > 0) REPORT("test start command reply: %dms", ct); PutProduct(p); //赋值 p->data.count++; //测试次数+1 p->SetIndex(_index); p->data.failItems[0] = 0; //清空 strcpy(p->Ate(), _data.ate); _startct = sys_GetTickCount(); char buff[MAX_NAME_LEN] = { 0 }; //sprintf(buff, "Fixture%d Start Test", _index); //ins->EventTracker(pszuser, 0, "", buff); sprintf(buff, "Fixture%d ", _index); ins->BreakdownLog(buff, "Test Start"); return 0; } int CTest::Home() { RETURN_CHK_NOPRT(IsReady(), ERR_NOREADY); RETURN_CHK_NOPRT(lock(), ERR_NOREADY); RETURN_CHK_NOPRT(IsReady(), ERR_NOREADY); resetReply(); _cmdres = ERR_TIMEOUT; _qstart = sys_GetTickCount(); SendMsg("%s", HOME); if (!waitReply()) {//指令未回复 unlock(); //释放 REPORT("%s %s 指令返回超时.", _data.ate, HOME); return ERR_TIMEOUT; } unlock(); //释放 return _cmdres; } int CTest::Reset() { RETURN_CHK_NOPRT(IsNormal(), ERR_NOREADY); RETURN_CHK_NOPRT(lock(), ERR_NOREADY); RETURN_CHK_NOPRT(IsNormal(), ERR_NOREADY); resetReply(); _cmdres = ERR_TIMEOUT; _qstart = sys_GetTickCount(); SendMsg("%s", RESET); if (!waitReply()) {//指令未回复 unlock(); //释放 REPORT("%s %s 指令返回超时.", _data.ate, RESET); return ERR_TIMEOUT; } unlock(); //释放 return _cmdres; } int CTest::Pause(int bpause/* = 1*/) {//通知治具暂停 RETURN_CHK_NOPRT(IsNormal(), ERR_NOREADY); RETURN_CHK_NOPRT(lock(), ERR_NOREADY); RETURN_CHK_NOPRT(IsNormal(), ERR_NOREADY); resetReply(); _cmdres = ERR_TIMEOUT; _qstart = sys_GetTickCount(); SendMsg("%s#%d", PAUSE, bpause); if (!waitReply()) {//指令未回复 unlock(); //释放 REPORT("%s %s 指令返回超时.", _data.ate, PAUSE); return ERR_TIMEOUT; } unlock(); //释放 return _cmdres; } int CTest::EnableGrip(int benable/* = 1*/) {//控制夹爪打开或关闭 1夹紧 0松开 RETURN_CHK_NOPRT(IsReady(), ERR_NOREADY); RETURN_CHK_NOPRT(lock(), ERR_NOREADY); RETURN_CHK_NOPRT(IsReady(), ERR_NOREADY); resetReply(); _cmdres = ERR_TIMEOUT; _qstart = sys_GetTickCount(); SendMsg("%s#%d", GRIP, benable); if (!waitReply()) {//指令未回复 unlock(); //释放 REPORT("%s 控制夹爪指令返回超时.", _data.ate); return ERR_TIMEOUT; } unlock(); //释放 return _cmdres; } int CTest::SendGR(const char* s) {//发送GR消息给治具 int ret = 0; RETURN_CHK_NOPRT(s && *s, ERR_INPUT_PARAM); RETURN_CHK_NOPRT(IsNormal(), ERR_NOREADY); RETURN_CHK_NOPRT(lock(), ERR_NOREADY); RETURN_CHK_NOPRT(IsNormal(), ERR_NOREADY); _cmdres = ERR_TIMEOUT; _qstart = sys_GetTickCount(); ret = SendMsg("%s#%s", GR, s); unlock(); //释放 return ret; } int CTest::GetResultCsvInfo(char* pbuffer/* = 0*/, int nsize/* = 0*/) { int nlen = (int)_csvInfo.length(); RETURN_CHK_NOPRT(pbuffer, nlen); if (nsize < nlen) nlen = nsize; comm_strncpy(pbuffer, _csvInfo.c_str(), nlen); return nlen; } int CTest::GetResultFailInfo(char* pbuffer/* = 0*/, int nsize/* = 0*/) { int nlen = (int)_failItems.length(); RETURN_CHK_NOPRT(pbuffer, nlen); if (nsize < nlen) nlen = nsize; comm_strncpy(pbuffer, _failItems.c_str(), nlen); return nlen; } int CTest::GetResultTestInfo(char* pbuffer/* = 0*/, int nsize/* = 0*/) { int nlen = (int)_testItems.length(); RETURN_CHK_NOPRT(pbuffer, nlen); if (nsize < nlen) nlen = nsize; comm_strncpy(pbuffer, _testItems.c_str(), nlen); return nlen; } static const char* _pszst[] = {"断开连接", "测试中", "就绪", "报警", "回原中" }; void CTest::UpdateStatus(TestStatus status) {//更新治具状态 ZERO_CHK(status != _data.status); REPORT("%s:%s", _data.ate, _pszst[status]); _data.status = status; //最后更新状态 if (_pvar) _pvar->seti(status); } void CTest::Connect() {//等待连接 ushort port = 0; char ip[MAX_IP_LEN] = {0}; ZERO_CHK(IsOpen()); ZERO_CHK(SOCKET_CONNECTED != _status); ZERO_CHK(SOCKET_CONNECTED == skt_status(_skt)); ClearFlag(); _status = SOCKET_CONNECTED; _regtm = sys_GetTickCount(); skt_get_addr(_skt, ip, &port); _socket = skt_get_socket(_skt); sprintf(_client, "%s:%d", ip, port); REPORT("%s 已连接,等待注册.", _client); } void CTest::Process() {//其它处理 -- 由线程执行 //sys_EnterCriticalSection(_hSection); ChkRegist(); QueryStatus(); ChkReplyTimeout(); //sys_LeaveCriticalSection(_hSection); } void CTest::ChkRegist() {//检测注册超时 ZERO_CHK(IsConn() && !IsRegOk()); if (sys_GetTickCount() - _regtm > 2000) {//超时了,超过2s未注册 Close(); REPORT("%s 超过2s未注册,断开连接.", _client); } } void CTest::QueryStatus() {//查询治具状态 uint ct = 0; ZERO_CHK(IsNormal() && IsReplyed()); ct = sys_GetTickCount(); if (ct - _qstatus > 500 && trylock()) {//已经回复ok -- 500ms查询一次 resetReply(); SendMsg(STATUS); _qstatus = _qstart = ct; } } void CTest::ChkReplyTimeout() {//检测回复超时 ulong ct = 0; ZERO_CHK(IsNormal() && !IsReplyed()); ct = sys_GetTickCount(); if (ct > _qstart + 2000) {//未回复,并且超过2s //Close(); _qstart = ct; REPORT("%s 超过2s未回复.", _data.ate); } } int CTest::SendMsg(const char *pszFormat, ...) { int len = 0; int ret = 0; va_list args; char buff[1024] = {0}; va_start(args, pszFormat); len = vsnprintf(buff, 1023, 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) {//已经断开 Close(); REPORT("%s 已断开连接", _data.ate); return ret; } if (ins->get_callback()) { ins->get_callback()(11, buff); } if (ins->testLog()) LOG_INF1("send->%s: %s", _data.ate, buff); return 0; } int CTest::FindEnd(char* pszmsg) { char* ptmp = NULL; ptmp = strstr(pszmsg, _endstr); if (!ptmp) return -1; *ptmp = 0; return (int)(ptmp - pszmsg); } void CTest::RecvMsg() {//接收消息 int len = 0; char* pdest = NULL; //ZERO_CHK(IsConn()); //len = skt_recv(_skt, _msg + _len, _size - 1 - _len, 0); len = sys_Recv(_socket, _msg + _len, _size - 1 - _len); if (ERR_NO_CONNECT == len) {//已经断开 Close(); REPORT("%s 已断开连接", _client); return; } ZERO_CHK(len > 0); //error pdest = _msg + _len; _len += len; //消息长度 pdest[len] = 0; if (ins->testLog()) LOG_INF1("%s[%s] recv: %s", _client, _data.ate, pdest); 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) {//未找到结束符 if (pdest != _msg) {//不等,标识前面已经解析过消息,后面剩余消息需要前移 mem_forward(pdest, _len + 1, (uint)(pdest - _msg)); } return; } //新消息 ParseMsg(pdest); len += _endlen; //加上结束符长度 _len -= len; pdest += len; } } void CTest::ParseMsg(char* pszmsg) { char* ptmp = NULL; ZERO_CHK(pszmsg); //LOG_INF1("%s[%s] parse msg: %s", _client, _data.ate, pszmsg); ptmp = sys_strtok(NULL, SPLIT, &pszmsg); ZERO_CHK(ptmp && *ptmp); if (!strcmp(ptmp, REG)) {//注册消息 return ParseRegister(pszmsg); } if (!strcmp(ptmp, STATUS)) {//治具状态回复 return ParseStatusReply(pszmsg); } if (!strcmp(ptmp, START)) {//启动测试回复 return ParseStartReply(pszmsg); } if (!strcmp(ptmp, RIO)) {//读取IO return ParseRIO(pszmsg); } if (!strcmp(ptmp, WIO)) {//写入IO return ParseWIO(pszmsg); } if (!strcmp(ptmp, VLOG)) {//上传日志 return ParseWriteLog(pszmsg); } if (!strcmp(ptmp, RES)) {//询问结果回复 ParseResultReply(pszmsg); setReply(); //重置信号 unlock(); UpdateStatus(TestIdle); return; } if (!strcmp(ptmp, ERR)) {//错误代码回复 return ParseErrorReply(pszmsg); } if (!strcmp(ptmp, HOME)) {//回原指令回复 return ParseIntReply(pszmsg); } if (!strcmp(ptmp, RESET)) {//重置指令回复 return ParseIntReply(pszmsg); } if (!strcmp(ptmp, GRIP)) {//控制夹爪回复 return ParseIntReply(pszmsg); } if (!strcmp(ptmp, PAUSE)) {//暂停回复 return ParseIntReply(pszmsg); } if (!strcmp(ptmp, GR)) {//侧相机视觉处理请求 return ParseGR(pszmsg); } REPORT("%s 异常指令: %s", _client, ptmp); } void CTest::ParseRegister(char* pszcmd) {//解析注册消息 int index = 0; char* ptmp = NULL; char ate[MAX_NAME_LEN] = {0}; if (0 == _regtm) { SendMsg("%s#0", REG); REPORT("%s 重复注册或不在限制时间内注册.", _client); return; } ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if ((0 == ptmp || 0 == *ptmp || strlen(ptmp) >= MAX_NAME_LEN)) {//格式不对 SendMsg("%s#0", REG); LOG_WARN("%s 注册格式错误.", _client); return; } strcpy(ate, ptmp); //ate ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (EMSTR_INT != get_str_type(ptmp)) {//格式不对 SendMsg("%s#0", REG); LOG_WARN("%s 注册格式错误.", _client); return; } index = atoi(ptmp); if (index <= 0 || index > TESTCNT) {//序号不对 SendMsg("%s#0", REG); LOG_WARN("%s 注册机台序号错误:%d", _client, index); return; } if (!ins->ChkAteValid(index, ate)) {//编码重复了 SendMsg("%s#0", REG); LOG_WARN("%s 治具编码重复:%s", _client, ate); return; } //判断是否带有标题 _csvTitle = pszcmd ? pszcmd : ""; _csvTitle += "\n"; //增加换行符 _regtm = 0; //重置标识 _index = index; //序号 strcpy(_data.ate, ate); //ate loadCounter(); //加载计数 SendMsg("%s#1", REG); UpdateStatus(TestWarn); } void CTest::ParseStatusReply(char* pszcmd) {//治具状态回复 int status = 0; if (EMSTR_INT != get_str_type(pszcmd)) {//格式不对 setReply(); unlock(); LOG_WARN("%s 状态返回错误 :%s.", _data.ate, pszcmd); return; } status = atoi(pszcmd); if (status != 0 && status != 1) {//必须是1和0 LOG_WARN("%s 状态返回错误 :%s.", _data.ate, pszcmd); } if (0 == status) {//测试中 SendMsg(ERR); _qstart = sys_GetTickCount(); } else if (_p && IsRunning()) {//有产品且测试中->就绪 SendMsg(RES); _qstart = sys_GetTickCount(); _data.lastct = (int)(_qstart - _startct); } else {//状态就绪 setReply(); unlock(); UpdateStatus(TestIdle); } } void CTest::ParseErrorReply(char* pszcmd) {//错误代码回复 int err = 0; char* ptmp = NULL; ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (EMSTR_INT != get_str_type(ptmp)) {//格式不对 setReply(); unlock(); LOG_WARN("%s 查询错误返回格式错误 :%s.", _data.ate, pszcmd); return; } err = atoi(ptmp); if (0 == err) {//无错误 //if (TestWarn == getStatus()) UpdateStatus(TestIdle); } else if (TestWarn != getStatus()) {//有错误 UpdateStatus(TestWarn); REPORT("%s 报警 %d:%s", _data.ate, err, pszcmd ? pszcmd : ""); ins->PostWarn("%s 报警 %d:%s", _data.ate, err, pszcmd ? pszcmd : ""); } setReply(); //设置信号 unlock(); } void CTest::ParseWriteLog(char* pszcmd) { char* ptmp = NULL; ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (0 == ptmp || 0 == pszcmd) {//格式不对 SendMsg("%s#0", VLOG); LOG_WARN("%s 上传日志格式错误.", _data.ate); return; } if (0 == *ptmp || 0 == *pszcmd || strlen(ptmp) > 256 || strlen(pszcmd) > 256) {//长度受限 SendMsg("%s#0", VLOG); LOG_WARN("%s 上传日志内容长度超限.", _data.ate); return; } ins->BreakdownLog(ptmp, pszcmd); SendMsg("%s#1", VLOG); } void CTest::ParseGR(char* pszcmd) { int ret = ins->SendTestGR(_index, pszcmd); if (ret) {//fail. SendMsg("%s#%d", GR, ret); LOG_WARN("%s 发送给视觉失败.", _data.ate); } } void DelEnter(char * source) { char * temp = source; if (source == NULL) { return; } while (*source) { if (*source != '\r' && *source != '\n') { *temp = *source; temp++; } source++; } *temp = '\0'; } void CTest::ParseResult(char* pszcmd) { DelEnter(pszcmd); char* ptmp = NULL; _csvInfo = ""; _failItems = ""; _testItems = ""; ZERO_CHK(pszcmd); ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (ptmp) _csvInfo = ptmp; //csvinfo ptmp = NULL; _csvInfo += ","; if (pszcmd) ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (ptmp) {//failitems _failItems = ptmp; _csvInfo += ptmp; } ptmp = NULL; _csvInfo += ","; if (pszcmd) ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (ptmp) {//testitems _testItems = ptmp; _csvInfo += ptmp; } _csvInfo += "\n"; ptmp = NULL; if (pszcmd) ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (_p) {//bin if (ptmp) comm_strncpy(_p->data.level, ptmp, MAX_NAME_LEN); //bin comm_strncpy(_p->data.failItems, _failItems.c_str(), MAX_BUF_LEN); } } void CTest::ParseResultReply(char* pszcmd) {//询问结果回复 int ret = 0; char* ptmp = NULL; char buff[MAX_NAME_LEN] = { 0 }; ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (EMSTR_INT != get_str_type(ptmp)) {//格式不对 LOG_WARN("%s 查询结果返回格式错误 :%s.", _data.ate, ptmp ? ptmp : ""); return; } ret = atoi(ptmp); ZERO_CHK(ret == 1); ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (EMSTR_INT != get_str_type(ptmp)) {//格式不对 LOG_WARN("%s 查询结果返回错误,测试结果:%s", _data.ate, ptmp ? ptmp : ""); return; } _result = atoi(ptmp); if (_p) {//有产品 -- 计算良率 _p->data.status = _result; _data.total++; if (_result) _data.pass++; _data.yield = (float)_data.pass / _data.total; saveCounter(); } ParseResult(pszcmd); //解析后面的结果 //CalcYield(); ins->SummaryLog(_csvTitle.c_str(), _csvInfo.c_str()); ins->UnitTracker(_p->data.sn, _data.ate, _p->data.lot, _p->data.status, _p->getRetryModelE()); //cstr pszuser = get_cur_user(); //sprintf(buff, "Fixture%d Test OK", _index); //ins->EventTracker(pszuser ? pszuser : "OP", 0, "", buff); sprintf(buff, "Fixture %d", _index); ins->BreakdownLog(buff, " Test End"); } void CTest::ParseStartReply(char* pszcmd) {//启动测试回复 int ret = 0; if (EMSTR_INT != get_str_type(pszcmd)) {//格式不对 LOG_WARN("%s 启动测试返回错误 :%s.", _data.ate, pszcmd); } else {//格式对 ret = atoi(pszcmd); if (ret != 0 && ret != 1) {//必须是1和0 LOG_WARN("%s 启动测试返回错误 :%s.", _data.ate, pszcmd); } } if (1 == ret) {//OK _cmdres = 0; UpdateStatus(TestRunning); } setReply(); } void CTest::ParseIntReply(char* pszcmd) {//解析返回结果(整数) int ret = 0; if (EMSTR_INT != get_str_type(pszcmd)) {//格式不对 LOG_WARN("%s 指令返回错误 :%s.", _data.ate, pszcmd); } else {//格式对 ret = atoi(pszcmd); if (ret != 0 && ret != 1) {//必须是1和0 LOG_WARN("%s 指令返回错误 :%s.", _data.ate, pszcmd); } if (1 == ret) {//OK _cmdres = 0; } } setReply(); } void CTest::ParseRIO(char* pszcmd) {//ReadIO#name ZERO_CHK(pszcmd); if (EMSTR_STRING != get_str_type(pszcmd)) {//格式不对 LOG_WARN("%s IO名称格式错误 :%s.", _data.ate, pszcmd); SendMsg("%s#0", RIO); return; } SendMsg("%s#%d", RIO, read_by_name(pszcmd)); } void CTest::ParseWIO(char* pszcmd) {//WriteIO#name#val int ret = 0; cstr ptmp = 0; ZERO_CHK(pszcmd); ptmp = sys_strtok(NULL, SPLIT, &pszcmd); if (EMSTR_STRING != get_str_type(ptmp)) {//格式不对 LOG_WARN("%s IO名称格式错误 :%s.", _data.ate, pszcmd); SendMsg("%s#-1", WIO); return; } if (EMSTR_INT != get_str_type(pszcmd)) {//格式不对 LOG_WARN("%s IO写入值格式错误 :%s.", _data.ate, pszcmd); SendMsg("%s#-1", WIO); return; } ret = atoi(pszcmd); SendMsg("%s#%d", WIO, write_by_name(ptmp, ret)); LOG_INF1("%s[%s] write IO: %s = %d", _client, _data.ate, ptmp, ret); } /* 根据产品在料盘中的索引值计算出产品在料盘中的行列 */ void CTest::CalcRowColumn(int takeindex, char* rowcol) { int _row, _col; _row = _col = 0; if (takeindex % 16 == 0) { _row = takeindex / 16; _col = 16; } else { _row = (takeindex / 16) + 1; _col = takeindex % 16; } sprintf(rowcol,"R%dC%d", _row, _col); }