// CModbusTcpc17pis.cpp: implementation of the CModbusTcpc17pis class. // ////////////////////////////////////////////////////////////////////// //#ifdef WIN32 //#include "stdafx.h" //#endif #ifndef WIN32 #include #endif #include "ModbusTcpc17pis.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif #include "thirdparty/json.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CModbusTcpc17pis::CModbusTcpc17pis() { m_nStationNo = 10; m_nNo = 0; } CModbusTcpc17pis::~CModbusTcpc17pis() { } void CModbusTcpc17pis::Init(S_PROTOCOLCFG *pcfg) { PRawCtrl = pcfg->PRawCtrl; pRxBuf = pcfg->pRxBuf; pTxBuf = pcfg->pTxBuf; pCmdMem = pcfg->pCmdMem; pRtu = pcfg->pRtu; pLink = pcfg->pLink; pTable = pcfg->pTable; pZfDataCtrl = pcfg->pZfDataCtrl; // pHis = pcfg->pHis; pLink->SetCommStatus(CMST_TX_CNT); m_nLastSendTime = GetNowSecond(); m_nRcvTimeOuts = pLink->GetRxTimeouts(); if (m_nRcvTimeOuts <= 0) { m_nRcvTimeOuts = 20; } pRxBuf->Move(pRxBuf->GetReadableSize()); pTxBuf->Move(pTxBuf->GetReadableSize()); m_nLastSendTime = 0; } sint32 CModbusTcpc17pis::RxProc() { sint32 rtuno = pLink->GetRtuNo(); unsigned char rtuaddr = pRtu->GetRtuAddr(rtuno); uint8 buf[1024]; int datalen = 0; int buflen = pRxBuf->GetReadableSize(); int nowtime = GetNowSecond(); E_RAW_ComStat coms = pLink->GetCommStatus(); if (coms == CMST_RX_CNT && (nowtime - m_nLastSendTime) >= 2/* m_nRcvTimeOuts*/) { //超时不重发,直接跳到下一个终端 pRxBuf->Move(buflen); pLink->RegisterFrm(FRAME_RX_TIMEOUT); pLink->SetCommStatus(CMST_TX_CNT); PrintLog( LOG_VIOLATION, "%d号终端 rtuaddr:%d 数据超时\n", rtuno, rtuaddr); return -1; } if (buflen < 9) //无数据或数据不够不改变链路通讯状态,继续等待 return -1; if (buflen > 510) buflen = 510; datalen = pRxBuf->Read(buf, buflen, DEF_BUFF_NOMOVE); if (datalen < (buf[5] + 6)) //无数据或数据不够不改变链路通讯状态,继续等待 return -1; if (buf[7] == 0x04) { pLink->RegisterFrm(FRAME_RX_SUC); ProcMeasure(buf + 7, buf[5]);//站厅,上行,下行,出入口区域设备状态 // printf("站厅%x-%x,上行%x-%x,下行%x-%x,出入口%x-%x\n",buf[10],buf[9],buf[12],buf[11],buf[14],buf[13],buf[16],buf[15]); pRxBuf->Move(buf[5] + 6); CmdRet(1); //pRxBuf->Move(datalen); pLink->SetCommStatus(CMST_TX_CNT); return 1; } else if (buf[7] == 0x10) { pLink->RegisterFrm(FRAME_RX_SUC); PrintLog( LOG_INFORMATION, "%d号终端 rtuaddr:%d 接收到命令返回成功\n", rtuno, rtuaddr); CmdRet(1); pRxBuf->Move(datalen); pLink->SetCommStatus(CMST_TX_CNT); return 1; } else if ((buf[7] & 0x80) == 0x80) { pLink->RegisterFrm(FRAME_RX_SUC); PrintLog( LOG_INFORMATION, "%d号终端 rtuaddr:%d 接收到命令返回失败\n", rtuno, rtuaddr); CmdRet(0); pRxBuf->Move(datalen); pLink->SetCommStatus(CMST_TX_CNT); return 1; } else { pLink->RegisterFrm(FRAME_RX_SUC); PrintLog( LOG_INFORMATION, "%d号终端 rtuaddr:%d 接收到命令返回other失败\n", rtuno, rtuaddr); CmdRet(0); pRxBuf->Move(datalen); pLink->SetCommStatus(CMST_TX_CNT); return 1; } return 1; } int CModbusTcpc17pis::GetNowSecond() { CSeTime SE_T; TCriterionTime tmptime; SE_T.GetNow(&tmptime); return (int)tmptime; } void CModbusTcpc17pis::ProcMeasure(uint8 *buf, int buflen) { sint32 rtuno = pLink->GetRtuNo(); uint16 ycyxNo; uint8 value0, value1; if (0x04 == buf[0]) { for (int j = 0; j < buf[1] / 2; j++)//只取低字节 { value0 = buf[2 + 2 * j + 1]; value1 = buf[2 + 2 * j]; for (int k = 0; k < 8; k++) { ycyxNo = 16 * j + k; PRawCtrl->PutAYx(rtuno, ycyxNo + 1, value0 & 1); value0 >>= 1; ycyxNo = 8 + 16 * j + k; PRawCtrl->PutAYx(rtuno, ycyxNo + 1, value1 & 1); value1 >>= 1; } } } } sint32 CModbusTcpc17pis::TxProc() { E_RAW_ComStat coms = pLink->GetCommStatus(); if (coms != CMST_TX_CNT && coms != CMST_NORMAL) return 0; if (ProcCmd()) { return 1; //处理外部下发命令 } if ((GetNowSecond() - m_nLastSendTime) > 1) { CallMeasure(); } return 1; } BOOL CModbusTcpc17pis::ProcCmd() { sint32 rtuno = pLink->GetRtuNo(); unsigned char rtuaddr = pRtu->GetRtuAddr(rtuno); int i = 0; S_RAWCMD rawcmd; while (pCmdMem->GetCmdNum(rtuno) > 0) { if (pCmdMem->GetACmd(rtuno, &rawcmd) == 0) break; PrintLog(LOG_INFORMATION, "收到%d号终端 rtuaddr:%d 命令", rtuno, rtuaddr); if (rawcmd.type == DC_K_CMD_PORTAL) { //读取Json包数据 std::string raw_data = (char*)(rawcmd.data); Json::Reader reader(Json::Features::strictMode()); Json::Value root; if (reader.parse(raw_data, root)) { int type = root["type"].asUInt(); if (type == 1) { pCmdMem->DelACmd(rtuno); break; } m_CmdSrc = rawcmd.src; m_nNo++; BYTE buf[512]; int len = 0; memset(buf, 0, 512); *(buf + len) = HIWORD(m_nNo); len++; *(buf + len) = LOWORD(m_nNo); len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x00; len++; *(buf + len) = 0xff; len++; *(buf + len) = 0x01; len++; *(buf + len) = 0x10; len++;//Function code *(buf + len) = 0x00; len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x7c; len++;//124word *(buf + len) = 0xf8; len++;//248[13-260]//13+248=261bytes??? *(buf + len) = HIWORD(m_nNo); len++; *(buf + len) = LOWORD(m_nNo); len++; int ctype = root["ctype"].asUInt(); int opt = root["opt"].asUInt(); switch (ctype) { case 1: //紧急控制 if (opt == 1) { *(buf + len + 0) = 0x00; *(buf + len + 1) = 0x01;//紧急控制 *(buf + len + 2) = 100;//音量1-100 *(buf + len + 3) = 0;//开播放模式 } else { *(buf + len + 0) = 0x00; *(buf + len + 1) = 0x01;//紧急取消 *(buf + len + 2) = 1;//音量1-100 *(buf + len + 3) = 1;//关取消播放模式 } break; case 2: //正常模式 if (opt == 1) { *(buf + len + 0) = 0x00; *(buf + len + 1) = 0x00;//正常控制 *(buf + len + 2) = 100;//音量1-100 *(buf + len + 3) = 0;//开播放模式 } else { *(buf + len + 0) = 0x00; *(buf + len + 1) = 0x00;//正常取消 *(buf + len + 2) = 1;//音量1-100 *(buf + len + 3) = 1;//关取消播放模式 } break; case 3: //特殊工况 break; case 7: //设置音量 *(buf + len + 0) = 0x00; *(buf + len + 1) = 0x02;//音量控制 if (opt > 100) *(buf + len + 2) = 100;//音量1-100 else *(buf + len + 2) = opt;//音量1-100 *(buf + len + 3) = 1;//关取消播放模式 break; case 8: //开关屏幕 *(buf + len + 0) = 0x00; *(buf + len + 1) = 0x04;//4-LCD开关屏模式 *(buf + len + 2) = 0; *(buf + len + 3) = opt + 1;//1-关屏;2-开屏 break; } len += 4; int zone = root["zone"].asUInt(); for (int k = 0; k < 4; k++)//站厅、上行、下行、出入口 { PRawCtrl->PutAYx(rtuno, 65 + k, zone & 1); *(buf + len) = 0; len++; *(buf + len) = zone & 1; len++; zone >>= 1; } int wlen = 0; //转码后字节数 if (ctype == 1 || ctype == 2 || ctype == 3) { std::string text = root["text"].asString(); char tmp[2048] = { 0 }; int n = 2048 - 1; strncpy(tmp, text.c_str(), n); char *inbuf = (char*)tmp; size_t inlen = strlen(inbuf); int m = 2048 * 4; size_t outlen = m; uint16 unicode[2048 * 4] = { 0 }; char* outbuf = (char*)unicode; char* from_charset = "gb2312"; char* to_charset = "utf-16"; iconv_t cd; char** pin = &inbuf; char** pout = &outbuf; cd = iconv_open(to_charset, from_charset); if (cd == 0) PrintLog(LOG_VIOLATION, "iconv false!\n"); memset(outbuf, 0, outlen); if (iconv(cd, pin, &inlen, pout, &outlen) == -1) { PrintLog(LOG_VIOLATION, "iconv false!inlen=%d,outlen=%d,Msg=%s,MsgLen=%d\n", inlen, (int)outlen, inbuf, text.length()); } wlen = m - outlen; if (wlen >116*2) { wlen = 116 * 2; memcpy(buf + len, (uint8*)(unicode), wlen); len += wlen; memset(buf + len, 0, 2); len += 2; } else { memcpy(buf + len, (uint8*)(unicode), wlen); len += wlen; memset(buf + len, 0, 117 * 2 - wlen); len += 117 * 2 - wlen; } iconv_close(cd); } else { memset(buf + len, 0, 117 * 2); len += 117 * 2; } char prttmp[1000] = { "TxCMD->" }; for (i = 0; i < len; i++) sprintf(prttmp + 3 * i + 7, "%02x ", buf[i]); PrintLog(LOG_INFORMATION, prttmp, rtuno); //*/ pTxBuf->Write(buf, len); pLink->SetCommStatus(CMST_NORMAL); m_nLastSendTime = GetNowSecond(); PrintLog(LOG_INFORMATION, "%d号终端-遥控命令直接下发", rtuno); pCmdMem->DelACmd(rtuno); return TRUE; } /* if (rawcmd.type == DC_K_CMD_PISINFO) { CSI_D_PIS_CMD *PisCmd; PisCmd = (CSI_D_PIS_CMD *)rawcmd.data; m_CmdSrc = rawcmd.src; m_nNo++; BYTE buf[512]; int len = 0; memset(buf,0,512); *(buf+len) = HIWORD(m_nNo);len++; *(buf+len) = LOWORD(m_nNo);len++; *(buf+len) = 0x00;len++; *(buf+len) = 0x00;len++; *(buf+len) = 0x00;len++; *(buf+len) = 0xff;len++; *(buf+len) = 0x01;len++; *(buf+len) = 0x10;len++;//Function code *(buf+len) = 0x00;len++; *(buf+len) = 0x00;len++; *(buf+len) = 0x00;len++; *(buf+len) = 0x7c;len++;//124word *(buf+len) = 0xf8;len++;//248[13-260]//13+248=261bytes??? *(buf+len) = HIWORD(m_nNo);len++; *(buf+len) = LOWORD(m_nNo);len++; switch (PisCmd->Func) { case PIS_FUNC_URGCTL: switch (PisCmd->Val) { case PIS_VAL_CTL_NORM: *(buf+len+0) = 0x00; *(buf+len+1) = 0x00;//紧急正常 *(buf+len+2) = 1;//音量1-100 *(buf+len+3) = 1;//关取消播放模式 break; case PIS_VAL_CTL_URGEN: *(buf+len+0) = 0x00; *(buf+len+1) = 0x01;//紧急控制 *(buf+len+2) = 100;//音量1-100 *(buf+len+3) = 0;//开播放模式 break; case PIS_VAL_CTL_CANCEL: *(buf+len+0) = 0x00; *(buf+len+1) = 0x00;//紧急取消 *(buf+len+2) = 10;//音量1-100 *(buf+len+3) = 1;//关取消播放模式 break; break; default: break; } break; case PIS_FUNC_ONOFF: // *(buf+len+0) = 0x00; // *(buf+len+1) = 0x00;//紧急取消 switch (PisCmd->Val) { case PIS_VAL_ON: *(buf+len+2) = 50;//音量1-100 *(buf+len+3) = 0x00;//开播放模式 break; case PIS_VAL_OFF: *(buf+len+2) = 0;//音量1-100 *(buf+len+3) = 0x01;//关取消播放模式 break; default: *(buf+len+2) = 0;//音量1-100 *(buf+len+3) = 0x01;//关取消播放模式 break; } break; case PIS_FUNC_VOLUME: *(buf+len+0) = 0x00; *(buf+len+1) = 0x02;//音量控制 if(PisCmd->Val>100) *(buf+len+2) = 100;//音量1-100 else *(buf+len+2) = PisCmd->Val;//音量1-100 *(buf+len+3) = 1;//关取消播放模式 break; case PIS_FUNC_LEDTEST://Modified by WYF20180605 开关屏 // *(buf+len+len) = 0x03;len++;//(h)LED屏幕测试 // *(buf+len+0) = 0x00; // *(buf+len+1) = 0x03;//3-出入口模式 // *(buf+len+2) = PisCmd->Val / 0x10;//0-2红绿黄 // *(buf+len+3) = PisCmd->Val % 0x10;//0-9播放速度 *(buf+len+0) = 0x00; *(buf+len+1) = 0x04;//4-LCD开关屏模式 *(buf+len+2) = 0; *(buf+len+3) = PisCmd->Val % 0x100;//1-关屏;2-开屏 break; default: *(buf+len+2) = 50;//音量1-100 *(buf+len+3) = 0x00;//开播放模式 break; } len += 4; //(e)车站区标志 uchar ztmp=0; for(i=0;i<13;i++) { ztmp=PisCmd->Zone[i]; if(ztmp>0)break; } for(int k = 0; k < 4; k++)//站厅、上行、下行、出入口 { PRawCtrl->PutAYx(rtuno,65+k,ztmp&1); *(buf+len)=0;len++; *(buf+len)=ztmp&1;len++; ztmp >>= 1; } char *sss="火灾"; //(g)信息内容或设备控制数值 if (PisCmd->Func == PIS_FUNC_URGCTL || PisCmd->Func == 0) { if(PisCmd->MsgLen>117*2) PisCmd->MsgLen=117*2; //buf[len]=49;buf[len+1]=50;buf[len+2]=51;buf[len+3]=52; //buf[len+5]=0x6b;buf[len+4]=0x70;buf[len+7]=0x7e;buf[len+6]=0x70; memcpy(buf+len, PisCmd->Msg, PisCmd->MsgLen); //len += PisCmd->MsgLen; //memset(buf+len, 0, 117*2 - PisCmd->MsgLen-8); len += 117*2;// - PisCmd->MsgLen-8; } else { memset(buf+len, 0, 117*2); len += 117*2; } // // char prttmp[1000]={"TxCMD->"}; // for(i=0; iWrite(buf,len); pLink->SetCommStatus(CMST_NORMAL); m_nLastSendTime = GetNowSecond(); PrintLog(LOG_INFORMATION,"%d号终端-遥控命令直接下发", rtuno); pCmdMem->DelACmd(rtuno); return TRUE; } */ else//对其它的下发命令不处理 pCmdMem->DelACmd(rtuno); break; } return FALSE; } } void CModbusTcpc17pis::SetExtendedPara(uint16 no, sint32 val) { if (no == 1) { m_nStationNo = val; } } void CModbusTcpc17pis::CmdRet(uint8 result) { sint32 rtuno = pLink->GetRtuNo(); S_RAWCMD rawcmd; S_CMD_RET cmdinfo; rawcmd.type = DC_K_CMDRET_PISINFO; rawcmd.len = sizeof(cmdinfo); rawcmd.src = m_CmdSrc; cmdinfo.RetCode = result; memcpy(rawcmd.data, &cmdinfo, sizeof(cmdinfo)); pCmdMem->RptAResult(rtuno, rawcmd); /* PrintLog( LOG_INFORMATION, "收到命令返回信息%d\n", result); */ } void CModbusTcpc17pis::CallMeasure() { sint32 rtuno = pLink->GetRtuNo(); unsigned char rtuadd = pRtu->GetRtuAddr(rtuno); BYTE buf[512]; int len = 0; m_nNo++; *(buf + len) = HIWORD(m_nNo); len++; *(buf + len) = LOWORD(m_nNo); len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x06; len++; *(buf + len) = 0x01; len++;//0xff *(buf + len) = 0x04; len++;//Function code *(buf + len) = 0x00; len++; *(buf + len) = 0; len++;//0x50 + m_nStationNo;len++; *(buf + len) = 0x00; len++; *(buf + len) = 0x04; len++;//0x0A;len++; pTxBuf->Write(buf, len); pLink->SetCommStatus(CMST_RX_CNT); m_nLastSendTime = GetNowSecond(); // PrintLog(LOG_INFORMATION,"召唤PIS设备状态rtuno:%d rtuaddr:1 len=4Word\n",rtuno); /* int i; for(i=0; i