deleted 101/104

This commit is contained in:
zhouhuang 2024-10-14 20:27:48 +08:00
parent a15ddd6b75
commit b497f4cbdb
8 changed files with 0 additions and 4934 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,474 +0,0 @@
#ifndef _ZJD_SUB_GDW104_PROCESS_H_
#define _ZJD_SUB_GDW104_PROCESS_H_
#include "iec104.h"
#include "sqlite/KompexSQLitePrerequisites.h"
#include "sqlite/KompexSQLiteDatabase.h"
#include "sqlite/KompexSQLiteStatement.h"
#include "sqlite/KompexSQLiteException.h"
#include "sqlite/KompexSQLiteStreamRedirection.h"
#include "sqlite/KompexSQLiteBlob.h"
#include <dirent.h>
#include <sys/stat.h>
#include <string>
using namespace Kompex;
#define FILE_PATH_LEN 64
#define MAX_FILEDATA_LEN 200
#define EPS 1e-7
#pragma pack(1)
typedef struct
{
struIEC104Option iec104;
char soeDir[FILE_PATH_LEN];
char coDir[FILE_PATH_LEN];
char fixptDir[FILE_PATH_LEN];
char exvDir[FILE_PATH_LEN];
char frzDir[FILE_PATH_LEN];
char flowrevDir[FILE_PATH_LEN];
char ulogDir[FILE_PATH_LEN];
} struGDW104Option;
#pragma pack()
typedef struct
{
time_t datetime;
float fMaxVal;
float fMinVal;
float fCoef;
float fBase;
int iMaxVal;
int iMinVal;
int MaxTime;
int MinTime;
int iCurVal;
} STRUCT_YCEXTREMUM;
typedef struct
{
time_t datetime;
float fCoef;
float fBase;
float fCurVal;
int iCurVal;
} STRUCT_FMRECORD;
typedef struct
{
int count;
std::string ss_outmax;
std::string ss_outmin;
} STRUCT_FILEBUFFER;
#if 1
#define CMD_GET_SOE_INFO 1
#define CMD_GET_CO_INFO (1 << 1)
#define CMD_GET_EXV_INFO (1 << 2)
#define CMD_GET_FIXPT_INFO (1 << 3)
#define CMD_GET_FRZ_INFO (1 << 4)
#define CMD_GET_FLOWREV_INFO (1 << 5)
#define CMD_GET_ULOG_INFO (1 << 6)
#define CMD_GET_FILE_INFO (1 << 7)
#define CMD_READ_FILE (1 << 8)
#define CMD_GET_DIR_INFO (1 << 9)
#define FIOCMD_IDLE 0
#define FIOCMD_CREATE_FILE 1
#define FIOCMD_OPEN_FILE 2
#define FIOCMD_GET_FILEINFO 3
#define FIOCMD_DEL_FILE 4
#define FIOCMD_MAKE_DIR 5
#define FIOCMD_REMOVE_DIR 6
#define FIOCMD_OPEN_DIR 7
#define FIOCMD_READ_FILE 8
#define FIOCMD_WRITE_FILE 9
#define FIOCMD_READ_DIR 10
#define FIOCMD_CLOSE_FILE 11
#define FIOCMD_CLOSE_DIR 12
#define FIOCMD_VALID 0x7fffffff
#define CMD_EXEC_ERR 0x80000000
typedef struct
{
std::string st_name;
struct stat st_st;
} struFileStat;
typedef std::vector<struFileStat> vecFileStat;
class CGDW104FileProcess
{
private:
DWORD last_sec;
int m_uid;
int m_information_address_length;
int m_yx_information_address_start;
int m_yc_information_address_start;
int m_ym_information_address_start;
SQLiteDatabase m_database;
struUnitStatic m_unit;
FILE* m_pFileHandle;
BYTE m_fileBuffer[256];
LONG m_nFilePos;
LONG m_nFileLength;
LONG m_nReadLen;
public:
CGDW104FileProcess()
{
m_pFileHandle = NULL;
m_nFilePos = 0;
m_nReadLen = 0;
m_nFileLength = 0;
m_nCmdID = 0;
m_bWr = FALSE;
m_soe_save = 0;
m_soe_load = 0;
m_yklog_save = 0;
m_yklog_load = 0;
m_uid = -1;
m_bCallAllFile = FALSE;
last_sec = 0;
m_last_day = -1;
m_nCmdIDConfirm = 0;
m_information_address_length = 3;
m_yx_information_address_start = IEC_101_104_YX_START_ADDR;
m_yc_information_address_start = IEC_101_104_YC_START_ADDR;
m_ym_information_address_start = IEC_101_104_YM_START_ADDR;
};
virtual ~CGDW104FileProcess()
{
SaveMapToFile();
if (m_pUnitYM)
{
delete [] m_pUnitYM;
m_pUnitYM = NULL;
}
m_database.SaveDatabaseFromMemoryToFile("./gdw104.db");
fprintf(stderr, "SaveDatabaseFromMemoryToFile finished.\n");
if (m_pFileHandle)
{
fclose(m_pFileHandle);
m_pFileHandle = NULL;
}
};
BOOLEAN OnCreate(int, const void*, const void*);
BOOLEAN OnTimer(void);
private:
struSOE m_soes[DATABASE_SOE_NUM];
int m_soe_save;
int m_soe_load;
struYKLog m_yklogs[DATABASE_YK_LOG_NUM];
int m_yklog_save;
int m_yklog_load;
BOOLEAN m_bWr;
DWORD m_nCmdID;
DWORD m_nCmdIDConfirm;
std::string m_pathName;
vecFileStat m_vecFileStat;
std::string str_SOERecordDir;
std::string str_coRecordDir;
std::string str_exvRecordDir;
std::string str_fixptRecordDir;
std::string str_frzRecordDir;
std::string str_flowrevRecordDir;
std::string str_ulogRecordDir;
BOOLEAN m_bCallAllFile;
time_t m_start_time;
time_t m_end_time;
WORD m_last_day;
struUnitYM *m_pUnitYM;
LONG m_total_ym;
std::map<int, STRUCT_YCEXTREMUM> mapYcExetremumRecordDatas;
std::map<int, STRUCT_FMRECORD> mapFmHisRecordDatas;
BOOLEAN SaveMapToFile(void);
BOOLEAN LoadMapFromFile(int);
BYTE GetCheckSum8(BYTE* pData, int count);
int ReadDir(const char* pathName)
{
DIR *dir; // 定义目录指针
struct dirent *dir_info; // 定义目录结构体
m_vecFileStat.clear();
char buf[260]; // 用于存放文件路径
struFileStat filestat;
if ((dir = opendir(pathName)) == NULL)
{ // 打开目录
vLog(LOG_ERROR, "打开文件目录:%s失败<%d,%s>\n", pathName, errno, strerror(errno));
return -1;
}
while ((dir_info = readdir(dir)) != NULL)
{ // 读取目录下文件列表
if (dir_info->d_name[0] == '.')
{ // 过滤掉 '.' 和 '..'
continue;
}
// 获取文件全路径,并打印
sprintf(buf, "%s/%s", pathName, dir_info->d_name);
//获取文件属性
if (stat(buf, &filestat.st_st) != 0)
{
vLog(LOG_ERROR, "获取文件%s属性失败<%d,%s>\n", buf, errno, strerror(errno));
continue;
}
filestat.st_name = buf;
m_vecFileStat.push_back(filestat);
}
closedir(dir); // 关闭目录
return m_vecFileStat.size();
}
int mkLogDir(const char* pathName)
{
if (access(pathName, F_OK) == 0) return 0;
// 创建目录
if (mkdir(pathName, 0777) == -1)
{
vLog(LOG_ERROR, "创建文件夹 %s失败<%d,%s>\r\n", pathName, errno, strerror(errno));
return -1;
}
return 1;
}
void delete_files_in_dir(const char*);
void DumpSOE(void);
void DumpYKLog(void);
void UpdateExtremumRecord(BOOLEAN);
void DumpYCHisRecord(LONG);
void DumpFmHisRecord(LONG);
void createSOEFile(void);
void createYKLogFile(void);
void createExtremumRecordFile(void);
void createYCHisRecordFile(void);
void createFmHisRecordFile(void);
public:
void AddFmRecord(struUnitYM* yms, int count)
{
memcpy(m_pUnitYM, yms, sizeof(struUnitYM) * count);
}
void AddExtremumRecord(int point, LONG value)
{
if (mapYcExetremumRecordDatas.find(point) == mapYcExetremumRecordDatas.end()) return;
LONG maxVal = mapYcExetremumRecordDatas[point].iMaxVal;
LONG minVal = mapYcExetremumRecordDatas[point].iMinVal;
if (value > maxVal)
{
mapYcExetremumRecordDatas[point].fMaxVal = value * mapYcExetremumRecordDatas[point].fCoef + mapYcExetremumRecordDatas[point].fBase;
mapYcExetremumRecordDatas[point].iMaxVal = value;
mapYcExetremumRecordDatas[point].MaxTime = system32.timers;
}
if (value < minVal)
{
mapYcExetremumRecordDatas[point].fMinVal = value * mapYcExetremumRecordDatas[point].fCoef + mapYcExetremumRecordDatas[point].fBase;
mapYcExetremumRecordDatas[point].iMinVal = value;
mapYcExetremumRecordDatas[point].MinTime = system32.timers;
}
mapYcExetremumRecordDatas[point].iCurVal = value;
}
void PushSOE(unionCP56Time& st, int order, BOOLEAN value, BYTE qds, int uid = -1, int point = -1)
{
m_soes[m_soe_save].st.year = st.year;
m_soes[m_soe_save].st.month = st.month;
m_soes[m_soe_save].st.dayofmonth = st.dayofmonth;
m_soes[m_soe_save].st.dayofweek = st.dayofweek;
m_soes[m_soe_save].st.hour = st.hour;
m_soes[m_soe_save].st.minute = st.minute;
m_soes[m_soe_save].st.millisecond = st.millisecond;
if (order < 0 || order >= DATABASE_YX_NUM)
{
m_soes[m_soe_save].order = -1;
}
else
{
m_soes[m_soe_save].order = order;
}
m_soes[m_soe_save].value = value;
m_soes[m_soe_save].uid = uid;
m_soes[m_soe_save].point = point;
m_soes[m_soe_save].qds = qds;
m_soe_save++;
m_soe_save = m_soe_save % DATABASE_SOE_NUM;
}
void PushYKLog(unionCP56Time& st, int point, BOOLEAN value, BYTE type, BYTE source = -1, int uid = -1)
{
m_yklogs[m_yklog_save].st.year = st.year;
m_yklogs[m_yklog_save].st.month = st.month;
m_yklogs[m_yklog_save].st.dayofmonth = st.dayofmonth;
m_yklogs[m_yklog_save].st.dayofweek = st.dayofweek;
m_yklogs[m_yklog_save].st.hour = st.hour;
m_yklogs[m_yklog_save].st.minute = st.minute;
m_yklogs[m_yklog_save].st.millisecond = st.millisecond;
m_yklogs[m_yklog_save].point = point;
m_yklogs[m_yklog_save].value = value;
m_yklogs[m_yklog_save].type = type;
m_yklogs[m_yklog_save].source = source;
m_yklogs[m_yklog_save].uid = uid;
m_yklog_save++;
m_yklog_save = m_yklog_save % DATABASE_YK_LOG_NUM;
}
void ReadDir(const char* dirName, BOOLEAN callAllFile, unionCP56Time st, unionCP56Time et)
{
m_nCmdID = FIOCMD_READ_DIR;
m_pathName = dirName;
m_bCallAllFile = callAllFile;
m_start_time = unionCP56TimetoTime_t(&st);
m_end_time = unionCP56TimetoTime_t(&et);
}
void OpenFile(const char* filename, bool bWr = FALSE)
{
m_nCmdID = FIOCMD_OPEN_FILE;
m_pathName = filename;
m_bWr = bWr;
}
void CloseFile()
{
m_nCmdID = FIOCMD_CLOSE_FILE;
}
void ReadFile()
{
m_nCmdID = FIOCMD_READ_FILE;
}
DWORD getCMD(void)
{
DWORD result = m_nCmdIDConfirm;
m_nCmdIDConfirm = 0;
return result;
}
int FileData(BYTE* pData)
{
ValToBuf(pData, m_nFilePos, 4); pData+= 4;
if (FileLeftLength() <= 0)
{
*pData = 0; pData++;
}
else
{
*pData = 1; pData++;
ReadFile();
}
memcpy(pData, m_fileBuffer, m_nReadLen); pData += m_nReadLen;
*pData = GetCheckSum8(m_fileBuffer, m_nReadLen);
m_nFilePos += m_nReadLen;
return (m_nReadLen + 6);
}
LONG FilePos(void) const
{
return m_nFilePos;
}
LONG FileLeftLength(void) const
{
return (m_nFileLength - m_nFilePos);
}
int FileCount(void) const
{
return m_vecFileStat.size();
}
std::string FileName(int order) const
{
if (order >= (int)m_vecFileStat.size()) return NULL;
return m_vecFileStat[order].st_name;
}
LONG FileLength(int order) const
{
if (order >= (int)m_vecFileStat.size()) return -1;
return m_vecFileStat[order].st_st.st_size;
}
time_t FileTime(int order) const
{
if (order >= (int)m_vecFileStat.size()) return -1;
return m_vecFileStat[order].st_st.st_atime;
}
LONG FileLength(std::string name) const
{
for (int i = 0; i < (int)m_vecFileStat.size(); i++)
{
if (name == m_vecFileStat[i].st_name)
{
return m_vecFileStat[i].st_st.st_size;
}
}
return -1;
}
time_t FileTime(std::string name) const
{
for (int i = 0; i < (int)m_vecFileStat.size(); i++)
{
if (name == m_vecFileStat[i].st_name)
{
return m_vecFileStat[i].st_st.st_atime;
}
}
return -1;
}
};
#endif
typedef struct
{
char dirname[FILE_PATH_LEN];
char filename[FILE_PATH_LEN];
LONG loadptr;
DWORD dirID;
DWORD length;
BOOLEAN allfile;
BYTE ret_val;
} stCallFileDir;
class CSubGDW104Process : public CIEC104Process
{
private:
CGDW104FileProcess m_gdwFile;
struGDW104Option gdw_option;
DWORD m_dwFileType;
stCallFileDir m_FileDir;
public:
CSubGDW104Process();
virtual ~CSubGDW104Process();
BOOLEAN OnPreCreate(int);
BOOLEAN OnCreated(int);
BOOLEAN Run(void);
BOOLEAN OnTimer(void);
BOOLEAN FetchUnitYC(int);
BOOLEAN FetchUnitYM(int);
public:
void GetItemEvents(CIEC104ProcessItem*);
public:
int MakeYKFrame(CIEC104ProcessItem*, int);
int MakeYTFrame(CIEC104ProcessItem*, int);
int MakeFileFrame(CIEC104ProcessItem*, int);
BOOLEAN OnUFrameReceived(BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN, int);
BOOLEAN OnIFrameReceived(WORD, WORD, BYTE*, int, int);
int Receive_Single_command(CIEC104ProcessItem*, const BYTE*, BYTE, BYTE*, int&); //单点令
int Receive_Double_command(CIEC104ProcessItem*, const BYTE*, BYTE, BYTE*, int&); //单点令
int Receive_Set_point_command_normalized(CIEC104ProcessItem*, const BYTE*, BYTE, BYTE*, int&); //设定规一化值命令
int Receive_Set_point_command_scaled(CIEC104ProcessItem*, const BYTE*, BYTE, BYTE*, int&); //设定标度化值命令
int Receive_Set_point_command_short_floating(CIEC104ProcessItem*, const BYTE*, BYTE, BYTE*, int&); //设定短浮点值命令
int Receive_FileTrans(CIEC104ProcessItem*, const BYTE*, BYTE); //读取文件
BOOLEAN parseFileReadDirAct(CIEC104ProcessItem*, const BYTE*);
BOOLEAN parseFileReadFileSelAct(CIEC104ProcessItem*, const BYTE*);
BOOLEAN parseFileReadFileDataCon(CIEC104ProcessItem*, const BYTE*);
int Send_CallFileDir_Confirm(CIEC104ProcessItem*, DWORD, int);
int Send_FileDir(CIEC104ProcessItem*, BOOLEAN, BOOLEAN, int, int, int);
int Send_CallFileSel_Confirm(CIEC104ProcessItem*, DWORD, int);
int Send_CallFileDat_Ack(CIEC104ProcessItem*, DWORD, int);
};
#endif //_ZJD_SUB_GDW104_PROCESS_H_

