📄 msghdler.cpp
字号:
//**************************************************************************
//
// Filename : Msghdler.cpp
//
// Subsystem :
//
// Description: Protocol message handlers.
//
//**************************************************************************
/*
* NT Definitions
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include "gencom.h"
#include "comiosrv.h"
#include "locmsgdef.h"
#define GET_BIT(a, b) (BYTE)a & (1 << b)
#define GET_BCD(a) (a >> 4) * 10 + (a & 0x0f)
#define SET_BCD(a) ((a / 10) << 4) + (a % 10)
static UINT SendCommand(CPio *pPio, REQUEST_MSGS *pMsg, int *respnum);
static USHORT mod_crc(BYTE *message, UINT message_length)
{
USHORT crc = 0xFFFF;
UINT byte;
UINT flag;
UINT shift;
if (message_length > 512)
return 0;
for ( byte = 0; byte < message_length; byte++ ) {
crc ^= message[ byte ];
for ( shift = 1; shift <= 8; shift++ ) {
flag = crc & 0x0001;
crc = crc>>1;
if ( flag == 1 ) {
crc ^= 0xA001;
}
}
}
return ( crc );
}
VOID PollMarshall(REQUEST_MSGS* pReqMsg, CPio* pPio)
{
int curtim, respsiz, msg_size = 0;
USHORT shtnum = 0;
BYTE *p_buf;
F2CMD *pF2Cmd;
F3CMD *pF3Cmd;
F12CMD *pF12Cmd;
/*
* If we are starting a poll, the command setup device in polled mode.
*/
p_buf = GetPioWrtBuf(pPio);
switch ( pReqMsg->FuncCode ) {
case INIT_POLL:
case INFO_POLL: // normal polling, digital input
if (pReqMsg->FuncCode != INIT_POLL) {
// do time related action if any
curtim = GetComSystim();
if (GetRtuClkSyn(pReqMsg->pRtu)) {
// need manually set time sync command
ClrRtuClkSyn(pReqMsg->pRtu);
SetRtuSoeSts(pReqMsg->pRtu);
respsiz = (BYTE)GetRtuNetId(pReqMsg->pRtu);
pReqMsg->FuncCode = TIME_SYNC;
msg_size = SendCommand(pPio, pReqMsg, &respsiz);
SetPioReadHeadCnt(pPio, respsiz);
SetPioReadCnt(pPio, respsiz);
// clear polling flag for next polling
ClrRtuPollSts(pReqMsg->pRtu);
}
else if ((curtim % 300) < 30 && !GetRtuSoeSts(pReqMsg->pRtu)) {
if (IsCommFirstRtu(pReqMsg->pRtu)) {
// need set time sync command
SetRtuSoeSts(pReqMsg->pRtu);
respsiz = 0; // broadcast on this channel
pReqMsg->FuncCode = TIME_SYNC;
msg_size = SendCommand(pPio, pReqMsg, &respsiz);
SetPioReadHeadCnt(pPio, respsiz);
SetPioReadCnt(pPio, respsiz);
// clear polling flag for next polling
ClrRtuPollSts(pReqMsg->pRtu);
}
}
// for next trigger, clear the flags
if ((curtim % 300) > 150 && GetRtuSoeSts(pReqMsg->pRtu))
ClrRtuSoeSts(pReqMsg->pRtu);
}
if (msg_size == 0) {
// issue poll command
SetRtuCmdStep(pReqMsg->pRtu, 0);
pF2Cmd = (F2CMD *)p_buf;
pF2Cmd->addr = (BYTE)GetRtuNetId(pReqMsg->pRtu);
pF2Cmd->func = FUNC_2;
pF2Cmd->reg = 0;
pF2Cmd->num = byte_swap(DIGDATBYT * 8);
pF2Cmd->crc = mod_crc(p_buf, (MODBUS_F2_SIZ - 2 ) );
msg_size = MODBUS_F2_SIZ;
SetPioReadHeadCnt(pPio, MODBUS_F2_REPLY_SIZ);
SetPioReadCnt(pPio, MODBUS_F2_REPLY_SIZ);
}
SetPioUnPackFunc(pPio, PollUnmarshall);
break;
case RFLH_POLL: // send additional polling
switch (GetRtuCmdStep(pReqMsg->pRtu)) {
case 1: // get soe message
pF12Cmd = (F12CMD *)p_buf;
pF12Cmd->addr = (BYTE)GetRtuNetId(pReqMsg->pRtu);
pF12Cmd->func = FUNC_12;
pF12Cmd->reg = 0;
pF12Cmd->num = byte_swap(SOEDATNUM);
pF12Cmd->crc = mod_crc(p_buf, (MODBUS_F12_SIZ - 2 ) );
msg_size = MODBUS_F12_SIZ;
SetPioReadHeadCnt(pPio, MODBUS_F12_REPLY_SIZ);
SetPioReadCnt(pPio, MODBUS_F12_REPLY_SIZ);
SetPioUnPackFunc(pPio, PollUnmarshall);
break;
case 2: // analog input
pF3Cmd = (F3CMD *)p_buf;
pF3Cmd->addr = (BYTE)GetRtuNetId(pReqMsg->pRtu);
pF3Cmd->func = FUNC_3;
pF3Cmd->reg = 0;
shtnum = GetDefGrpPnt(pReqMsg->pRtu, AINORMSLOT);
pF3Cmd->num = byte_swap(shtnum * 2);
pF3Cmd->crc = mod_crc(p_buf, (MODBUS_F3_SIZ - 2 ) );
msg_size = MODBUS_F3_SIZ;
respsiz = shtnum * 2 + 6;
SetPioReadHeadCnt(pPio, respsiz);
SetPioReadCnt(pPio, respsiz);
SetPioUnPackFunc(pPio, PollUnmarshall);
break;
}
break;
case DIGI_COMD: // digital output command
// form command by frame type
msg_size = SendCommand(pPio, pReqMsg, &respsiz);
SetPioReadHeadCnt(pPio, respsiz);
SetPioReadCnt(pPio, respsiz);
SetPioUnPackFunc(pPio, PollUnmarshall);
SetPioWriteCnt(pPio, msg_size);
break;
case ANAL_COMD: // register output command
// form command by frame type
msg_size = SendCommand(pPio, pReqMsg, &respsiz);
SetPioReadHeadCnt(pPio, respsiz);
SetPioReadCnt(pPio, respsiz);
SetPioUnPackFunc(pPio, PollUnmarshall);
SetPioWriteCnt(pPio, msg_size);
break;
case RELY_COMD: // relay control command
// form command by frame type
msg_size = SendCommand(pPio, pReqMsg, &respsiz);
SetPioReadHeadCnt(pPio, respsiz);
SetPioReadCnt(pPio, respsiz);
SetPioUnPackFunc(pPio, PollUnmarshall);
SetPioWriteCnt(pPio, msg_size);
break;
default:
printf( "PollMarshall(), Unexpected Cmd: %d\n", pReqMsg->FuncCode);
break;
}
memcpy(GetPioUserDefMsg(pPio), pReqMsg, sizeof(REQUEST_MSGS) );
SetPioWriteCnt(pPio, msg_size);
SetPioWriteOffset(pPio, 0);
//
// STS commands are acknowledged
// Set this stuff for a reply!
//
// One pass read, Simple two pass, purge
SetPioComState(pPio, FALSE, FALSE, TRUE);
// write data to debug buffer if rtu in debug mode
SetPioRtuDbgOutMsg(pPio, pReqMsg->pRtu);
SetPioReadOffset(pPio, 0);
SetPioReadFixupCnt(pPio, 0);
}
VOID PollUnmarshall(CPio *pPio, int ioStream)
{
BYTE *p_buf, *pSts, data[8], valtyp;
int i, j, gix, nStep, sts, pix, value, len, procdi = 0;
int setval, startidx, setidx, cpuidx, setnum, inpcnt;
USHORT shtval, crc;
float fvalue = 0.0f;
BOOL bChange = FALSE;
REQUEST_MSGS *sendInfo = (REQUEST_MSGS*)GetPioUserDefMsg(pPio);
F2RSP *pF2Rsp;
F3RSP *pF3Rsp;
F5RSP *pF5Rsp;
F12RSP *pF12Rsp;
SOETIME soeTime;
char comstr[64];
p_buf = GetPioReadBuf(pPio);
sts = GetPioRecvStatus(pPio);
if ( sts == PIO__SUCCESS ||
sts == PIO__BAD_MSG_LENGTH ) {
// write data to debug buffer if rtu in debug mode
SetPioRtuDbgInMsg(pPio, sendInfo->pRtu);
if (p_buf[0] != (BYTE)GetRtuNetId(sendInfo->pRtu)) {
SetPioRecvStatus(pPio, PIO__ACK_NOT_FOUND);
SetRtuCmdStep(sendInfo->pRtu, 0);
// clear polling flag for next polling
ClrRtuPollSts(sendInfo->pRtu);
ClrPioRtuStream(ioStream);
return;
}
len = GetPioReadCnt(pPio);
crc = mod_crc(p_buf, len - 2);
switch (sendInfo->FuncCode) {
case INIT_POLL:
case INFO_POLL: // normal polling, digital input
case RFLH_POLL: // send additional polling
nStep = GetRtuCmdStep(sendInfo->pRtu);
switch (nStep) {
case 0: // digital input
pF2Rsp = (F2RSP *)p_buf;
if (crc != *(USHORT *)&p_buf[len - 2]) {
SetPioRecvStatus(pPio, PIO__BAD_CHECKSUM);
SetRtuCmdStep(sendInfo->pRtu, 0);
// clear polling flag for next polling
ClrRtuPollSts(sendInfo->pRtu);
}
else {
gix = DINORMSLOT;
pix = 0;
for (i = 0; i < (len - 6); i++) {
for (j = 0; j < 8; j++) {
value = (UCHAR)GET_BIT(pF2Rsp->pts[i], j) ? 1 : 0;
procdi = UpdRtuRawData(sendInfo->pRtu, gix, pix, value);
if (procdi) {
bChange = TRUE;
}
pix++;
}
if ((i % 4) == 3) {
gix++;
pix = 0;
}
}
if (GET_BIT(pF2Rsp->pts[3], 7)) { // has soe message
SetRtuCmdStep(sendInfo->pRtu, 1);
}
else { // to poll analog input data
SetRtuCmdStep(sendInfo->pRtu, 2);
}
if (bChange) { // any DI change during process
UpdRtuPntSts(sendInfo->pRtu, 1);
}
if ( sts == PIO__BAD_MSG_LENGTH ) {
SetPioRecvStatus(pPio, PIO__SUCCESS);
}
// send additional polling command
sendInfo->FuncCode = RFLH_POLL;
// add a high priority refresh poll
AddMorePollCmd(sendInfo, TRUE);
}
break;
case 1: // soe message
pF12Rsp = (F12RSP *)p_buf;
if (crc != *(USHORT *)&p_buf[len - 2]) {
SetPioRecvStatus(pPio, PIO__BAD_CHECKSUM);
SetRtuCmdStep(sendInfo->pRtu, 0);
// clear polling flag for next polling
ClrRtuPollSts(sendInfo->pRtu);
}
else {
SetRtuCmdStep(sendInfo->pRtu, 2);
soeTime.year = 2000 + GET_BCD(pF12Rsp->year);
soeTime.mon = GET_BCD(pF12Rsp->mon);
soeTime.day = GET_BCD(pF12Rsp->day);
soeTime.hour = GET_BCD(pF12Rsp->hour);
soeTime.min = GET_BCD(pF12Rsp->min);
soeTime.sec = GET_BCD(pF12Rsp->sec);
soeTime.cms = GET_BCD(pF12Rsp->ms[0]) * 100 + GET_BCD(pF12Rsp->ms[1]);
switch (pF12Rsp->type) {
case 1: // normal di soe
gix = DINORMSLOT;
pix = pF12Rsp->idx;
if (pix < 8) {
value = (UCHAR)GET_BIT(pF12Rsp->state[1], pix) ? 1 : 0;
}
else if (pix < 16) {
value = (UCHAR)GET_BIT(pF12Rsp->state[0], pix) ? 1 : 0;
}
else { // control wire broken
value = 1;
}
// generate SOE message
UpdRtuSoeData(sendInfo->pRtu, gix, pix, value, &soeTime);
break;
case 2: // protect relay soe
gix = DINORMSLOT;
pix = pF12Rsp->idx + DIPROOFFSET;
value = (pF12Rsp->state[3] | pF12Rsp->state[2] << 8 |
pF12Rsp->state[1] << 16 | pF12Rsp->state[0] << 24) / 2;
switch (pF12Rsp->attr) {
case 0: // 电流
case 5: // 正序电流
case 6: // 负序电流
case 8: // 横差
fvalue = (float)sqrt((double)value) * 100.0f / CURRRATIO / 12.0f;
sprintf(comstr, "%s%6.2f", evtstr[pF12Rsp->attr], fvalue);
// send soe message
UpdRtuSoeData(sendInfo->pRtu, gix, pix, 1, &soeTime, comstr);
break;
case 1: // 电压
case 4: // 零序电压
fvalue = (float)sqrt((double)value) * 100.0f / VOLTRATIO / 12.0f;
sprintf(comstr, "%s%6.2f", evtstr[pF12Rsp->attr], fvalue);
// send soe message
UpdRtuSoeData(sendInfo->pRtu, gix, pix, 1, &soeTime, comstr);
break;
case 2: // 频率(动作值取前两字节)
value = pF12Rsp->state[1] | pF12Rsp->state[0] << 8;
fvalue = FREQRATIO / (float)value;
sprintf(comstr, "%s%6.2f", evtstr[pF12Rsp->attr], fvalue);
// send soe message
UpdRtuSoeData(sendInfo->pRtu, gix, pix, 1, &soeTime, comstr);
break;
case 3: // 零序电流
fvalue = (float)sqrt((double)value) * 100.0f / ZCURRATIO / 12.0f;
sprintf(comstr, "%s%6.2f", evtstr[pF12Rsp->attr], fvalue);
// send soe message
UpdRtuSoeData(sendInfo->pRtu, gix, pix, 1, &soeTime, comstr);
break;
case 7: // 温度
UpdRtuSoeData(sendInfo->pRtu, gix, pix, 1, &soeTime);
break;
case 9: // 功率
UpdRtuSoeData(sendInfo->pRtu, gix, pix, 1, &soeTime);
break;
}
// issue alarm for this point as well
// UpsRtuSoeAlm(sendInfo->pRtu, gix, pix);
break;
}
}
// send additional polling command
sendInfo->FuncCode = RFLH_POLL;
// add a high priority refresh poll
AddMorePollCmd(sendInfo, TRUE);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -