map/das-dn/hostmodbustcp/host_modbus_tcp.cpp
2024-11-20 15:43:54 +08:00

1282 lines
46 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "host_modbus_tcp.h"
///////////////////////////////////////////////////////////////////////////////////
//Valid slave device addresses are in the range of 0 锟?C 247 decimal. //
//The individual slave devices are assigned addresses in the range of 1 锟?C 247. //
//Address 0 is used for the broadcast address, which all slave devices recognize.//
///////////////////////////////////////////////////////////////////////////////////
CHostModbusTcpProcessItem::CHostModbusTcpProcessItem()
{
m_nNum = 0;
m_nFramePoll = 0;
apdu_t0_begin = 1;
m_nCurFrame = 0;
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
}
CHostModbusTcpProcessItem::~CHostModbusTcpProcessItem()
{
m_nNum = 0;
m_nFramePoll = 0;
apdu_t0_begin = 1;
m_nCurFrame = 0;
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
}
void CHostModbusTcpProcessItem::AddFrames(struModbusExtFrame* yxs, struModbusExtFrame* ycs, struModbusExtFrame* yms)
{
int i = 0, j = 0;
memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames));
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
{
if (yxs[j].FrameType == 0 || yxs[j].FuncCode == 0 || yxs[j].RegCount == 0) continue;
memcpy(&m_nModbusFrames[i], &yxs[j], sizeof(struModbusExtFrame));
i++;
if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break;
}
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
{
if (ycs[j].FrameType == 0 || ycs[j].FuncCode == 0 || ycs[j].RegCount == 0) continue;
memcpy(&m_nModbusFrames[i], &ycs[j], sizeof(struModbusExtFrame));
i++;
if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break;
}
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
{
if (yms[j].FrameType == 0 || yms[j].FuncCode == 0 || yms[j].RegCount == 0) continue;
memcpy(&m_nModbusFrames[i], &yms[j], sizeof(struModbusExtFrame));
i++;
if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break;
}
}
struModbusExtFrame* CHostModbusTcpProcessItem::GetNextFrame(void)
{
int last;
if (m_nCurFrame >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) return NULL;
if (m_nCurFrame < 0) m_nCurFrame = -1;
last = m_nCurFrame;
for (m_nCurFrame++; m_nCurFrame < MODBUS_RTU_AUTOMATIC_FRAME_MAX; m_nCurFrame++)
{
if (m_nModbusFrames[m_nCurFrame].FuncCode == 0 || m_nModbusFrames[m_nCurFrame].FrameType == 0) break;
return &m_nModbusFrames[m_nCurFrame];
}
for (m_nCurFrame = 0; m_nCurFrame <= last; m_nCurFrame++)
{
if (m_nModbusFrames[m_nCurFrame].FuncCode == 0 || m_nModbusFrames[m_nCurFrame].FrameType == 0) break;
return &m_nModbusFrames[m_nCurFrame];
}
return NULL;
}
void CHostModbusTcpProcessItem::Attach(int uid, int sock, DWORD peer_addr, WORD peer_port)
{
CNetProcessItem::Attach(uid, sock, peer_addr, peer_port);
apdu_t0_begin = 1;
m_nNum = 0;
m_nFramePoll = 0;
m_nCurFrame = 0;
}
void CHostModbusTcpProcessItem::Release(void)
{
apdu_t0_begin = 1;
m_nNum = 0;
m_nFramePoll = 0;
m_nCurFrame = 0;
CNetProcessItem::Release();
}
CHostModbusTcpProcess::CHostModbusTcpProcess()
{
m_nCount = 0;
m_nFrameCount = 0;
m_nCurFrame = 0;
m_nSendPoint = 0;
m_nCurBeginReg = 0;
m_nNeedSend = FALSE;
}
CHostModbusTcpProcess::~CHostModbusTcpProcess()
{
}
CNetProcessItem *CHostModbusTcpProcess::CreateItem(int ord)
{
return dynamic_cast<CNetProcessItem *>(new CHostModbusTcpProcessItem);
}
void CHostModbusTcpProcess::DestroyItem(int ord, BOOLEAN bDeleted /* = FALSE */)
{
CHostModbusTcpProcessItem *pItem = (CHostModbusTcpProcessItem *)GetItem(ord);
if (pItem != NULL && !bDeleted)
{
delete pItem;
return CNetProcess::DestroyItem(ord, TRUE);
}
return CNetProcess::DestroyItem(ord, bDeleted);
}
void CHostModbusTcpProcess::sort1(STRUCT_PARAM *params, int count)
{
int i, j, n;
STRUCT_PARAM temp;
n = count;
for (i = 0; i < n - 1; ++i) //比较n-1轮
{
for (j = 0; j < n - 1 - i; ++j) //每轮比较n-1-i次,
{
if (params[j].param[0] > params[j + 1].param[0])
{
memcpy(&temp, &params[j], sizeof(STRUCT_PARAM));
memcpy(&params[j], &params[j + 1], sizeof(STRUCT_PARAM));
memcpy(&params[j + 1], &temp, sizeof(STRUCT_PARAM));
}
}
}
}
void CHostModbusTcpProcess::sort2(STRUCT_PARAM *params, int count)
{
int i, j, n;
STRUCT_PARAM temp;
n = count;
for (i = 0; i < n - 1; ++i) //比较n-1轮
{
for (j = 0; j < n - 1 - i; ++j) //每轮比较n-1-i次,
{
int addr1 = (int)MAKEWORD(params[j].param[1], params[j].param[2]);
int addr2 = (int)MAKEWORD(params[j+1].param[1], params[j+1].param[2]);
if (addr1 > addr2)
{
memcpy(&temp, &params[j], sizeof(STRUCT_PARAM));
memcpy(&params[j], &params[j + 1], sizeof(STRUCT_PARAM));
memcpy(&params[j + 1], &temp, sizeof(STRUCT_PARAM));
}
}
}
}
void CHostModbusTcpProcess::calc2(void)
{
int i, j, n, uid;
BYTE addr;
CHostModbusTcpProcessItem *pItem;
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CHostModbusTcpProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
if (GetUnitAddr(uid, &addr, 1))
{ //获取单元地址成功,则该段原地址采用配置地址,否则该单元为无效地址。
pItem->m_addr = addr;
}
struModbusExtFrame ycframes[MODBUS_RTU_AUTOMATIC_FRAME];
struModbusExtFrame ymframes[MODBUS_RTU_AUTOMATIC_FRAME];
struModbusExtFrame yxframes[MODBUS_RTU_AUTOMATIC_FRAME];
memset(ycframes, 0, sizeof(ycframes));
memset(ymframes, 0, sizeof(ymframes));
memset(yxframes, 0, sizeof(yxframes));
struUnitModbusOption option;
if (GetUnitOption(uid, &option, sizeof(option)))
{
if (option.use_owner_config)
{ //采用协议配置
if (option.modbus.yx1Enable)
{
yxframes[0].FrameType = MODBUSP_READ_YX1;
yxframes[0].FuncCode = option.modbus.yx1FuncCode;
yxframes[0].RegBegin = option.modbus.yx1Begin;
yxframes[0].RegCount = option.modbus.yx1Count;
}
if (option.modbus.yx2Enable)
{
yxframes[1].FrameType = MODBUSP_READ_YX1;
yxframes[1].FuncCode = option.modbus.yx2FuncCode;
yxframes[1].RegBegin = option.modbus.yx2Begin;
yxframes[1].RegCount = option.modbus.yx2Count;
}
if (option.modbus.yc1Enable)
{
ycframes[0].FrameType = MODBUSP_READ_YC1;
ycframes[0].FuncCode = option.modbus.yc1FuncCode;
ycframes[0].RegBegin = option.modbus.yc1Begin;
ycframes[0].RegCount = option.modbus.yc1Count;
}
if (option.modbus.yc2Enable)
{
ycframes[1].FrameType = MODBUSP_READ_YC1;
ycframes[1].FuncCode = option.modbus.yc2FuncCode;
ycframes[1].RegBegin = option.modbus.yc2Begin;
ycframes[1].RegCount = option.modbus.yc2Count;
}
if (option.modbus.yc3Enable)
{
ycframes[2].FrameType = MODBUSP_READ_YC1;
ycframes[2].FuncCode = option.modbus.yc3FuncCode;
ycframes[2].RegBegin = option.modbus.yc3Begin;
ycframes[2].RegCount = option.modbus.yc3Count;
}
if (option.modbus.yc4Enable)
{
ycframes[3].FrameType = MODBUSP_READ_YC1;
ycframes[3].FuncCode = option.modbus.yc4FuncCode;
ycframes[3].RegBegin = option.modbus.yc4Begin;
ycframes[3].RegCount = option.modbus.yc4Count;
}
if (option.modbus.ym1Enable)
{
ymframes[0].FrameType = MODBUSP_READ_YM1;
ymframes[0].FuncCode = option.modbus.ym1FuncCode;
ymframes[0].RegBegin = option.modbus.ym1Begin;
ymframes[0].RegCount = option.modbus.ym1Count;
}
if (option.modbus.ym2Enable)
{
ymframes[1].FrameType = MODBUSP_READ_YM1;
ymframes[1].FuncCode = option.modbus.ym2FuncCode;
ymframes[1].RegBegin = option.modbus.ym2Begin;
ymframes[1].RegCount = option.modbus.ym2Count;
}
//按寄存器排序
pItem->AddFrames(ycframes, ymframes, yxframes);
continue;
}
}
{
int yccount, ymcount, yxcount;
yccount = GetUnitYCCount(uid);
ymcount = GetUnitYMCount(uid);
yxcount = GetUnitYXCount(uid);
STRUCT_PARAM *ycparam = NULL, *ymparam = NULL, *yxparam = NULL;
if (yccount) ycparam = new STRUCT_PARAM[yccount];
if (ymcount) ymparam = new STRUCT_PARAM[ymcount];
if (yxcount) yxparam = new STRUCT_PARAM[yxcount];
if (ycparam)
{
memset(ycparam, 0, sizeof(STRUCT_PARAM) * yccount);
for (n = 0; n < yccount; n++)
{
memcpy(ycparam[n].param, GetUnitYCParamByPoint(uid, n), sizeof(STRUCT_PARAM));
}
//按功能码排序
sort1(ycparam, yccount);
//按寄存器地址排序
sort2(ycparam, yccount);
//组帧
for (n = 0; n < yccount; n++)
{
WORD addr = MAKEWORD(ycparam[n].param[1], ycparam[n].param[2]);
if (addr >= 65535) continue;
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
{
if (ycframes[j].FuncCode == 0)
{
ycframes[j].FrameType = MODBUSP_READ_YC1;
ycframes[j].FuncCode = ycparam[n].param[0];
ycframes[j].RegBegin = addr;
ycframes[j].RegCount = ycparam[n].param[3];
break;
}
if (ycframes[j].FuncCode == ycparam[n].param[0])
{
if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + ycframes[j].RegBegin)
{
int len = addr - ycframes[j].RegBegin;
if (len)
{
ycframes[j].RegCount = len + ycparam[n].param[3];
}
else
{
vLog(LOG_DEBUG, "遥测测点配置了相同的功能码和寄存器地址\n");
}
break;
}
}
}
}
}
if (ymparam)
{
memset(ymparam, 0, sizeof(STRUCT_PARAM) * ymcount);
for (n = 0; n < ymcount; n++)
{
memcpy(ymparam[n].param, GetUnitYMParamByPoint(uid, n), sizeof(STRUCT_PARAM));
}
sort1(ymparam, ymcount);
sort2(ymparam, ymcount);
//组帧
for (n = 0; n < ymcount; n++)
{
WORD addr = MAKEWORD(ymparam[n].param[1], ymparam[n].param[2]);
if (addr >= 65535) continue;
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
{
if (ymframes[j].FuncCode == 0)
{
ymframes[j].FrameType = MODBUSP_READ_YM1;
ymframes[j].FuncCode = ymparam[n].param[0];
ymframes[j].RegBegin = addr;
ymframes[j].RegCount = ymparam[n].param[3];
break;
}
if (ymframes[j].FuncCode == ymparam[n].param[0])
{
if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + ymframes[j].RegBegin)
{
int len = addr - ymframes[j].RegBegin;
if (len)
{
ymframes[j].RegCount = len + ymparam[n].param[3];
}
else
{
vLog(LOG_DEBUG, "遥脉测点配置了相同的功能码和寄存器地址\n");
}
break;
}
}
}
}
}
if (yxparam)
{
memset(yxparam, 0, sizeof(STRUCT_PARAM) * yxcount);
for (n = 0; n < yxcount; n++)
{
memcpy(yxparam[n].param, GetUnitYXParamByPoint(uid, n), sizeof(STRUCT_PARAM));
}
sort1(yxparam, yxcount);
sort2(yxparam, yxcount);
//组帧
for (n = 0; n < yxcount; n++)
{
WORD addr = MAKEWORD(yxparam[n].param[1], yxparam[n].param[2]);
if (addr >= 65535) continue;
for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++)
{
if (yxframes[j].FuncCode == 0)
{
yxframes[j].FrameType = MODBUSP_READ_YX1;
yxframes[j].FuncCode = yxparam[n].param[0];
yxframes[j].RegBegin = addr;
yxframes[j].RegCount = 1;
break;
}
if (yxframes[j].FuncCode == yxparam[n].param[0])
{
int len = addr - yxframes[j].RegBegin;
if (len)
{
if (yxframes[j].FuncCode == MODBUSC_F01 || yxframes[j].FuncCode == MODBUSC_F02)
{
if (addr <= MODBUS_MAX_BITMAP_REGISTER_NUM + yxframes[j].RegBegin)
{
yxframes[j].RegCount = len + 1;
break;
}
}
else if (yxframes[j].FuncCode == MODBUSC_F03 || yxframes[j].FuncCode == MODBUSC_F04)
{
if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + yxframes[j].RegBegin)
{
yxframes[j].RegCount = len + 1;
break;
}
}
}
else
{
if (yxframes[j].FuncCode == MODBUSC_F01 || yxframes[j].FuncCode == MODBUSC_F02)
{
vLog(LOG_DEBUG, "遥信测点配置了相同的功能码和寄存器地址\n");
}
break;
}
}
}
}
}
//按寄存器排序
pItem->AddFrames(ycframes, ymframes, yxframes);
}
}
}
BOOLEAN CHostModbusTcpProcess::OnPreCreate(int id)
{
if (!CNetProcess::OnPreCreate(id)) return FALSE;
m_nTimeout = 200;
calc2();
return TRUE;
}
BOOLEAN CHostModbusTcpProcess::Run(void)
{
int count;
BYTE buffer[512];
if (!CNetProcess::Run()) return FALSE;
FeedDog();
//process polling command
CHostModbusTcpProcessItem *pItem = (CHostModbusTcpProcessItem *)GetItem(0);
if (NULL == pItem) return TRUE;
if (pItem->GetSock() < 0) {
usleep(20000);
return TRUE;
}
pItem = (CHostModbusTcpProcessItem *)GetCurItem();
if (NULL == pItem) return TRUE;
buffer[0] = HIBYTE(pItem->m_nNum); buffer[1] = LOBYTE(pItem->m_nNum);
buffer[2] = 0; buffer[3] = MB_TCP_PROTOCOL_ID;
if ((m_nCurFrame == 0 && m_nNeedSend))
{
count = 0;
if (GetYKFrame(pItem, &buffer[6], count, m_nCurFrame, m_nCurFuncCode))
{ //insert yk command
}
else if (GetYTFrame(pItem, &buffer[6], count, m_nCurFrame, m_nCurFuncCode))
{ //insert yt command
}
else if (pItem->m_nFramePoll & MODBUSP_SET_TIME_FRAME)
{
pItem->m_nFramePoll &= ~MODBUSP_SET_TIME_FRAME;
if (GetSetTimeFrame(pItem, &buffer[6], count))
{
m_nCurFrame = 0;
}
}
else if (pItem->m_nFramePoll & MODBUSP_GET_DATA_FRAME)
{
pItem->m_nFramePoll &= ~MODBUSP_GET_DATA_FRAME;
if (GetReadDataFrame(pItem, &buffer[6], count))
{
m_nCurFrame = m_nFrameType;
}
}
if (count >= 2)
{ //发送前清除接收缓冲区所有数据
buffer[4] = HIBYTE(count);
buffer[5] = LOBYTE(count);
if (WriteData(buffer, count + 6, 0))
{
DisplayTxData(buffer, count + 6, TRUE);
}
pItem->m_nNum++;
m_nSendPoint = system32.ticks;//0;
m_nNeedSend = FALSE;
FeedDog();
}
}
return TRUE;
}
BOOLEAN CHostModbusTcpProcess::OnTimer(void)
{
CHostModbusTcpProcessItem *pItem;
if (!CNetProcess::OnTimer()) return FALSE;
m_nCount++;
pItem = (CHostModbusTcpProcessItem *)GetItem(0);
if (NULL == pItem) return FALSE;
if (pItem->GetSock() < 0)
{
if ((pItem->apdu_t0_begin + 30) < system32.timers)
{
pItem->apdu_t0_begin = system32.timers;
Connect(pItem, 0, TRUE);
}
return TRUE;
}
if (m_nCurFrame != 0)
{
if (m_nSendPoint && (m_nSendPoint + m_nTimeout) <= system32.ticks)
{ //0.5 second command time out
m_nSendPoint = 0;
m_nCurFrame = 0;
}
}
if (m_nCurFrame == 0 && (m_nCount % PollGap()) == 0)
{
pItem = (CHostModbusTcpProcessItem *)GetNextItem();
if (pItem == NULL) return TRUE;
m_nNeedSend = TRUE;
struModbusExtFrame* frame = pItem->GetNextFrame();
if (frame != NULL)
{
m_nFrameType = frame->FrameType;
m_nCurFuncCode = frame->FuncCode;
m_nCurBeginReg = frame->RegBegin;
m_nCurRegCount = frame->RegCount;
pItem->m_nFramePoll |= MODBUSP_GET_DATA_FRAME;
return TRUE;
}
}
return TRUE;
}
BOOLEAN CHostModbusTcpProcess::GetYKFrame(CHostModbusTcpProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode)
{
int uid;
BYTE result;
BYTE* pData;
if (NULL == pItem) return FALSE;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
if (NULL == pBuf) return FALSE;
pData = pBuf;
if (!GetUnitYK(uid, m_nYKOrder, m_bYKValue, m_nYKState, result))
{
return FALSE;
}
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s.\n", uid, m_nYKOrder, (m_bYKValue ? "ClOSE" : "TRIP"), val_to_str(m_nYKState, yk_state, "STATE = %d"), val_to_str(result, yk_result, "RESULT = %d"));
BYTE* m_param;
BYTE nFun; //功能码
BOOLEAN nNeedSelect; //遥控需要选择
WORD nReg, nVal;
WORD nCloseSelReg, nCloseExecReg, nCloseEscReg, nCloseValue; //合闸命令参数
WORD nOpenSelReg, nOpenExecReg, nOpenEscReg, nOpenValue; //分闸命令参数
m_param = GetUnitYKParamByPoint(uid, m_nYKOrder);
if (NULL == m_param) return FALSE;
nFun = m_param[0]; //功能码占一个字节
nNeedSelect = m_param[1]; //遥控是否需要选择
nCloseSelReg = MAKEWORD(m_param[4], m_param[5]); //选择合寄存器
nCloseExecReg = MAKEWORD(m_param[6], m_param[7]); //执行合寄存器
nCloseEscReg = MAKEWORD(m_param[8], m_param[9]); //撤销合寄存器
nCloseValue = MAKEWORD(m_param[10], m_param[11]); //合
nOpenSelReg = MAKEWORD(m_param[12], m_param[13]); //选择分寄存器
nOpenExecReg = MAKEWORD(m_param[14], m_param[15]); //执行分寄存器
nOpenEscReg = MAKEWORD(m_param[16], m_param[17]); //撤销分寄存器
nOpenValue = MAKEWORD(m_param[18], m_param[19]); //分
if (m_nYKState == YKS_SELREQ)
{ //遥控选择
if (m_bYKValue)
{
nReg = nCloseSelReg;
nVal = nCloseValue;
}
else
{
nReg = nOpenSelReg;
nVal = nOpenValue;
}
if (0xffff == nReg || !nNeedSelect)
{ //寄存器无效,遥控无须选择
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_SELED, YKR_SUCC);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
return FALSE;
}
else
{
pData[0] = pItem->m_addr;
pData[1] = nFun;
pData[2] = (nReg >> 8) & 0x00ff;
pData[3] = nReg & 0x00ff;
pData[4] = (nVal >> 8) & 0x00ff;
pData[5] = nVal & 0x00ff;
count = 6;
FuncCode = nFun;
frame = MODBUSP_YK_SELECT;
return TRUE;
}
}
else if (m_nYKState == YKS_EXEREQ)
{ //遥控执行
if (m_bYKValue)
{
nReg = nCloseExecReg;
nVal = nCloseValue;
}
else
{
nReg = nOpenExecReg;
nVal = nOpenValue;
}
if (0xffff == nReg) return FALSE;
pData[0] = pItem->m_addr;
pData[1] = nFun;
pData[2] = (nReg >> 8) & 0x00ff;
pData[3] = nReg & 0x00ff;
pData[4] = (nVal >> 8) & 0x00ff;
pData[5] = nVal & 0x00ff;
count = 6;
FuncCode = nFun;
frame = MODBUSP_YK_EXECUTE;
return TRUE;
}
else if (m_nYKState == YKS_ABRREQ)
{ //遥控撤销
if (m_bYKValue)
{
nReg = nCloseEscReg;
nVal = nCloseValue;
}
else
{
nReg = nOpenEscReg;
nVal = nOpenValue;
}
if (0xffff == nReg || !nNeedSelect)
{ //寄存器无效
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
return FALSE;
}
pData[0] = pItem->m_addr;
pData[1] = nFun;
pData[2] = (nReg >> 8) & 0x00ff;
pData[3] = nReg & 0x00ff;
pData[4] = (nVal >> 8) & 0x00ff;
pData[5] = nVal & 0x00ff;
count = 6;
FuncCode = nFun;
frame = MODBUSP_YK_CANCEL;
return TRUE;
}
else if ((m_nYKState == YKS_SELING || m_nYKState == YKS_SELED) && result == YKR_OVER)
{ //遥控撤销
if (m_bYKValue)
{
nReg = nCloseEscReg;
nVal = nCloseValue;
}
else
{
nReg = nOpenEscReg;
nVal = nOpenValue;
}
if (0xffff == nReg || !nNeedSelect)
{ //寄存器无效
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
return FALSE;
}
pData[0] = pItem->m_addr;
pData[1] = nFun;
pData[2] = (nReg >> 8) & 0x00ff;
pData[3] = nReg & 0x00ff;
pData[4] = (nVal >> 8) & 0x00ff;
pData[5] = nVal & 0x00ff;
count = 6;
FuncCode = nFun;
frame = MODBUSP_YK_CANCEL;
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
// yt start //
//////////////////////////////////////////////////////////////////////////
BOOLEAN CHostModbusTcpProcess::GetYTFrame(CHostModbusTcpProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode)
{
int uid;
BYTE result;
BYTE* pData;
if (NULL == pItem) return FALSE;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
if (NULL == pBuf) return FALSE;
pData = pBuf;
if (!GetUnitYT(uid, m_nYTOrder, m_dwYTValue, m_nYTState, result))
{
return FALSE;
}
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is %s result is %s.\n", uid, m_nYTOrder, m_dwYTValue, val_to_str(m_nYTState, yt_state, "STATE = %d"), val_to_str(result, yt_result, "RESULT = %d"));
BYTE* m_param;
BYTE nFun; //功能码
BYTE nSetType; //设置方式 0单寄存器1双寄存器
BOOLEAN nNeedSelect; //遥设需要选择
WORD nReg = 0xffff;
WORD nSelReg, nExecReg, nEscReg; //合闸命令参数
m_param = GetUnitYTParamByPoint(uid, m_nYTOrder);
if (NULL == m_param) return FALSE;
nSetType = m_param[0]; //0 16位整型值;1 32位整型值;2 32位浮点数值;
nFun = m_param[1]; //功能码占一个字节
nNeedSelect = m_param[2]; //遥控是否需要选择
nSelReg = MAKEWORD(m_param[4], m_param[5]); //选择寄存器
nExecReg = MAKEWORD(m_param[6], m_param[7]); //执行寄存器
nEscReg = MAKEWORD(m_param[8], m_param[9]); //撤销寄存器
if (m_nYTState == YTS_SELREQ)
{ //遥设选择
nReg = nSelReg;
if (0xffff == nReg || !nNeedSelect)
{ //寄存器无效,遥设无须选择
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_SELED, YTR_SUCC);
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
return FALSE;
}
else
{
FuncCode = nFun;
frame = MODBUSP_YT_SELECT;
}
}
else if (m_nYTState == YTS_EXEREQ)
{ //遥设执行
nReg = nExecReg;
if (0xffff == nReg) return FALSE;
FuncCode = nFun;
frame = MODBUSP_YT_EXECUTE;
}
else if (m_nYTState == YTS_ABRREQ)
{ //遥设撤销
nReg = nEscReg;
if (0xffff == nReg || !nNeedSelect)
{ //寄存器无效
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC);
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
return FALSE;
}
FuncCode = nFun;
frame = MODBUSP_YT_CANCEL;
}
else if ((m_nYTState == YTS_SELING || m_nYTState == YTS_SELED) && result == YTR_OVER)
{ //遥设撤销
nReg = nEscReg;
if (0xffff == nReg || !nNeedSelect)
{ //寄存器无效
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC);
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
return FALSE;
}
FuncCode = nFun;
frame = MODBUSP_YT_CANCEL;
}
//modify by assouan for clean;
pData[0] = pItem->m_addr;
pData[1] = nFun;
pData[2] = (nReg >> 8) & 0x00ff;
pData[3] = nReg & 0x00ff;
if (nFun == MODBUSC_F06)
{
pData[4] = (m_dwYTValue >> 8) & 0x00ff;
pData[5] = m_dwYTValue & 0x00ff;
count = 6;
}
else if (nFun == MODBUSC_F16)
{
if (nSetType == 0)
{
pData[4] = 0x00;
pData[5] = 0x01;
pData[6] = 0x02;
pData[7] = (m_dwYTValue >> 8) & 0x00ff;
pData[8] = m_dwYTValue & 0x00ff;
count = 9;
}
else if (nSetType == 1)
{
pData[4] = 0x00;
pData[5] = 0x02;
pData[6] = 0x04;
pData[7] = (m_dwYTValue >> 24) & 0x00ff;
pData[8] = (m_dwYTValue >> 16) & 0x00ff;
pData[9] = (m_dwYTValue >> 8) & 0x00ff;
pData[10] = m_dwYTValue & 0x00ff;
count = 11;
}
else if (nSetType == 2)
{
pData[4] = 0x00;
pData[5] = 0x02;
pData[6] = 0x04;
pData[7] = (m_dwYTValue >> 8) & 0x00ff;
pData[8] = m_dwYTValue & 0x00ff;
pData[9] = (m_dwYTValue >> 24) & 0x00ff;
pData[10] = (m_dwYTValue >> 16) & 0x00ff;
count = 11;
}
}
else return FALSE;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
// yt end //
//////////////////////////////////////////////////////////////////////////
BOOLEAN CHostModbusTcpProcess::GetSetTimeFrame(CHostModbusTcpProcessItem *pItem, BYTE* /*pData*/, int& /*count*/)
{
return TRUE;
}
BOOLEAN CHostModbusTcpProcess::GetReadDataFrame(CHostModbusTcpProcessItem *pItem, BYTE* pData, int& count)
{
if (NULL == pItem) return FALSE;
if (m_nFrameType == 0) return FALSE;
if (m_nCurFuncCode == 0) return FALSE;
pData[0] = pItem->m_addr;
pData[1] = (BYTE)m_nCurFuncCode;
pData[2] = (m_nCurBeginReg >> 8) & 0x00ff;
pData[3] = m_nCurBeginReg & 0x00ff;
pData[4] = (m_nCurRegCount >> 8) & 0x00ff;
pData[5] = m_nCurRegCount & 0x00ff;
count = 6;
return TRUE;
}
int CHostModbusTcpProcess::OnPackageReceived(BYTE* pBuf, int count, int ord)
{
int uid;
if (count < 6)
{ //数据长度不足
return 0;
}
CHostModbusTcpProcessItem* pItem;
pItem = (CHostModbusTcpProcessItem *)GetItem(ord);
if (NULL == pItem) return -1;
//头尾判断。
WORD protocol, len;
protocol = MAKEWORD(pBuf[3], pBuf[2]);
len = MAKEWORD(pBuf[5], pBuf[4]);
if (count < len + 6)
{ //数据接收未完
return 0;
}
if (protocol != MB_TCP_PROTOCOL_ID)
{ //未知协议
return -1;
}
BYTE* buffer = &pBuf[6];
if (((buffer[1] & 0x7f) != MODBUSC_F01) && ((buffer[1] & 0x7f) != MODBUSC_F02) &&
((buffer[1] & 0x7f) != MODBUSC_F03) && ((buffer[1] & 0x7f) != MODBUSC_F04) &&
((buffer[1] & 0x7f) != MODBUSC_F05) && ((buffer[1] & 0x7f) != MODBUSC_F06) &&
((buffer[1] & 0x7f) != MODBUSC_F07) && ((buffer[1] & 0x7f) != MODBUSC_F08) &&
((buffer[1] & 0x7f) != MODBUSC_F11) && ((buffer[1] & 0x7f) != MODBUSC_F12) &&
((buffer[1] & 0x7f) != MODBUSC_F15) && ((buffer[1] & 0x7f) != MODBUSC_F16) &&
((buffer[1] & 0x7f) != MODBUSC_F17) && ((buffer[1] & 0x7f) != MODBUSC_F20) &&
((buffer[1] & 0x7f) != MODBUSC_F21) && ((buffer[1] & 0x7f) != MODBUSC_F22) &&
((buffer[1] & 0x7f) != MODBUSC_F23) && ((buffer[1] & 0x7f) != MODBUSC_F24) &&
((buffer[1] & 0x7f) != MODBUSC_F43) && ((buffer[1] & 0x7f) != MODBUSC_F26))
{ //不支持的功能码
return -1;
}
if ((buffer[1] & 0x80) == 0x80)
{ //错误代码
m_nCurFrame = 0;
}
//根据地址查找单元id
uid = GetUnitByAddr(buffer, 1);
if (uid < 0 || uid >= UNIT_NUM) return (len + 6);
int order = GetOrderByUnitID(uid);
if (order < 0 || order >= PROCESS_UNIT_NUM) return (len + 6);
pItem = (CHostModbusTcpProcessItem *)GetItem(order);
if (NULL == pItem) return (len + 6);
if (OnReceiveData(pItem, buffer, (len - 3)))
{
m_nCurFrame = 0;
}
DisplayRxData(pBuf, (len + 6), TRUE, uid);
UnitFeedDog(uid);
return (len + 6);
}
BOOLEAN CHostModbusTcpProcess::OnReceiveData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
{
int uid;
if (NULL == pItem) return FALSE;
uid = pItem->GetUnitID();
if (uid < 0) return FALSE;
UnitFeedDog(uid);
if (pData[1] == m_nCurFuncCode)
{
if (m_nCurFrame == MODBUSP_READ_YX1)
{
return OnReceiveYXData(pItem, &pData[3], count);
}
else if (m_nCurFrame == MODBUSP_READ_YC1)
{
return OnReceiveYCData(pItem, &pData[3], count);
}
else if (m_nCurFrame == MODBUSP_READ_YM1)
{
return OnReceiveYMData(pItem, &pData[3], count);
}
else if (m_nCurFrame == MODBUSP_YK_EXECUTE)
{
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_EXEED, YKR_SUCC);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
return TRUE;
}
else if (MODBUSP_YK_SELECT == m_nCurFrame)
{
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_SELED, YKR_SUCC);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
return TRUE;
}
else if (MODBUSP_YK_CANCEL == m_nCurFrame)
{
SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP"));
return TRUE;
}
else if (MODBUSP_YT_EXECUTE == m_nCurFrame)
{
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_EXEED, YTR_SUCC);
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_EXEED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
return TRUE;
}
else if (MODBUSP_YT_SELECT == m_nCurFrame)
{
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_SELED, YTR_SUCC);
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
return TRUE;
}
else if (MODBUSP_YT_CANCEL == m_nCurFrame)
{
SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC);
vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue);
return TRUE;
}
}
return FALSE;
}
BOOLEAN CHostModbusTcpProcess::OnReceiveYXData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
{
int uid;
int i, j;
int point;
BYTE param[4];
WORD reg;
BOOLEAN yxVal;
if (pItem == NULL) return FALSE;
uid = pItem->GetUnitID();
if (uid < 0) return FALSE;
reg = m_nCurBeginReg;
param[0] = m_nCurFuncCode;
if (MODBUSC_F03 == m_nCurFuncCode || MODBUSC_F04 == m_nCurFuncCode)
{ //03功能码读取Holdings
WORD nValue;
WORD nTemp = 0x0001;
for (i = 0; i < count; i += 2)
{
nValue = (pData[i] << 8) | pData[i+1];
nTemp = 0x0001;
param[1] = LOBYTE(reg);
param[2] = HIBYTE(reg);
reg++;
for (j = 0; j < 16; j++)
{
param[3] = j;
point = GetUnitYXPointByParam(uid, param, 4);
if (point >= 0)
{
yxVal = SPI_OFF;
if ((nValue) & nTemp)
{
yxVal = SPI_ON;
}
SetUnitYX(uid, point, yxVal);
}
nTemp <<= 1;
}
}
}
else if (MODBUSC_F01 == m_nCurFuncCode || MODBUSC_F02 == m_nCurFuncCode)
{ //01 02功能码读取Coils和Status
BYTE *nValue = pData;
BYTE nTemp = 0x01;
for (i = 0; i < count; i++)
{
nTemp = 0x01;
for (j = 0; j < 8; j++)
{
param[1] = LOBYTE(reg);
param[2] = HIBYTE(reg);
reg++;
point = GetUnitYXPointByParam(uid, param, 3);
if (point >= 0)
{
yxVal = SPI_OFF;
if ((*nValue) & nTemp)
{
yxVal = SPI_ON;
}
SetUnitYX(uid, point, yxVal);
}
nTemp <<= 1;
}
nValue++;
}
}
return TRUE;
}
BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
{
int uid;
int i;
BYTE* pBuf;
BYTE* pParam;
BYTE param[8];
DWORD nValue = 0;
LONG bin_value;
float f_val;
int point;
WORD reg;
BYTE reg_count, value_type, sign_mark;
if (pItem == NULL) return FALSE;
uid = pItem->GetUnitID();
if (uid < 0) return FALSE;
pBuf = pData;
reg = m_nCurBeginReg;
param[0] = m_nCurFuncCode;
for (i = 0; i < count;)
{
param[1] = LOBYTE(reg);
param[2] = HIBYTE(reg);
point = GetUnitYCPointByParam(uid, param, 3);
if (point >= 0)
{ //获得合法点号
pParam = GetUnitYCParamByPoint(uid, point);
if (pParam != NULL)
{
reg_count = pParam[3];
value_type = pParam[4];
sign_mark = pParam[5];
if ((1 == reg_count) && (2 == value_type))
{ //16位归一化值
if (2 == value_type)
{
if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]);
else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]);
SetUnitYC(uid, point, (LONG)nValue);
}
else if (8 == value_type)
{
if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]);
else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]);
nValue = bcd_to_int((const BYTE*)&nValue, sizeof(WORD));
SetUnitYC(uid, point, (LONG)nValue);
}
pBuf += 2; i += 2; reg++;
}
else if (2 == reg_count)
{ //32位测量值
if (0 == value_type)
{ //浮点数,高位在第一个寄存器
nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]);
memcpy(&f_val, &nValue, 4);
SetUnitYC(uid, point, f_val);
//nValue = (DWORD)(f_val * 1000);
}
else if (1 == value_type)
{
nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]);
memcpy(&f_val, &nValue, 4);
SetUnitYC(uid, point, f_val);
//nValue = (DWORD)(f_val * 1000);
}
else if (3 == value_type)
{ //归一化值,高位在第一个寄存器
nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]);
SetUnitYC(uid, point, (LONG)nValue);
}
else if (4 == value_type)
{ //归一化值,高位在第二个寄存器
nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]);
SetUnitYC(uid, point, (LONG)nValue);
}
else if (5 == value_type)
{
nValue = (DWORD)(pBuf[3] << 24 | pBuf[2] << 16 | pBuf[1] << 8 | pBuf[0]);
memcpy(&f_val, &nValue, 4);
SetUnitYC(uid, point, f_val);
}
else if (6 == value_type)
{ //32位bcd数据高位在第一个寄存器
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
bin_value = (LONG)bcd_to_int((const BYTE*)&nValue, sizeof(DWORD));
SetUnitYC(uid, point, bin_value);
}
else if (7 == value_type)
{ //32位bcd数据高位在第二个寄存器
nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]);
bin_value = (LONG)bcd_to_int((const BYTE*)&nValue, sizeof(DWORD));
SetUnitYC(uid, point, bin_value);
}
pBuf += 4; i += 4; reg += 2;
}
}
}
else
{
pBuf += 2; i += 2; reg++;
}
}
return TRUE;
}
BOOLEAN CHostModbusTcpProcess::OnReceiveYMData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count)
{
int i;
int point;
int uid;
BYTE* pBuf;
BYTE* pParam;
BYTE nParam[4];
BYTE value_type;
WORD reg;
DWORD nValue = 0;
float f_val;
DWORD dw[2]; //双精度转换中间变量
double d_val;
DWORD bin_value;
if (pItem == NULL) return FALSE;
uid = pItem->GetUnitID();
if (uid < 0) return FALSE;
pBuf = pData;
reg = m_nCurBeginReg;
nParam[0] = m_nCurFuncCode;
for (i = 0; i < count; )
{
nParam[1] = LOBYTE(reg);
nParam[2] = HIBYTE(reg);
point = GetUnitYMPointByParam(uid, nParam, 3);
if (point >= 0)
{ //获得有效点号
pParam = GetUnitYMParamByPoint(uid, point);
if (NULL != pParam)
{ //获得有效参数
value_type = pParam[4];
if (0 == value_type)
{ //16位无符号整型
nValue = (pBuf[0] << 8) | pBuf[1];
SetUnitYM(uid, point, nValue);
pBuf += 2; i += 2; reg++;
}
else if (1 == value_type)
{ //32位无符号整型高位在第一个寄存器
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
SetUnitYM(uid, point, nValue);
pBuf += 4; reg += 2; i += 4;
}
else if (2 == value_type)
{ //32位整型高位在第一个寄存器
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
SetUnitYM(uid, point, nValue);
pBuf += 4; reg += 2; i += 4;
}
else if (3 == value_type)
{ //32位无符号整型高位在第二个寄存器
nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
SetUnitYM(uid, point, nValue);
pBuf += 4; reg += 2; i += 4;
}
else if (4 == value_type)
{ //32位整型高位在第二个寄存器
nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
SetUnitYM(uid, point, nValue);
pBuf += 4; reg += 2; i += 4;
}
else if (5 == value_type)
{ //32位浮点数高位在第一个寄存器
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
memcpy(&f_val, &nValue, 4);
SetUnitYM(uid, point, (DWORD)f_val);
pBuf += 4; reg += 2; i += 4;
}
else if (6 == value_type)
{ //32位浮点数高位在第二个寄存器
nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
memcpy(&f_val, &nValue, 4);
SetUnitYM(uid, point, (DWORD)f_val);
pBuf += 4; reg += 2; i += 4;
}
else if (7 == value_type)
{ //64位浮点数高位在第一个寄存器
dw[1] = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
dw[0] = (DWORD)((pBuf[6] << 24) | (pBuf[7] << 16) | (pBuf[4] << 8) | pBuf[5]);
memcpy(&d_val, dw, 8);
SetUnitYM(uid, point, (DWORD)(d_val));
pBuf += 8; reg += 4; i += 8;
}
else if (8 == value_type)
{
dw[0] = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]);
dw[1] = (DWORD)((pBuf[6] << 24) | (pBuf[7] << 16) | (pBuf[4] << 8) | pBuf[5]);
memcpy(&d_val, dw, 8);
SetUnitYM(uid, point, (DWORD)(d_val));
pBuf += 8; reg += 4; i += 8;
}
else if (9 == value_type)
{
nValue = (DWORD)((pBuf[3] << 24) | (pBuf[2] << 16) | (pBuf[1] << 8) | pBuf[0]);
memcpy(&f_val, &nValue, 4);
SetUnitYM(uid, point, (DWORD)(f_val * 10));
pBuf += 4; reg += 2; i += 4;
}
else if (10 == value_type)
{ //32位bcd数据
nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]);
bin_value = bcd_to_int((const BYTE*)&nValue, sizeof(DWORD));
SetUnitYM(uid, point, bin_value);
pBuf += 4; reg += 2; i += 4;
}
else
{ //无配置
pBuf += 2; reg++; i += 2;
}
}
}
else
{
pBuf += 2; i += 2; reg++;
}
}
return TRUE;
}