View File

@ -1,241 +0,0 @@
#include "sub_iec101_balanced.h"
/***************************************************************************************/
BOOLEAN CIEC101SecondaryBalancedProcess::OnPreCreate(int id)
{
if (!CIEC101Process::OnPreCreate(id)) return FALSE;
int i;
int uid;
CIEC101SecondaryBalancedProcessItem* pItem;
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC101SecondaryBalancedProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
BYTE phy_addr[2];
GetUnitAddr(uid, phy_addr, 2);
pItem->Attach(uid, phy_addr[0], phy_addr[0], m_option.originatorAddress); //默认公共地址和物理地址一致
pItem->setAppLayerParameters(m_option.sizeOfCOT, m_option.sizeOfCA, m_option.sizeOfIOA, m_option.maxSizeOfASDU);
Slave_setLinkLayerAddressOtherStation(pItem, phy_addr[1]);
pItem->setAppLayerIOABase();
pItem->setAppLayerDataCount(GetUnitYXCount(uid), GetUnitYCCount(uid), GetUnitYMCount(uid));
}
last_sec != (time_t)system32.timers;
return TRUE;
}
BOOLEAN CIEC101SecondaryBalancedProcess::Run(void)
{
if (!CIEC101Process::Run()) return FALSE;
FeedDog();
CIEC101ProcessItem* pItem = (CIEC101ProcessItem *)GetCurItem();
LinkLayerPrimaryBalanced_runStateMachine(pItem);
return TRUE;
}
BOOLEAN CIEC101SecondaryBalancedProcess::OnTimer(void)
{
if (!CIEC101Process::OnTimer()) return FALSE;
BOOLEAN sec_changed = FALSE;
if (last_sec != (time_t)system32.timers)
{
last_sec = (time_t)system32.timers;
sec_changed = TRUE;
}
CIEC101ProcessItem* pItem = (CIEC101ProcessItem *)GetCurItem();
if (NULL == pItem) return TRUE;
int uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return TRUE;
//刷新事件记录库
GetItemEvents(pItem);
//刷新遥测库
FetchUnitYC(0);
if (pItem->interrogation_finish)
{
//总召唤结束,开始上送遥信变位
GetItemYXBWs(pItem);
//总召唤结束,开始刷新遥测变位缓冲。
if (pItem->ycbws.count <= 0)
{ //当遥测变位发送结束后才更新
GetItemYCBWs(pItem);
}
//发送遥控返校
if (MakeYKFrame(pItem)) return TRUE;
if (MakeYTFrame(pItem)) return TRUE;
if (Send_Single_point_information(pItem)) return TRUE;
if (Send_Single_point_information_with_time_tag_cp56time2a(pItem)) return TRUE;
if (!pItem->interrogation_start)
{ //变位遥测优先级在总召唤之后。
if (sec_changed)
{
switch (m_option.yc_type)
{
case USE_YC_NB: //标度化值
return Send_Measured_value_scaled(pItem);
case USE_YC_NC: //短浮点数
return Send_Measured_value_short_floating_point(pItem);
case USE_YC_ND: //不带品质归一化值
return Send_Measured_value_normalised_without_quality(pItem);
default: //USE_YC_NA: 归一化值
return Send_Measured_value_normalised(pItem);
}
}
}
}
//响应总召唤命令
if (pItem->interrogation_start)
{
if (pItem->call_type != IEC_101_104_COT_INTERROGATION)
{ //组召唤
//激活终止
Send_FrameInterrogation(pItem);
pItem->call_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
}
else if (!pItem->interrogation_yx_fin)
{
Send_Single_point_information(pItem, IEC_101_104_COT_INTERROGATION);
}
else if (!pItem->interrogation_yc_fin)
{
switch (m_option.yc_type)
{
case USE_YC_NB: //标度化值
return Send_Measured_value_scaled(pItem, IEC_101_104_COT_INTERROGATION);
case USE_YC_NC: //短浮点数
return Send_Measured_value_short_floating_point(pItem, IEC_101_104_COT_INTERROGATION);
case USE_YC_ND: //不带品质归一化值
return Send_Measured_value_normalised_without_quality(pItem, IEC_101_104_COT_INTERROGATION);
default: //USE_YC_NA: 归一化值
return Send_Measured_value_normalised(pItem, IEC_101_104_COT_INTERROGATION);
}
}
else
{
Send_FrameInterrogation(pItem);
pItem->call_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
}
}
else if (pItem->pulse_start)
{
if (!pItem->pulse_fin)
{
Send_Integrated_totals(pItem, IEC_101_104_COT_REQCOGEN);
}
else
{
Send_FrameCounterInterrogation(pItem);
pItem->call_type = 0;
pItem->pulse_start = FALSE;
pItem->pulse_fin = TRUE;
}
}
return TRUE;
}
//平衡方式从协议接收到主站报文
void CIEC101SecondaryBalancedProcess::LinkLayerSecondaryBalanced_ReceivedMessage(BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, int address, BYTE* msg, int userDataStart, int userDataLength)
{
CIEC101ProcessItem* pItem;
if (address == -1) pItem = (CIEC101ProcessItem *)GetCurItem();
else
{
int uid = GetUnitByAddr((BYTE *)&address, m_linkLayer.linkLayerParameters.addressLength);
if (uid < 0 || uid >= UNIT_NUM) return;
pItem = (CIEC101ProcessItem *)GetItem(GetOrderByUnitID(uid));
UnitFeedDog(uid);
}
if (pItem == NULL)
{
vLog(LOG_DEBUG, "PLL RECV - response from unknown slave %i\n", address);
return;
}
pIEC101_LinkLayerSecondaryBalanced self = &(pItem->secondaryLinkBalanced);
if (fcv)
{
if (LinkLayerSecondaryBalanced_checkFCB(self, fcb) == FALSE) return;
}
switch (fc)
{
case LL_FC_00_RESET_REMOTE_LINK:
//vLog(LOG_DEBUG, "SLL - RECV FC 00 - RESET REMOTE LINK\n");
self->expectedFcb = TRUE;
//vLog(LOG_DEBUG, "SLL - SEND FC 00 - ACK\n");
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, m_linkLayer.dir, FALSE, FALSE);
}
break;
case LL_FC_02_TEST_FUNCTION_FOR_LINK:
//vLog(LOG_DEBUG, "SLL - RECV FC 02 - TEST FUNCTION FOR LINK\n");
//vLog(LOG_DEBUG, "SLL - SEND FC 00 - ACK\n");
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, m_linkLayer.dir, FALSE, FALSE);
}
break;
case LL_FC_03_USER_DATA_CONFIRMED:
//vLog(LOG_DEBUG, "SLL - RECV FC 03 - USER DATA CONFIRMED\n");
if (userDataLength > 0)
{
if (ApplicationLayer_ReceivedData(pItem, msg, isBroadcast, userDataStart, userDataLength))
{
//vLog(LOG_DEBUG, "SLL - SEND FC 00 - ACK\n");
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, m_linkLayer.dir, FALSE, FALSE);
}
}
}
break;
case LL_FC_04_USER_DATA_NO_REPLY:
//vLog(LOG_DEBUG, "SLL -FC 04 - USER DATA NO REPLY\n");
if (userDataLength > 0)
{
ApplicationLayer_ReceivedData(pItem, msg, isBroadcast, userDataStart, userDataLength);
}
break;
case LL_FC_09_REQUEST_LINK_STATUS:
//vLog(LOG_DEBUG, "SLL - RECV FC 09 - REQUEST LINK STATUS");
//vLog(LOG_DEBUG, "SLL - SEND FC 11 - STATUS OF LINK\n");
SendFixedFrame(LL_FC_11_STATUS_OF_LINK_OR_ACCESS_DEMAND, pItem->address, FALSE, m_linkLayer.dir, FALSE, FALSE);
break;
default:
//vLog(LOG_DEBUG, "SLL - UNEXPECTED LINK LAYER MESSAGE");
//vLog(LOG_DEBUG, "SLL - SEND FC 15 - SERVICE NOT IMPLEMENTED\n");
SendFixedFrame(LL_FC_15_SERVICE_NOT_IMPLEMENTED, pItem->address, FALSE, m_linkLayer.dir, FALSE, FALSE);
break;
}
}

View File

@ -1,63 +0,0 @@
#ifndef _ZJD_SUB_IEC101_BALANCED_PROCESS_H_
#define _ZJD_SUB_IEC101_BALANCED_PROCESS_H_
#include "iec101.h"
class CIEC101SecondaryBalancedProcessItem : public CIEC101ProcessItem
{
public:
CIEC101SecondaryBalancedProcessItem() {};
virtual ~CIEC101SecondaryBalancedProcessItem() {};
public:
void Attach(int uid, int physicsAddress = 0, int commonAddress = 0, int originatorAddress = 0)
{
CIEC101ProcessItem::Attach(uid, physicsAddress, commonAddress, m_originatorAddress);
primaryLinkBalanced.otherStationAddress = physicsAddress;
common_address = commonAddress;
applicationlParameters.originatorAddress = originatorAddress;
}
void setAppLayerDataCount(int yx = 0, int yc = 0, int ym = 0)
{
total_yx = yx;
total_yc = yc;
total_ym = ym;
yx_pos = 0;
yc_pos = 0;
ym_pos = 0;
}
};
class CIEC101SecondaryBalancedProcess : public CIEC101SecondaryProcess
{
public:
CIEC101SecondaryBalancedProcess() {m_linkLayer.mode = llSecBalanced;};
virtual ~CIEC101SecondaryBalancedProcess() {};
BOOLEAN OnPreCreate(int id);
BOOLEAN Run(void);
BOOLEAN OnTimer(void);
CIEC101ProcessItem *CreateItem(int ord)
{
return dynamic_cast<CIEC101ProcessItem *>(new CIEC101SecondaryBalancedProcessItem);
}
void Slave_setLinkLayerAddressOtherStation(CIEC101ProcessItem* pItem, int address)
{
pItem->address = address;
}
private:
BOOLEAN LinkLayerSecondaryBalanced_checkFCB(pIEC101_LinkLayerSecondaryBalanced self, BOOLEAN fcb)
{
if (fcb != self->expectedFcb)
{
//vLog(LOG_DEBUG, "ERROR: Frame count bit (FCB) invalid!\n");
/* TODO change link status */
return FALSE;
}
self->expectedFcb = !(self->expectedFcb);
return TRUE;
}
virtual void LinkLayerSecondaryBalanced_ReceivedMessage(BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, int address, BYTE* msg, int userDataStart, int userDataLength);
};
#endif // _ZJD_SUB_IEC101_BALANCED_PROCESS_H_

View File

@ -1,404 +0,0 @@
#include "sub_iec101_unbalanced.h"
/***************************************************************************************/
BOOLEAN CIEC101SecondaryUnbalancedProcess::OnPreCreate(int id)
{
if (!CIEC101Process::OnPreCreate(id)) return FALSE;
int i;
int uid;
CIEC101SecondaryUnbalancedProcessItem* pItem;
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC101SecondaryUnbalancedProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
BYTE phy_addr[2];
GetUnitAddr(uid, phy_addr, 2);
pItem->Attach(uid, phy_addr[0], phy_addr[0], m_option.originatorAddress); //默认公共地址和物理地址一致
pItem->setAppLayerParameters(m_option.sizeOfCOT, m_option.sizeOfCA, m_option.sizeOfIOA, m_option.maxSizeOfASDU);
Slave_setLinkLayerAddressOtherStation(pItem, phy_addr[1]);
pItem->setAppLayerIOABase();
pItem->setAppLayerDataCount(GetUnitYXCount(uid), GetUnitYCCount(uid), GetUnitYMCount(uid));
}
last_sec = (time_t)system32.timers;
return TRUE;
}
BOOLEAN CIEC101SecondaryUnbalancedProcess::Run(void)
{
if (!CIEC101Process::Run()) return FALSE;
FeedDog();
if (m_state != LL_STATE_IDLE)
{
if ((getTimeInMs() - m_lastReceivedMsg) > (unsigned int) m_idleTimeout)
{
llsu_setState(LL_STATE_IDLE);
}
}
return TRUE;
}
BOOLEAN CIEC101SecondaryUnbalancedProcess::OnTimer(void)
{
if (!CIEC101Process::OnTimer()) return FALSE;
BOOLEAN sec_changed = FALSE;
if (last_sec != (time_t)system32.timers)
{
last_sec = (time_t)system32.timers;
sec_changed = TRUE;
}
CIEC101ProcessItem* pItem = (CIEC101ProcessItem *)GetCurItem();
if (NULL == pItem) return TRUE;
int uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return TRUE;
//刷新事件记录库
GetItemEvents(pItem);
//刷新遥测库
FetchUnitYC(0);
if (pItem->interrogation_finish)
{
//总召唤结束,开始上送遥信变位
GetItemYXBWs(pItem);
//总召唤结束,开始刷新遥测变位缓冲。
if (pItem->ycbws.count <= 0)
{ //当遥测变位发送结束后才更新
GetItemYCBWs(pItem);
}
//发送遥控返校
if (MakeYKFrame(pItem)) return TRUE;
if (MakeYTFrame(pItem)) return TRUE;
if (Send_Single_point_information(pItem)) return TRUE;
if (Send_Single_point_information_with_time_tag_cp56time2a(pItem)) return TRUE;
if (!pItem->interrogation_start)
{ //变位遥测优先级在总召唤之后。
if (sec_changed)
{
switch (m_option.yc_type)
{
case USE_YC_NB: //标度化值
return Send_Measured_value_scaled(pItem);
case USE_YC_NC: //短浮点数
return Send_Measured_value_short_floating_point(pItem);
case USE_YC_ND: //不带品质归一化值
return Send_Measured_value_normalised_without_quality(pItem);
default: //USE_YC_NA: 归一化值
return Send_Measured_value_normalised(pItem);
}
}
}
}
//响应总召唤命令
if (pItem->interrogation_start)
{
if (pItem->call_type != IEC_101_104_COT_INTERROGATION)
{ //组召唤
//激活终止
Send_FrameInterrogation(pItem);
pItem->call_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
}
else if (!pItem->interrogation_yx_fin)
{
Send_Single_point_information(pItem, IEC_101_104_COT_INTERROGATION);
}
else if (!pItem->interrogation_yc_fin)
{
switch (m_option.yc_type)
{
case USE_YC_NB: //标度化值
return Send_Measured_value_scaled(pItem, IEC_101_104_COT_INTERROGATION);
case USE_YC_NC: //短浮点数
return Send_Measured_value_short_floating_point(pItem, IEC_101_104_COT_INTERROGATION);
case USE_YC_ND: //不带品质归一化值
return Send_Measured_value_normalised_without_quality(pItem, IEC_101_104_COT_INTERROGATION);
default: //USE_YC_NA: 归一化值
return Send_Measured_value_normalised(pItem, IEC_101_104_COT_INTERROGATION);
}
}
else
{
Send_FrameInterrogation(pItem);
pItem->call_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
}
}
else if (pItem->pulse_start)
{
if (!pItem->pulse_fin)
{
Send_Integrated_totals(pItem, IEC_101_104_COT_REQCOGEN);
}
else
{
Send_FrameCounterInterrogation(pItem);
pItem->call_type = 0;
pItem->pulse_start = FALSE;
pItem->pulse_fin = TRUE;
}
}
return TRUE;
}
int CIEC101SecondaryUnbalancedProcess::OnPackageReceived(BYTE* pBuf, int msgSize, int /* ord = -1 */)
{
m_lastReceivedMsg = getTimeInMs();
int userDataLength = 0;
int userDataStart = 0;
BYTE c;
int csStart;
int csIndex;
int address = 0;
int addressLength = m_linkLayer.linkLayerParameters.addressLength;
BYTE* msg = (BYTE *)pBuf;
if (msg [0] == 0x68)
{
if (msg [1] != msg [2])
{
vLog(LOG_DEBUG, "ERROR: L fields differ!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
userDataLength = (int)msg [1] - addressLength - 1;
userDataStart = 5 + addressLength;
csStart = 4;
csIndex = userDataStart + userDataLength;
/* check if message size is reasonable */
if (msgSize != (userDataStart + userDataLength + 2 /* CS + END */))
{
vLog(LOG_DEBUG, "ERROR: Invalid message length\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
c = msg [4];
}
else if (msg [0] == 0x10)
{
c = msg [1];
csStart = 1;
csIndex = 2 + addressLength;
}
else
{
vLog(LOG_DEBUG, "ERROR: Received unexpected message type in unbalanced slave mode!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
BOOLEAN isBroadcast = false;
CIEC101ProcessItem* pItem;
/* check address */
if (addressLength > 0)
{
address = msg[csStart + 1];
if (addressLength > 1)
{
address += msg [csStart + 2] * 0x100;
if (address == 65535) isBroadcast = TRUE;
}
else
{
if (address == 255) isBroadcast = TRUE;
}
}
int fc = c & 0x0f;
if (isBroadcast)
{
if (fc != LL_FC_04_USER_DATA_NO_REPLY)
{
vLog(LOG_DEBUG, "ERROR: Invalid function code for broadcast message!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
}
else
{
int uid = GetUnitByAddr((BYTE *)&address, m_linkLayer.linkLayerParameters.addressLength);
if (uid < 0 || uid >= UNIT_NUM)
{
vLog(LOG_DEBUG, "INFO: unknown link layer address(%i) -> ignore message\n", address);
return 1;
}
pItem = (CIEC101ProcessItem *)GetItem(GetOrderByUnitID(uid));
if (pItem == NULL)
{
vLog(LOG_DEBUG, "INFO: unknown link layer address(%i) -> ignore message\n", address);
return 1;
}
UnitFeedDog(uid);
}
/* check checksum */
BYTE checksum = 0;
int i;
for (i = csStart; i < csIndex; i++) checksum += msg [i];
if (checksum != msg [csIndex])
{
vLog(LOG_DEBUG, "ERROR: checksum invalid!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
/* parse C field bits */
BOOLEAN prm = ((c & 0x40) == 0x40);
if (prm == FALSE)
{
vLog(LOG_DEBUG, "ERROR: Received secondary message in unbalanced slave mode!\n");
llsu_setState(LL_STATE_ERROR);
return 1;
}
BOOLEAN fcb = ((c & 0x20) == 0x20);
BOOLEAN fcv = ((c & 0x10) == 0x10);
LinkLayerSecondaryUnbalanced_ReceivedMessage(pItem, fc, isBroadcast, fcb, fcv, msg, userDataStart, userDataLength);
return 1;
}
//不平衡方式从协议接收到主站报文
void CIEC101SecondaryUnbalancedProcess::LinkLayerSecondaryUnbalanced_ReceivedMessage(CIEC101ProcessItem* pItem, BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, BYTE* msg, int userDataStart, int userDataLength)
{
pIEC101_LinkLayerSecondaryUnbalanced self = &(pItem->secondaryLinkUnbalanced);
if (fcv)
{
if (checkFCB(self, fcb) == FALSE)
{
vLog(LOG_DEBUG, "SLL - FCB check failed\n");
llsu_setState(LL_STATE_ERROR);
return;
}
}
llsu_setState(LL_STATE_AVAILABLE);
switch (fc)
{
case LL_FC_09_REQUEST_LINK_STATUS:
//vLog(LOG_DEBUG, "SLL - REQUEST LINK STATUS\n");
{
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
SendFixedFrame(LL_FC_11_STATUS_OF_LINK_OR_ACCESS_DEMAND, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
break;
case LL_FC_00_RESET_REMOTE_LINK:
//vLog(LOG_DEBUG, "SLL - RESET REMOTE LINK\n");
{
self->expectedFcb = TRUE;
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, FALSE, FALSE, FALSE);
}
ResetCUReceived(pItem, FALSE);
}
break;
case LL_FC_07_RESET_FCB:
//vLog(LOG_DEBUG, "SLL - RESET FCB\n");
{
self->expectedFcb = TRUE;
if (m_linkLayer.linkLayerParameters.useSingleCharACK)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, FALSE, FALSE, FALSE);
}
ResetCUReceived(pItem, TRUE);
}
break;
case LL_FC_11_REQUEST_USER_DATA_CLASS_2:
//vLog(LOG_DEBUG, "SLL - REQUEST USER DATA CLASS 2\n");
{
/* provide a buffer where the application layer can encode the user data */
pIEC101_QueueElement element = GetClass2Data(pItem);
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
if (element)
{
SendVariableLengthFrame(LL_FC_08_RESP_USER_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE, element->buffer, element->size);
}
else
{
if (m_linkLayer.linkLayerParameters.useSingleCharACK && !accessDemand)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_09_RESP_NACK_NO_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
}
}
break;
case LL_FC_10_REQUEST_USER_DATA_CLASS_1:
//vLog(LOG_DEBUG, "SLL - REQUEST USER DATA CLASS 1\n");
{
/* provide a buffer where the application layer can encode the user data */
pIEC101_QueueElement element = GetClass1Data(pItem);
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
if (element)
{
SendVariableLengthFrame(LL_FC_08_RESP_USER_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE, element->buffer, element->size);
}
else
{
if (m_linkLayer.linkLayerParameters.useSingleCharACK && !accessDemand)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_09_RESP_NACK_NO_DATA, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
}
}
break;
case LL_FC_03_USER_DATA_CONFIRMED:
//vLog(LOG_DEBUG, "SLL - USER DATA CONFIRMED\n");
if (userDataLength > 0)
{
if (ApplicationLayer_ReceivedData(pItem, msg, isBroadcast, userDataStart, userDataLength))
{
BOOLEAN accessDemand = IsClass1DataAvailable(pItem);
if (m_linkLayer.linkLayerParameters.useSingleCharACK && !accessDemand)
{
SendSingleCharCharacter();
}
else
{
SendFixedFrame(LL_FC_00_ACK, pItem->address, FALSE, FALSE, accessDemand, FALSE);
}
}
}
break;
case LL_FC_04_USER_DATA_NO_REPLY:
//vLog(LOG_DEBUG, "SLL - USER DATA NO REPLY\n");
if (userDataLength > 0)
{
ApplicationLayer_ReceivedData(pItem, msg, isBroadcast, userDataStart, userDataLength);
}
break;
default:
//vLog(LOG_DEBUG, "SLL - UNEXPECTED LINK LAYER MESSAGE\n");
SendFixedFrame(LL_FC_15_SERVICE_NOT_IMPLEMENTED, pItem->address, FALSE, FALSE, FALSE, FALSE);
break;
}
}

View File

@ -1,88 +0,0 @@
#ifndef _ZJD_SUB_IEC101_UNBALANCED_PROCESS_H_
#define _ZJD_SUB_IEC101_UNBALANCED_PROCESS_H_
#include "iec101.h"
class CIEC101SecondaryUnbalancedProcessItem : public CIEC101ProcessItem
{
public:
CIEC101SecondaryUnbalancedProcessItem() {};
virtual ~CIEC101SecondaryUnbalancedProcessItem() {};
public:
void Attach(int uid, int physicsAddress = 0, int commonAddress = 0, int originatorAddress = 0)
{
CIEC101ProcessItem::Attach(uid, physicsAddress, commonAddress, m_originatorAddress);
primaryLinkBalanced.otherStationAddress = physicsAddress;
common_address = commonAddress;
applicationlParameters.originatorAddress = originatorAddress;
}
void setAppLayerDataCount(int yx = 0, int yc = 0, int ym = 0)
{
total_yx = yx;
total_yc = yc;
total_ym = ym;
yx_pos = 0;
yc_pos = 0;
ym_pos = 0;
}
};
class CIEC101SecondaryUnbalancedProcess : public CIEC101SecondaryProcess
{
private:
enumIEC101_LinkLayerState m_state;
QWORD m_lastReceivedMsg;
int m_idleTimeout; /* connection timeout in ms */
public:
CIEC101SecondaryUnbalancedProcess()
{
m_linkLayer.mode = llSecUnbalanced;
m_state = LL_STATE_IDLE;
}
virtual ~CIEC101SecondaryUnbalancedProcess() {};
BOOLEAN OnPreCreate(int id);
BOOLEAN Run(void);
BOOLEAN OnTimer(void);
CIEC101ProcessItem *CreateItem(int ord)
{
return dynamic_cast<CIEC101ProcessItem *>(new CIEC101SecondaryUnbalancedProcessItem);
}
void Slave_setLinkLayerAddressOtherStation(CIEC101ProcessItem* pItem, int address)
{
pItem->address = address;
}
int OnPackageReceived(BYTE* pBuf, int count, int ord = -1);
private:
void llsu_setState(enumIEC101_LinkLayerState newState)
{
if (m_state != newState)
{
m_state = newState;
}
}
BOOLEAN checkFCB(pIEC101_LinkLayerSecondaryUnbalanced self, BOOLEAN fcb)
{
if (fcb != self->expectedFcb) return FALSE;
self->expectedFcb = !(self->expectedFcb);
return TRUE;
}
void ResetCUReceived(CIEC101ProcessItem* pItem, bool onlyFCB)
{
if (onlyFCB)
{
//vLog(LOG_DEBUG, "CS101 slave: Reset FCB received\n");
}
else
{
//vLog(LOG_DEBUG, "Received reset CU\n");
pItem->userDataClass1Queue.flush();
pItem->userDataClass2Queue.flush();
}
}
void LinkLayerSecondaryUnbalanced_ReceivedMessage(CIEC101ProcessItem* self, BYTE fc, BOOLEAN isBroadcast, BOOLEAN fcb, BOOLEAN fcv, BYTE* msg, int userDataStart, int userDataLength);
};
#endif // _ZJD_SUB_IEC101_UNBALANCED_PROCESS_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +0,0 @@
#ifndef _ZJD_SUB_MODBUS_RTU_TCP_PROCESS_H_
#define _ZJD_SUB_MODBUS_RTU_TCP_PROCESS_H_
#include "netproc.h"
#include "modbus_def.h"
#include <vector>
#pragma pack(1)
typedef struct
{
struNetWorkOption net;
BYTE defaultYCType;
} struSubModbusTCPOption;
#pragma pack()
typedef std::vector<int> vecInt;
class CSubModbusTcpProcessItem : public CNetProcessItem
{
public:
BYTE ied_addr;
WORD m_nNum;
short m_CoilRegCount;
short m_DiscreteRegCount;
short m_HoldingRegCount;
short m_InputregCount;
BYTE *m_pCoilRegTable;
BYTE *m_pDiscreteRegTable;
WORD *m_pHoldingRegTable;
WORD *m_pInputRegTable;
public:
CSubModbusTcpProcessItem();
virtual ~CSubModbusTcpProcessItem();
void Attach(int uid, int sock, DWORD peer_addr, WORD peer_port);
void Release(void);
};
class CSubModbusTcpProcess : public CNetProcess
{
public:
CSubModbusTcpProcess();
virtual ~CSubModbusTcpProcess();
CNetProcessItem *CreateItem(int ord);
void DestroyItem(int ord, BOOLEAN bDeleted = FALSE);
virtual BOOLEAN OnPreCreate(int id);
virtual BOOLEAN Run(void);
virtual BOOLEAN OnTimer(void);
private:
struSubModbusTCPOption m_option;
BYTE m_YC_Type;
enum
{
M_ME_NA,
M_ME_NC
};
vecInt m_CoilRegTable;
vecInt m_DiscreteTable;
vecInt m_HoldingRegTable;
vecInt m_InputRegTable;
private:
int OnPackageReceived(BYTE* pBuf, int count, int ord /* = -1 */);
BOOLEAN OnReceiveData(CSubModbusTcpProcessItem *pItem, BYTE* pData, int count, int uid);
eMBErrorCode eMBTCPSend(BYTE ucSlaveAddress, const BYTE *pucFrame, WORD usLength);
eMBException prveMBError2Exception(eMBErrorCode eErrorCode);
eMBException eMBFuncReadInputRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncReadHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncWriteHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncWriteMultipleHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncReadCoils(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncWriteCoil(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncWriteMultipleCoils(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBException eMBFuncReadDiscreteInputs(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen);
eMBErrorCode eMBRegInputCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNRegs);
eMBErrorCode eMBRegHoldingCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNRegs, eMBRegisterMode eMode);
eMBErrorCode eMBRegCoilsCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNCoils, eMBRegisterMode eMode);
eMBErrorCode eMBRegDiscreteCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNDiscrete);
};
#endif //_ZJD_SUB_MODBUS_RTU_TCP_PROCESS_H_