map/das-dn/subgdw104/sub_gdw104.cpp
2024-09-24 15:59:22 +08:00

2543 lines
92 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 "sub_gdw104.h"
#include <fstream>
//国网DLT634.5104-2009实施细则(试行)
static const BYTE GDW_M_FT_NA_1 = 0x2A; //故障事件
static const BYTE GDW_M_KY_NA_1 = 0x6C; //108 ECC公钥传输报文
static const BYTE GDW_C_SE_ND_1 = 0x88; //多点设定 归一化
static const BYTE GDW_C_SR_NA_1 = 0xC8; //切换定值区
static const BYTE GDW_C_RR_NA_1 = 0xC9; //读取定值区
static const BYTE GDW_C_RS_NA_1 = 0xCA; //读取定值
static const BYTE GDW_C_WS_NA_1 = 0xCB; //设定定值
static const BYTE GDW_M_IT_NB_1 = 0xCE; //累计量,短浮点数
static const BYTE GDW_M_IT_TC_1 = 0xCF; //带CP56Time2a时标的累计量短浮点数
static const BYTE GDW_M_EM_NA_1 = 0xCE; //电量当前值
static const BYTE GDW_M_FM_NA_1 = 0xCF; //电量冻结值
static const BYTE GDW_F_FR_NA_1 = 0xD2; //文件传输
static const BYTE GDW_F_SR_NA_1 = 0xD3; //软件升级
static const BYTE FILE_TRS_TYPE = 0x02;
static const BYTE ReadFileDirAct = 0x01;
static const BYTE ReadFileDirCon = 0x02;
static const BYTE ReadFileSelAct = 0x03;
static const BYTE ReadFileSelCon = 0x04;
static const BYTE ReadFileDataAct = 0x05;
static const BYTE ReadFileDataCon = 0x06;
static const BYTE WriteFileSelAct = 0x07;
static const BYTE WriteFileSelCon = 0x08;
static const BYTE WriteFileDataAct = 0x09;
static const BYTE WriteFileDataCon = 0x0A;
#define FILE_SOE_PATH_NAME "%s/soe.msg"
#define FILE_CO_PATH_NAME "%s/co.msg"
#define FILE_EXV_PATH_NAME "%s/exv%04d%02d%02d.msg"
#define FILE_FIXPT_PATH_NAME "%s/fixpt%04d%02d%02d.msg"
#define FILE_FRZ_PATH_NAME "%s/frz%04d%02d%02d.msg"
#define FILE_FLOWREV_PATH_NAME "%s/flowrev.msg"
#define FILE_ULOG_PATH_NAME "%s/ulog.msg"
static const value_string yk_type[] =
{
{YKT_NULL, "空闲"},
{YKT_SELREQ, "选择"},
{YKT_SELRET, "选择确认"},
{YKT_ABRREQ, "撤销"},
{YKT_EXEREQ, "执行"},
{YKT_EXERET, "执行确认"}
};
static void* main_file_process(void* param)
{
CGDW104FileProcess* proc = (CGDW104FileProcess *)param;
DWORD old_ticks = 0;
while (TRUE)
{
if (old_ticks != system32.ticks)
{
old_ticks = system32.ticks;
proc->OnTimer();
}
usleep(5000);
}
pthread_exit(0);
return ((void*)0);
}
BOOLEAN CGDW104FileProcess::SaveMapToFile(void)
{
std::ofstream file("gdw104mapext.dmp");
if (file.is_open())
{
std::map<int, STRUCT_YCEXTREMUM>::iterator it;
file << system32.timers << std::endl;
for (it = mapYcExetremumRecordDatas.begin(); it != mapYcExetremumRecordDatas.end(); it++)
{
file << it->first << " " \
<< it->second.datetime << " "\
<< it->second.fMaxVal << " "\
<< it->second.fMinVal << " " \
<< it->second.fCoef << " " \
<< it->second.fBase << " " \
<< it->second.iMaxVal << " " \
<< it->second.iMinVal << " " \
<< it->second.MaxTime << " " \
<< it->second.MinTime << " " \
<< it->second.iCurVal << std::endl;
}
file.close();
return TRUE;
}
return FALSE;
}
BOOLEAN CGDW104FileProcess::LoadMapFromFile(int size)
{
std::ifstream file("gdw104mapext.dmp");
if (file.is_open())
{
int count = 0;
std::string line;
int key;
STRUCT_YCEXTREMUM value;
mapYcExetremumRecordDatas.clear();
while (std::getline(file, line))
{
std::stringstream stream(line);
if (count == 0)
{
LONG dt;
stream >> dt;
m_last_day = Time_ttounionCP56Time((time_t)dt).dayofmonth;
if (m_last_day <= 0)
{
file.close();
return FALSE;
}
}
else
{
stream >> key >> value.datetime >> value.fMaxVal >> value.fMinVal >> value.fCoef >> value.fBase >> value.iMaxVal >> value.iMinVal >> value.MaxTime >> value.MinTime >> value.iCurVal;
if (mapYcExetremumRecordDatas.find(key) == mapYcExetremumRecordDatas.end())
{
mapYcExetremumRecordDatas.insert(std::map<int, STRUCT_YCEXTREMUM>::value_type(key, value));
}
}
count++;
}
file.close();
if (size != (count - 1))
{
vLog(LOG_ERROR, "yccount is: %d, and count is: %d\n", size, count);
unlink("gdw104mapext.dmp");
return FALSE;
}
return TRUE;
}
return FALSE;
}
BYTE CGDW104FileProcess::GetCheckSum8(BYTE* pData, int count)
{
int i;
BYTE result = 0;
BYTE* pBuf = pData;
for (i = 0; i < count; i++)
{
result += *pBuf;
pBuf++;
}
return result;
}
void CGDW104FileProcess::delete_files_in_dir(const char* folder_path)
{
DIR* dir;
struct dirent* entry;
char file_path[256];
// 打开目录
dir = opendir(folder_path);
if (dir == NULL)
{
vLog(LOG_ERROR, "无法打开目录:%s", folder_path);
return;
}
// 遍历目录
while ((entry = readdir(dir)) != NULL)
{
// 忽略当前目录和上级目录
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
{
continue;
}
// 构建文件路径
snprintf(file_path, sizeof(file_path), "%s/%s", folder_path, entry->d_name);
// 检查文件类型
struct stat statbuf;
if (lstat(file_path, &statbuf) == -1)
{
vLog(LOG_ERROR, "获取文件<%s>状态失败(%d,%s)\n", file_path, errno, strerror(errno));
return;
}
// 如果是文件则删除
if (S_ISREG(statbuf.st_mode))
{
if (unlink(file_path) != 0)
{
vLog(LOG_ERROR, "删除文件<%s>失败(%d,%s)", file_path, errno, strerror(errno));
return;
}
}
// 如果是文件夹则递归删除
else if (S_ISDIR(statbuf.st_mode))
{
delete_files_in_dir(file_path);
}
}
// 关闭目录
closedir(dir);
}
BOOLEAN CGDW104FileProcess::OnCreate(int uid, const void* pUnit, const void* param)
{
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
if (pUnit == NULL || param == NULL) return FALSE;
mapYcExetremumRecordDatas.clear();
m_uid = uid;
struGDW104Option m_nOption = *(struGDW104Option *)param;
struUnit unit = *(struUnit *)pUnit;
m_pUnitYM = NULL;
if (unit.ymcount)
{
m_total_ym = unit.ymcount;
m_pUnitYM = new struUnitYM[unit.ymcount];
if (m_pUnitYM)
{
memcpy(m_pUnitYM, unit.yms, sizeof(struUnitYM) * unit.ymcount);
}
}
m_information_address_length = m_nOption.iec104.info_addr_size;
m_yx_information_address_start = m_nOption.iec104.yx_start_address;
m_yc_information_address_start = m_nOption.iec104.yc_start_address;
m_ym_information_address_start = m_nOption.iec104.ym_start_address;
if (m_nOption.soeDir[0] == '\0') str_SOERecordDir = "soe";
else str_SOERecordDir = m_nOption.soeDir;
if (m_nOption.coDir[0] == '\0') str_coRecordDir = "co";
else str_coRecordDir = m_nOption.coDir;
if (m_nOption.fixptDir[0] == '\0') str_fixptRecordDir = "fixpt";
else str_fixptRecordDir = m_nOption.fixptDir;
if (m_nOption.exvDir[0] == '\0') str_exvRecordDir = "exv";
else str_exvRecordDir = m_nOption.exvDir;
if (m_nOption.frzDir[0] == '\0') str_frzRecordDir = "frz";
else str_frzRecordDir = m_nOption.frzDir;
if (m_nOption.flowrevDir[0] == '\0') str_flowrevRecordDir = "flowrev";
else str_flowrevRecordDir = m_nOption.flowrevDir;
if (m_nOption.ulogDir[0] == '\0') str_ulogRecordDir = "ulog";
else str_ulogRecordDir = m_nOption.ulogDir;
//根据配置来创建文件夹
mkLogDir(str_SOERecordDir.c_str());
mkLogDir(str_coRecordDir.c_str());
mkLogDir(str_fixptRecordDir.c_str());
mkLogDir(str_exvRecordDir.c_str());
mkLogDir(str_frzRecordDir.c_str());
mkLogDir(str_flowrevRecordDir.c_str());
mkLogDir(str_ulogRecordDir.c_str());
char pathName[512];
FILE* pf;
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_UNIT_STATIC);
pf = fopen(pathName, "rb");
if (pf)
{
memset(&m_unit, '\0', sizeof(m_unit));
if (fseek(pf, sizeof(struUnitStatic) * uid, SEEK_SET) == 0)
{
fread(&m_unit, sizeof(struUnitStatic), 1, pf);
}
fclose(pf);
}
//创建极值列表
if (!LoadMapFromFile(unit.yccount))
{
for (int i = 0; i < unit.yccount; i++)
{
STRUCT_YCEXTREMUM data;
data.datetime = system32.timers;
data.iMaxVal = 0x80000000;
data.iMinVal = 0x7FFFFFFF;
data.MaxTime = system32.timers;
data.MinTime = system32.timers;
data.fCoef = unit.ycs[i].coef;
data.fBase = unit.ycs[i].base;
if (mapYcExetremumRecordDatas.find(i) == mapYcExetremumRecordDatas.end())
{
mapYcExetremumRecordDatas.insert(std::map<int, STRUCT_YCEXTREMUM>::value_type(i, data));
}
}
}
m_database.Open("./gdw104.db", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
m_database.MoveDatabaseToMemory();
//创建数据库表
try
{
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
pStmt->SqlStatement("CREATE TABLE IF NOT EXISTS SOE_RECORD_TABLE ("
"Yxpoint INTEGER NOT NULL,"
"Yxvalue INTEGER NOT NULL,"
"Yxdatetime INTEGER NOT NULL,"
"Yxmillisecond INTEGER NOT NULL,"
"CONSTRAINT SOE_RECORD_TABLE_PK PRIMARY KEY (Yxpoint, Yxvalue, Yxdatetime, Yxmillisecond));");
pStmt->SqlStatement("CREATE TABLE IF NOT EXISTS YKLOG_RECORD_TABLE ("
"Ykpoint INTEGER NOT NULL,"
"Yktype INTEGER NOT NULL,"
"Ykvalue INTEGER NOT NULL,"
"Ykdatetime INTEGER NOT NULL,"
"Ykmillisecond INTEGER NOT NULL,"
"CONSTRAINT YKLOG_RECORD_TABLE_PK PRIMARY KEY (Ykpoint, Yktype, Ykvalue, Ykdatetime, Ykmillisecond));");
//创建极值库
pStmt->SqlStatement("CREATE TABLE IF NOT EXISTS YCEXV_RECORD_TABLE ("
"Ycpoint INTEGER NOT NULL,"
"Ycdatetime INTEGER NOT NULL,"
"YciMaxval INTEGER NOT NULL,"
"YciMinval INTEGER NOT NULL,"
"YcfMaxval REAL NOT NULL,"
"YcfMinval REAL NOT NULL,"
"YcMaxdatetime INTEGER NOT NULL,"
"YcMindatetime INTEGER NOT NULL,"
"CONSTRAINT YCEXV_RECORD_TABLE_PK PRIMARY KEY (Ycpoint, Ycdatetime));");
//创建遥测历史数据表YcHisRecordTable
pStmt->SqlStatement("CREATE TABLE IF NOT EXISTS YCHIS_RECORD_TABLE ("
"Ycpoint INTEGER NOT NULL,"
"Ycdatetime INTEGER NOT NULL,"
"YciVal INTEGER NOT NULL,"
"Ycfval REAL NOT NULL,"
"CONSTRAINT YCHIS_RECORD_TABLE PRIMARY KEY (Ycpoint, Ycdatetime));");
//创建冻结电度量表
pStmt->SqlStatement("CREATE TABLE IF NOT EXISTS FMHIS_RECORD_TABLE ("
"Ympoint INTEGER NOT NULL,"
"Ymdatetime INTEGER NOT NULL,"
"YmiVal INTEGER NOT NULL,"
"Ymfval REAL NOT NULL,"
"CONSTRAINT FMHIS_RECORD_TABLE PRIMARY KEY (Ympoint, Ymdatetime));");
//比较表空间
delete pStmt;
}
catch (SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
return FALSE;
}
return TRUE;
}
BOOLEAN CGDW104FileProcess::OnTimer(void)
{
BOOLEAN sec_changed = FALSE;
if (last_sec != system32.timers)
{
last_sec = system32.timers;
sec_changed = TRUE;
}
do
{
if (m_nCmdID == FIOCMD_OPEN_FILE)
{
m_nCmdID = 0;
if (m_pFileHandle)
{
fclose(m_pFileHandle);
m_pFileHandle = NULL;
}
m_pFileHandle = fopen(m_pathName.c_str(), m_bWr ? "wb+" : "rb");
if (m_pFileHandle == NULL) m_nCmdIDConfirm |= CMD_EXEC_ERR;
//获取文件长度
m_nFileLength = FileLength(m_pathName);
m_nCmdIDConfirm = FIOCMD_OPEN_FILE;
}
else if (m_nCmdID == FIOCMD_CLOSE_FILE)
{
m_nCmdID = 0;
if (m_pFileHandle)
{
fclose(m_pFileHandle);
m_pFileHandle = NULL;
}
m_nFileLength = 0;
m_nFilePos = 0;
m_nReadLen = 0;
}
else if (m_nCmdID == FIOCMD_READ_FILE)
{
m_nCmdID = 0;
if (fseek(m_pFileHandle, m_nFilePos, SEEK_SET) != 0)
{
m_nCmdIDConfirm |= CMD_EXEC_ERR;
}
else
{
int count = (FileLeftLength() > MAX_FILEDATA_LEN) ? MAX_FILEDATA_LEN : FileLeftLength();
fread((char *)m_fileBuffer, count, 1, m_pFileHandle);
m_nReadLen = count;
}
m_nCmdIDConfirm = FIOCMD_READ_FILE;
}
else if (m_nCmdID == FIOCMD_READ_DIR)
{
//删除目录下所有文件
delete_files_in_dir(str_SOERecordDir.c_str());
delete_files_in_dir(str_coRecordDir.c_str());
delete_files_in_dir(str_exvRecordDir.c_str());
delete_files_in_dir(str_fixptRecordDir.c_str());
delete_files_in_dir(str_frzRecordDir.c_str());
delete_files_in_dir(str_flowrevRecordDir.c_str());
delete_files_in_dir(str_ulogRecordDir.c_str());
m_nCmdID = 0;
//生成事件记录文件
createSOEFile();
//生成遥控记录文件
createYKLogFile();
//生成极值文件
createExtremumRecordFile();
//生成遥测定点记录数据文件
createYCHisRecordFile();
//生成冻结数据文件
createFmHisRecordFile();
//将数据保存到本地数据库
m_database.SaveDatabaseFromMemoryToFile("./gdw104.db");
if (ReadDir(m_pathName.c_str()) <= 0)
{
vLog(LOG_ERROR, "Read %s dir error.\n", m_pathName.c_str());
m_nCmdIDConfirm |= CMD_EXEC_ERR;
}
m_nCmdIDConfirm = FIOCMD_READ_DIR;
}
} while (0);
if (sec_changed)
{
DumpSOE();
DumpYKLog();
if (m_last_day != system32.now.dayofmonth)
{
UpdateExtremumRecord(TRUE);
m_last_day = system32.now.dayofmonth;
}
else
{
UpdateExtremumRecord(FALSE);
}
if ((system32.timers % 300) == 0) //此处最好根据配置来设置定点数据频率
{ //5分钟保存一次
//保存一次遥测历史
DumpYCHisRecord(system32.timers);
//保存一次冻结数据
DumpFmHisRecord(system32.timers);
// save the memory database to a file
m_database.SaveDatabaseFromMemoryToFile("./gdw104.db");
}
}
return TRUE;
}
void CGDW104FileProcess::createSOEFile(void)
{
int count = 0;
char sql[512];
char query[512];
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
//生成soe文件
if (m_bCallAllFile)
{
snprintf(query, sizeof(query), "SELECT * FROM SOE_RECORD_TABLE;");
count = (int)pStmt->SqlAggregateFuncResult("SELECT COUNT(*) FROM SOE_RECORD_TABLE;");
}
else
{
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM SOE_RECORD_TABLE WHERE Yxdatetime >= %d AND Yxdatetime <= %d;", (DWORD)m_start_time, (DWORD)m_end_time);
snprintf(query, sizeof(query), "SELECT * FROM SOE_RECORD_TABLE WHERE Yxdatetime >= %d AND Yxdatetime <= %d;", (DWORD)m_start_time, (DWORD)m_end_time);
count = (int)pStmt->SqlAggregateFuncResult(sql);
}
char text[64];
snprintf(text, sizeof(text), FILE_SOE_PATH_NAME, str_SOERecordDir.c_str());
FILE *pf = fopen(text, "wb+");
if (pf != NULL)
{
fprintf(pf, "soe.msg, v1.0\r\n%s,%02d,%02d\r\n", m_unit.name, count, m_information_address_length);
pStmt->BeginTransaction();
pStmt->Sql(query);
while (pStmt->FetchRow())
{
char buffer[32];
struct tm info;
time_t t = (time_t)pStmt->GetColumnInt(2);
localtime_r(&t, &info);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &info);
fprintf(pf, "%04x,%d,%s.%3d\r\n",
pStmt->GetColumnInt(0) + m_yx_information_address_start,
pStmt->GetColumnInt(1),
buffer,
pStmt->GetColumnInt(3));
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
fclose(pf);
}
}
catch(SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::createYKLogFile(void)
{
int count = 0;
char sql[512];
char query[512];
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
if (m_bCallAllFile)
{
snprintf(query, sizeof(query), "SELECT * FROM YKLOG_RECORD_TABLE;");
count = (int)pStmt->SqlAggregateFuncResult("SELECT COUNT(*) FROM YKLOG_RECORD_TABLE;");
}
else
{
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM YKLOG_RECORD_TABLE WHERE Yxdatetime >= %d AND Yxdatetime <= %d;", (DWORD)m_start_time, (DWORD)m_end_time);
snprintf(query, sizeof(query), "SELECT * FROM YKLOG_RECORD_TABLE WHERE Yxdatetime >= %d AND Yxdatetime <= %d;", (DWORD)m_start_time, (DWORD)m_end_time);
count = (int)pStmt->SqlAggregateFuncResult(sql);
}
char text[64];
snprintf(text, sizeof(text), FILE_CO_PATH_NAME, str_coRecordDir.c_str());
FILE *pf = fopen(text, "wb+");
if (pf != NULL)
{
fprintf(pf, "co.msg, v1.0\r\n%s,%02d,%02d\r\n", m_unit.name, count, m_information_address_length);
pStmt->BeginTransaction();
pStmt->Sql(query);
while (pStmt->FetchRow())
{
char buffer[32];
struct tm info;
time_t t = (time_t)pStmt->GetColumnInt(3);
localtime_r(&t, &info);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &info);
fprintf(pf, "%04x,%s,%s,%s.%03d\r\n",
pStmt->GetColumnInt(0),
val_to_str(pStmt->GetColumnInt(1), yk_type, "STATE=%d"),
pStmt->GetColumnInt(2) ? "" : "",
buffer,
pStmt->GetColumnInt(4));
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
fclose(pf);
}
}
catch(SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::createExtremumRecordFile(void)
{
char query[512];
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
if (m_bCallAllFile)
{
snprintf(query, sizeof(query), "SELECT * FROM YCEXV_RECORD_TABLE;");
}
else
{
snprintf(query, sizeof(query), "SELECT * FROM YCEXV_RECORD_TABLE WHERE Ycdatetime >= %d AND Ycdatetime <= %d;", (DWORD)m_start_time, (DWORD)m_end_time);
}
std::map<std::string, STRUCT_FILEBUFFER> mapExvFileBuffers;
mapExvFileBuffers.clear();
pStmt->BeginTransaction();
pStmt->Sql(query);
while (pStmt->FetchRow())
{
char buffer[256];
unionCP56Time ut = Time_ttounionCP56Time((time_t)pStmt->GetColumnInt(1));
snprintf(buffer, sizeof(buffer), FILE_EXV_PATH_NAME, str_exvRecordDir.c_str(), ut.year + 2000, ut.month, ut.dayofmonth);
std::string filename = buffer;
std::string maxbuffer;
std::string minbuffer;
int point = pStmt->GetColumnInt(0);
float maxVal = pStmt->GetColumnDouble(4);
float minVal = pStmt->GetColumnDouble(5);
unionCP56Time maxTime = Time_ttounionCP56Time((time_t)pStmt->GetColumnInt(6));
unionCP56Time minTime = Time_ttounionCP56Time((time_t)pStmt->GetColumnInt(7));
snprintf(buffer, sizeof(buffer), "%4x,%4.3f,%04d-%02d-%02d %02d:%02d:%02d.%03d", point + m_yc_information_address_start, maxVal,
maxTime.year + 2000, maxTime.month, maxTime.dayofmonth, maxTime.hour, maxTime.minute, maxTime.millisecond / 1000, maxTime.millisecond % 1000);
maxbuffer = buffer;
snprintf(buffer, sizeof(buffer), "%4x,%4.3f,%04d-%02d-%02d %02d:%02d:%02d.%03d", point + m_yc_information_address_start, minVal,
minTime.year + 2000, minTime.month, minTime.dayofmonth, minTime.hour, minTime.minute, minTime.millisecond / 1000, minTime.millisecond % 1000);
minbuffer = buffer;
if (mapExvFileBuffers.find(filename) == mapExvFileBuffers.end())
{
STRUCT_FILEBUFFER fb;
fb.count = 1;
fb.ss_outmax = maxbuffer;
fb.ss_outmin = minbuffer;
mapExvFileBuffers.insert(std::map<std::string, STRUCT_FILEBUFFER>::value_type(filename, fb));
}
else
{
mapExvFileBuffers[filename].count++;
mapExvFileBuffers[filename].ss_outmax += "," + maxbuffer;
mapExvFileBuffers[filename].ss_outmin += "," + minbuffer;
}
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
std::map<std::string, STRUCT_FILEBUFFER>::iterator it;
for (it = mapExvFileBuffers.begin(); it != mapExvFileBuffers.end(); it++)
{
FILE* pf = fopen(it->first.c_str(), "wb+");
if (pf)
{
fprintf(pf, "%s, v1.0\r\n%s,%04d-%02d-%02d,%02d\r\n", it->first.c_str(), m_unit.name, system32.now.year+2000, system32.now.month, system32.now.dayofmonth, m_information_address_length);
fprintf(pf, "%d,%s\r\n", it->second.count, it->second.ss_outmax.c_str());
fprintf(pf, "%d,%s\r\n", it->second.count, it->second.ss_outmin.c_str());
fclose(pf);
}
}
}
catch(SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::createYCHisRecordFile(void)
{
int count = 0;
char query[512];
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
if (m_bCallAllFile)
{
snprintf(query, sizeof(query), "SELECT * FROM YCHIS_RECORD_TABLE WHERE Ycdatetime %% 900 == 0;");
}
else
{
snprintf(query, sizeof(query), "SELECT * FROM YCHIS_RECORD_TABLE WHERE Ycdatetime >= %d AND Ycdatetime <= %d AND Ycdatetime %% 900 == 0;", (DWORD)m_start_time, (DWORD)m_end_time);
}
vLog(LOG_DEBUG, "ychis file query is: %s\n", query);
std::map<std::string, STRUCT_FILEBUFFER> mapFixptFileBuffers;
mapFixptFileBuffers.clear();
pStmt->BeginTransaction();
pStmt->Sql(query);
count = 0;
int max_count = mapYcExetremumRecordDatas.size();
while (pStmt->FetchRow())
{
char buffer[256];
unionCP56Time ut = Time_ttounionCP56Time((time_t)pStmt->GetColumnInt(1)); //数据时间
snprintf(buffer, sizeof(buffer), FILE_FIXPT_PATH_NAME, str_fixptRecordDir.c_str(), ut.year + 2000, ut.month, ut.dayofmonth);
std::string filename = buffer;
int point = pStmt->GetColumnInt(0);
float fVal = pStmt->GetColumnDouble(3);
snprintf(buffer, sizeof(buffer), "%4x,%4.3f", point + m_yc_information_address_start, fVal);
std::string valbuffer = buffer;
if (mapFixptFileBuffers.find(filename) == mapFixptFileBuffers.end())
{
char temp[64];
snprintf(temp, sizeof(temp), "%d,%04d-%02d-%02d %02d:%02d:%02d.%03d,", max_count, ut.year + 2000, ut.month, ut.dayofmonth, ut.hour, ut.minute, ut.millisecond / 1000, ut.millisecond % 1000);
STRUCT_FILEBUFFER fb;
fb.count = 1;
fb.ss_outmax = temp + valbuffer;
mapFixptFileBuffers.insert(std::map<std::string, STRUCT_FILEBUFFER>::value_type(filename, fb));
}
else if (count == 0)
{
char temp[64];
snprintf(temp, sizeof(temp), "%d,%04d-%02d-%02d %02d:%02d:%02d.%03d,", max_count, ut.year + 2000, ut.month, ut.dayofmonth, ut.hour, ut.minute, ut.millisecond / 1000, ut.millisecond % 1000);
mapFixptFileBuffers[filename].count++;
mapFixptFileBuffers[filename].ss_outmax += temp + valbuffer;
}
else
{
mapFixptFileBuffers[filename].ss_outmax += "," + valbuffer;
}
count++;
if (count >= max_count)
{
count = 0;
mapFixptFileBuffers[filename].ss_outmax += "\r\n";
}
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
std::map<std::string, STRUCT_FILEBUFFER>::iterator it;
for (it = mapFixptFileBuffers.begin(); it != mapFixptFileBuffers.end(); it++)
{
FILE* pf = fopen(it->first.c_str(), "wb+");
if (pf)
{
fprintf(pf, "%s, v1.0\r\n%s,%04d-%02d-%02d,%d,%02d\r\n", it->first.c_str(), m_unit.name, system32.now.year+2000, system32.now.month, system32.now.dayofmonth, it->second.count, m_information_address_length);
fprintf(pf, "%s\r\n", it->second.ss_outmax.c_str());
fclose(pf);
}
}
}
catch(SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::createFmHisRecordFile(void)
{
int count = 0;
char query[512];
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
if (m_bCallAllFile)
{
snprintf(query, sizeof(query), "SELECT * FROM FMHIS_RECORD_TABLE WHERE Ymdatetime %% 900 == 0;");
}
else
{
snprintf(query, sizeof(query), "SELECT * FROM FMHIS_RECORD_TABLE WHERE Ymdatetime >= %d AND Ymdatetime <= %d AND Ymdatetime %% 900 == 0;", (DWORD)m_start_time, (DWORD)m_end_time);
}
vLog(LOG_DEBUG, "create frz data query is: %s\n", query);
std::map<std::string, STRUCT_FILEBUFFER> mapFmHisFileBuffers;
mapFmHisFileBuffers.clear();
pStmt->BeginTransaction();
pStmt->Sql(query);
count = 0;
while (pStmt->FetchRow())
{
char buffer[256];
unionCP56Time ut = Time_ttounionCP56Time((time_t)pStmt->GetColumnInt(1)); //数据时间
snprintf(buffer, sizeof(buffer), FILE_FRZ_PATH_NAME, str_frzRecordDir.c_str(), ut.year + 2000, ut.month, ut.dayofmonth);
std::string filename = buffer;
int point = pStmt->GetColumnInt(0);
float fVal = pStmt->GetColumnDouble(3);
snprintf(buffer, sizeof(buffer), "%4x,%4.3f", point + m_ym_information_address_start, fVal);
std::string valbuffer = buffer;
if (mapFmHisFileBuffers.find(filename) == mapFmHisFileBuffers.end())
{
char temp[64];
snprintf(temp, sizeof(temp), "%d,%04d-%02d-%02d %02d:%02d:%02d.%03d,", m_total_ym, ut.year + 2000, ut.month, ut.dayofmonth, ut.hour, ut.minute, ut.millisecond / 1000, ut.millisecond % 1000);
STRUCT_FILEBUFFER fb;
fb.count = 1;
fb.ss_outmax = temp + valbuffer;
mapFmHisFileBuffers.insert(std::map<std::string, STRUCT_FILEBUFFER>::value_type(filename, fb));
}
else if (count == 0)
{
char temp[64];
snprintf(temp, sizeof(temp), "%d,%04d-%02d-%02d %02d:%02d:%02d.%03d,", m_total_ym, ut.year + 2000, ut.month, ut.dayofmonth, ut.hour, ut.minute, ut.millisecond / 1000, ut.millisecond % 1000);
mapFmHisFileBuffers[filename].count++;
mapFmHisFileBuffers[filename].ss_outmax += temp + valbuffer;
}
else
{
mapFmHisFileBuffers[filename].ss_outmax += "," + valbuffer;
}
count++;
if (count >= m_total_ym)
{
count = 0;
mapFmHisFileBuffers[filename].ss_outmax += "\r\n";
}
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
std::map<std::string, STRUCT_FILEBUFFER>::iterator it;
for (it = mapFmHisFileBuffers.begin(); it != mapFmHisFileBuffers.end(); it++)
{
FILE* pf = fopen(it->first.c_str(), "wb+");
if (pf)
{
fprintf(pf, "%s, v1.0\r\n%s,%04d-%02d-%02d,%d,%02d\r\n", it->first.c_str(), m_unit.name, system32.now.year+2000, system32.now.month, system32.now.dayofmonth, it->second.count, m_information_address_length);
fprintf(pf, "%s\r\n", it->second.ss_outmax.c_str());
fclose(pf);
}
}
}
catch(SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::DumpSOE(void)
{
if (m_soe_load == m_soe_save) return;
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
pStmt->BeginTransaction();
pStmt->Sql("INSERT INTO SOE_RECORD_TABLE VALUES(?,?,?,?)");
//保存SOE数据
while (m_soe_load != m_soe_save)
{
pStmt->BindInt(1, m_soes[m_soe_load].order);
pStmt->BindInt(2, m_soes[m_soe_load].value);
pStmt->BindInt(3, unionCP56TimetoTime_t(&m_soes[m_soe_load].st));
pStmt->BindInt(4, (m_soes[m_soe_load].st.millisecond % 1000));
pStmt->Execute();
pStmt->Reset();
m_soe_load++;
m_soe_load = m_soe_load % DATABASE_SOE_NUM;
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
}
catch (SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::DumpYKLog(void)
{
if (m_yklog_load == m_yklog_save) return;
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
pStmt->BeginTransaction();
pStmt->Sql("INSERT INTO YKLOG_RECORD_TABLE VALUES(?,?,?,?,?)");
//保存SOE数据
while (m_yklog_load != m_yklog_save)
{
pStmt->BindInt(1, m_yklogs[m_yklog_load].point);
pStmt->BindInt(2, m_yklogs[m_yklog_load].type);
pStmt->BindInt(3, m_yklogs[m_yklog_load].value);
pStmt->BindInt(4, unionCP56TimetoTime_t(&m_yklogs[m_yklog_load].st));
pStmt->BindInt(5, (m_yklogs[m_yklog_load].st.millisecond % 1000));
pStmt->Execute();
pStmt->Reset();
m_yklog_load++;
m_yklog_load = m_yklog_load % DATABASE_YK_LOG_NUM;
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
}
catch (SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::UpdateExtremumRecord(BOOLEAN bAddNew)
{
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
pStmt->BeginTransaction();
if (bAddNew)
{
pStmt->Sql("INSERT INTO YCEXV_RECORD_TABLE VALUES(?,?,?,?,?,?,?,?)");
//保存极值数据
std::map<int, STRUCT_YCEXTREMUM>::iterator it;
for (it = mapYcExetremumRecordDatas.begin(); it != mapYcExetremumRecordDatas.end(); it++)
{
pStmt->BindInt(1, it->first);
//将数据都更新为当前数据和当前时间
it->second.datetime = system32.timers;
it->second.iMaxVal = it->second.iCurVal;
it->second.iMinVal = it->second.iCurVal;
it->second.fMaxVal = it->second.iCurVal * it->second.fCoef + it->second.fBase;
it->second.fMinVal = it->second.iCurVal * it->second.fCoef + it->second.fBase;
it->second.MaxTime = system32.timers;
it->second.MinTime = system32.timers;
pStmt->BindInt(2, (LONG)it->second.datetime);
pStmt->BindInt(3, it->second.iMaxVal);
pStmt->BindInt(4, it->second.iMinVal);
pStmt->BindDouble(5, it->second.fMaxVal);
pStmt->BindDouble(6, it->second.fMinVal);
pStmt->BindInt(7, (LONG)it->second.MaxTime);
pStmt->BindInt(8, (LONG)it->second.MinTime);
pStmt->Execute();
pStmt->Reset();
}
}
else
{
pStmt->Sql("UPDATE YCEXV_RECORD_TABLE SET "
"YciMaxval=@YciMaxval, "
"YciMinval=@YciMinval, "
"YcfMaxval=@YcfMaxval, "
"YcfMinval=@YcfMinval,"
"YcMaxdatetime=@YcMaxdatetime, "
"YcMindatetime=@YcMindatetime "
"WHERE Ycpoint=@Ycpoint");
//保存极值数据
std::map<int, STRUCT_YCEXTREMUM>::iterator it;
for (it = mapYcExetremumRecordDatas.begin(); it != mapYcExetremumRecordDatas.end(); it++)
{
pStmt->BindInt(1, it->second.iMaxVal);
pStmt->BindInt(2, it->second.iMinVal);
pStmt->BindDouble(3, it->second.fMaxVal);
pStmt->BindDouble(4, it->second.fMinVal);
pStmt->BindInt(5, (LONG)it->second.MaxTime);
pStmt->BindInt(6, (LONG)it->second.MinTime);
pStmt->BindInt(7, it->first);
pStmt->Execute();
pStmt->Reset();
}
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
}
catch (SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "aaaaSQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::DumpYCHisRecord(LONG now)
{
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
pStmt->BeginTransaction();
pStmt->Sql("INSERT INTO YCHIS_RECORD_TABLE VALUES(?,?,?,?)");
std::map<int, STRUCT_YCEXTREMUM>::iterator it;
for (it = mapYcExetremumRecordDatas.begin(); it != mapYcExetremumRecordDatas.end(); it++)
{
pStmt->BindInt(1, it->first);
pStmt->BindInt(2, now);
pStmt->BindInt(3, it->second.iCurVal);
pStmt->BindDouble(4, ((it->second.iCurVal * it->second.fCoef) + it->second.fBase));
pStmt->Execute();
pStmt->Reset();
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
}
catch (SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
void CGDW104FileProcess::DumpFmHisRecord(LONG now)
{
SQLiteStatement *pStmt = new SQLiteStatement(&m_database);
try
{
pStmt->BeginTransaction();
//pStmt->Sql("INSERT INTO FMHIS_RECORD_TABLE VALUES(?,?,?,?)");
pStmt->Sql("REPLACE INTO FMHIS_RECORD_TABLE VALUES(?,?,?,?)");
for (int i = 0; i < m_total_ym; i++)
{
pStmt->BindInt(1, m_pUnitYM[i].order);
pStmt->BindInt(2, now);
pStmt->BindInt(3, m_pUnitYM[i].value);
pStmt->BindDouble(4, ((m_pUnitYM[i].value * m_pUnitYM[i].coef) + m_pUnitYM[i].base));
pStmt->Execute();
pStmt->Reset();
}
pStmt->FreeQuery();
pStmt->CommitTransaction();
}
catch (SQLiteException &exception)
{
vLog(LOG_ERROR, "\nException Occured");
exception.Show();
vLog(LOG_ERROR, "SQLite result code: %d,%s\n", exception.GetSqliteResultCode(), exception.GetErrorDescription().c_str());
}
delete pStmt;
}
CSubGDW104Process::CSubGDW104Process()
{
last_sec = system32.timers;
m_dwFileType = 0;
memset(&m_nOption, 0, sizeof(m_nOption));
}
CSubGDW104Process::~CSubGDW104Process()
{
}
BOOLEAN CSubGDW104Process::OnPreCreate(int id)
{
if (!CIEC104Process::OnPreCreate(id)) return FALSE;
m_yx_start_address = m_nOption.yx_start_address;
m_yc_start_address = m_nOption.yc_start_address;
m_ym_start_address = m_nOption.ym_start_address;
if (m_yx_start_address <= 0) m_yx_start_address = IEC_101_104_YX_START_ADDR;
if (m_yc_start_address <= 0) m_yc_start_address = IEC_101_104_YC_START_ADDR;
if (m_ym_start_address <= 0) m_ym_start_address = IEC_101_104_YM_START_ADDR;
if (!GetOption(&gdw_option, sizeof(gdw_option)))
{
return FALSE;
}
int i;
int uid;
CIEC104ProcessItem *pItem;
//更新配置
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC104ProcessItem *)GetItem(i);
if (NULL == pItem) continue;
pItem->apdu_k_max = m_nOption.k;
pItem->apdu_w_max = m_nOption.w;
pItem->apdu_t0_begin = 10;
uid = GetUnitID(i);
if (uid < 0 || uid >= UNIT_NUM) continue;
m_gdwFile.OnCreate(uid, &config.units[uid], &gdw_option);
}
return TRUE;
}
BOOLEAN CSubGDW104Process::OnCreated(int id)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, MEMERY_1M);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_t pid;
if (pthread_create(&pid, &attr, main_file_process, &m_gdwFile) < 0)
{
vLog(LOG_ERROR, "create main_run_process error(%d,%s).\n", errno, strerror(errno));
return FALSE;
}
pthread_attr_destroy(&attr);
return CIEC104Process::OnCreated(id);
}
void CSubGDW104Process::GetItemEvents(CIEC104ProcessItem* pItem)
{
int i, uid, count;
int soe_point;
BOOLEAN soe_value;
BYTE soe_qds;
unionCP56Time soe_time;
if (NULL == pItem) return;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return;
if (NULL == pItem->events.data) return;
count = pItem->events.count;
if (count < 0 || count >= DATABASE_SOE_NUM) count = 0;
int max_count = DATABASE_SOE_NUM - count;
for (i = 0; i < max_count; i++)
{
soe_point = GetUnitSOE(uid, soe_value, soe_qds, soe_time);
if (soe_point < 0) break;
pItem->events.data[count].order = soe_point;
pItem->events.data[count].value = soe_value;
pItem->events.data[count].qds = soe_qds;
memcpy(&pItem->events.data[count].ct, &soe_time, sizeof(soe_time));
m_gdwFile.PushSOE(soe_time, soe_point, soe_value, uid);
count++;
}
pItem->events.count = count;
}
BOOLEAN CSubGDW104Process::FetchUnitYC(int order)
{
int i;
int uid;
int oid;
struUnit* pUnit;
if (order < 0 || order >= PROCESS_UNIT_NUM) return FALSE;
uid = config.processes[m_nProcess].units[order];
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return FALSE;
for (i = 0; i < pUnit->yccount; i++)
{
oid = pUnit->ycs[i].order;
if (oid < 0 || oid >= DATABASE_YC_NUM) continue;
pUnit->ycs[i].qds = database.ycs[oid].qds;
if (pUnit->ycs[i].value != database.ycs[oid].value)
{ //此处家里如极值判断,并入库
if (pUnit->ycs[i].change_pos >= 0)
{
if (abs(pUnit->ycs[i].value - database.ycs[oid].value) >= pUnit->ycs[i].change_pos)
{ //40码值变化量认为是遥测变位
pUnit->ycs[i].value = database.ycs[oid].value;
pUnit->ycs[i].update_time = database.ycs[oid].update_time;
pUnit->ycs[i].ycbw = TRUE;
}
}
}
m_gdwFile.AddExtremumRecord(i, database.ycs[oid].value);
}
return TRUE;
}
BOOLEAN CSubGDW104Process::FetchUnitYM(int order)
{
int i;
int uid;
int oid;
struUnit* pUnit;
if (order < 0 || order >= PROCESS_UNIT_NUM) return FALSE;
uid = config.processes[m_nProcess].units[order];
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
pUnit = &config.units[uid];
if ((pUnit->state & 0x01) != TRUE) return FALSE;
for (i = 0; i < pUnit->ymcount; i++)
{
oid = pUnit->yms[i].order;
if (oid < 0 || oid >= DATABASE_YM_NUM) continue;
if (pUnit->yms[i].value != database.yms[oid].value)
{
pUnit->yms[i].value = database.yms[oid].value;
pUnit->yms[i].update_time = database.yms[oid].update_time;
}
}
m_gdwFile.AddFmRecord(pUnit->yms, pUnit->ymcount);
return TRUE;
}
BOOLEAN CSubGDW104Process::Run(void)
{
if (!CIEC104Process::Run()) return FALSE;
int i, uid;
CIEC104ProcessItem* pItem;
FeedDog();
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC104ProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
if (pItem->interrogation_finish)
{
GetItemYXBWs(pItem);
}
//刷新事件记录库
GetItemEvents(pItem);
//刷新遥测库
FetchUnitYC(i);
//刷新遥脉库
FetchUnitYM(i);
//总召唤结束,开始刷新遥测变位缓冲。
if (pItem->interrogation_finish)
{ //刷新遥测变位
if (pItem->ycbws.count <= 0)
{ //当遥测变位发送结束后才更新
GetItemYCBWs(pItem);
}
}
}
return TRUE;
}
BOOLEAN CSubGDW104Process::OnTimer(void)
{
int uid;
int i;
int ret;
CIEC104ProcessItem *pItem;
BOOLEAN sec_changed = FALSE;
if (!CIEC104Process::OnTimer()) return FALSE;
//是否发生了秒变化
if (last_sec != (time_t)system32.timers)
{
last_sec = system32.timers;
sec_changed = TRUE;
}
for (i = 0; i < PROCESS_UNIT_NUM; i++)
{
pItem = (CIEC104ProcessItem *)GetItem(i);
if (NULL == pItem) continue;
uid = pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) continue;
if (pItem->GetSock() < 0)
{
continue;
}
pItem->apdu_t0_begin = system32.timers;
//判断t3超时
if (pItem->apdu_t3_begin > 0 && system32.timers > (pItem->apdu_t3_begin + apdu_t3_max))
{
if (!SendUFrame(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, i))
{
vLog(LOG_ERROR, "Unit(%d) SendUFrame error.\n", uid);
pItem->Release();
continue;
}
pItem->apdu_t3_begin = 0;
//启动t1计时
pItem->apdu_t1_begin = system32.timers;
pItem->apdu_wait_test = TRUE;
continue;
}
//判断t1超时
if (pItem->apdu_t1_begin > 0 && system32.timers > (pItem->apdu_t1_begin + apdu_t1_max))
{ //直接复位链路
vLog(LOG_ERROR, "Unit(%d) t1 expired (begin at %lu).\n", uid, pItem->apdu_t1_begin);
pItem->Release();
continue;
}
//判断t2超时
if (pItem->apdu_t2_begin > 0 && system32.timers > (pItem->apdu_t2_begin + apdu_t2_max))
{ //发送S帧
if (!SendSFrame(i))
{
vLog(LOG_ERROR, "Unit(%d) SendSFrame error.\n", uid);
pItem->Release();
continue;
}
continue;
}
//如果链路通信未启动则不发送任何报文
if (!pItem->apdu_setup) continue;
//是否已经达到k值,若k值已经达到则不再发送数据报文
if (pItem->apdu_k >= pItem->apdu_k_max) continue;
//总召唤没有结束不响应遥控。不上送遥信变位及SOE
if (pItem->interrogation_finish)
{ //发送遥控返校
ret = MakeYKFrame(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
//发送遥调返校
ret = MakeYTFrame(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
//发送遥信变位
ret = Send_Single_point_information(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
//发送SOE信息
ret = Send_Single_point_information_with_time_tag_cp56time2a(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
//响应总召唤命令
if (pItem->interrogation_start)
{
if (pItem->interrogation_type != IEC_101_104_COT_INTERROGATION)
{ //组召唤
//激活终止
ret = Send_FrameInterrogation(pItem, i);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_FrameInterrogation error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0)
{
pItem->interrogation_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
continue;
}
}
if (!pItem->interrogation_yx_fin)
{
ret = Send_Single_point_information(pItem, i, IEC_101_104_COT_INTERROGATION);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Single_point_information IEC_101_104_COT_INTERROGATION error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
if (!pItem->interrogation_yc_fin)
{
switch (m_nOption.yc_type)
{
case USE_YC_NB: //标度化值
ret = Send_Measured_value_scaled(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
case USE_YC_NC: //短浮点数
ret = Send_Measured_value_short_floating_point(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
case USE_YC_ND: //不带品质归一化值
ret = Send_Measured_value_normalised_without_quality(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
default: //USE_YC_NA: 归一化值
ret = Send_Measured_value_normalised(pItem, i, IEC_101_104_COT_INTERROGATION);
break;
}
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Measured_value IEC_101_104_COT_INTERROGATION error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
//激活终止
ret = Send_FrameInterrogation(pItem, i);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_FrameInterrogation error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0)
{
pItem->interrogation_type = 0;
pItem->interrogation_finish = TRUE;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = TRUE;
pItem->interrogation_yc_fin = TRUE;
continue;
}
}
//响应召唤电能脉冲
if (pItem->pulse_start)
{
if (!pItem->pulse_fin)
{
ret = Send_Integrated_totals(pItem, i, IEC_101_104_COT_REQCOGEN);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Integrated_totals error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
//激活终止
ret = Send_FrameCounterInterrogation(pItem, i);
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_FrameCounterInterrogation error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0)
{
pItem->pulse_type = 0;
pItem->pulse_start = FALSE;
pItem->pulse_fin = TRUE;
continue;
}
}
//文件
ret = MakeFileFrame(pItem, i);
if (ret < 0)
{
pItem->Release();
continue;
}
else if (ret > 0)
{
vLog(LOG_DEBUG, "here......MakeFileFrame.\n");
continue;
}
//总召唤没有结束,不上送变位遥测
if (pItem->interrogation_finish)
{ //发送遥测变位
if (sec_changed)
{
switch (m_nOption.yc_type)
{
case USE_YC_NB: //标度化值
ret = Send_Measured_value_scaled(pItem, i);
break;
case USE_YC_NC: //短浮点数
ret = Send_Measured_value_short_floating_point(pItem, i);
break;
case USE_YC_ND: //不带品质归一化值
ret = Send_Measured_value_normalised_without_quality(pItem, i);
break;
default: //USE_YC_NA: 归一化值
ret = Send_Measured_value_normalised(pItem, i);
break;
}
if (ret < 0)
{
vLog(LOG_ERROR, "Unit(%d) Send_Measured_value IEC_101_104_COT_SPONT error.\n", uid);
pItem->Release();
continue;
}
else if (ret > 0) continue;
}
}
}
return TRUE;
}
BOOLEAN CSubGDW104Process::OnIFrameReceived(WORD ns, WORD nr, BYTE* pBuf, int count, int ord)
{
int uid;
CIEC104ProcessItem* pItem = (CIEC104ProcessItem *)GetItem(ord);
if (NULL == pItem) return FALSE;
uid = (int)pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
//处理接收序号
if (!OnDealWithPeerNS(pItem, ns)) return FALSE;
//处理发送序号
if (!OnDealWithPeerNR(pItem, nr)) return FALSE;
//启动t2计时
if (pItem->apdu_t2_begin == 0)
{
pItem->apdu_t2_begin = system32.timers;
}
pItem->apdu_w++;
if (pItem->apdu_w >= pItem->apdu_w_max)
{
if (!SendSFrame(ord)) return FALSE;
}
//重置t3计时
pItem->apdu_t3_begin = system32.timers;
//处理接收到的报文
int ret;
int len;
BYTE buffer[256];
BYTE* pData = pBuf;
BYTE TI;
// BYTE VSQ;
WORD COT;
BYTE cause_of_transmission;
TI = *pData; pData++;
//VSQ = *pData;
pData++;
COT = GetCOT(pData); pData += cot_length;
//判断CA地址是否正确
short apdu_addr = GetAsduAddr(pData); pData += asdu_addr_length;
if (apdu_addr != pItem->apdu_addr)
{
vLog(LOG_WARN, "Unit(%d) invalid CA(%d) received.\n", uid, apdu_addr);
return FALSE;
}
cause_of_transmission = GET_COT(COT);
len = 0;
memset(buffer, 0, sizeof(buffer));
switch (TI)
{
case C_IC_NA_1: //总召唤命令
ret = Receive_Interrogation_command(pItem, pData, cause_of_transmission, buffer, len);
if (NO_ERROR == ret)
{
pItem->interrogation_start = TRUE;
pItem->interrogation_yx_fin = FALSE;
pItem->interrogation_yc_fin = FALSE;
pItem->yx_pos = 0;
pItem->yc_pos = 0;
//清空原先YXBW库
ClearUnitYXBW(uid);
}
break;
case C_SC_NA_1: //单点遥控命令.没有总召唤,不响应遥控报文
if (!pItem->interrogation_finish) return TRUE;
ret = Receive_Single_command(pItem, pData, cause_of_transmission, buffer, len);
break;
case C_DC_NA_1: //双点遥控命令.没有总召唤,不响应遥控报文
if (!pItem->interrogation_finish) return TRUE;
ret = Receive_Double_command(pItem, pData, cause_of_transmission, buffer, len);
break;
case C_CI_NA_1: //脉冲量召唤命令
Receive_Counter_interrogation_command(pItem, pData,cause_of_transmission, buffer, len);
break;
case C_CS_NA_1: //时间同步命令
Receive_Clock_synchronisation_command(pItem, pData, cause_of_transmission, buffer, len);
break;
case C_SE_NA_1: //设定命令,归一化值.没有总召唤,不响应设定报文
if (!pItem->interrogation_finish) return TRUE;
Receive_Set_point_command_normalized(pItem, pData, cause_of_transmission, buffer, len); //设定规一化值命令
break;
case C_SE_NB_1: //设定命令,标度化值.没有总召唤,不响应设定报文
if (!pItem->interrogation_finish) return TRUE;
Receive_Set_point_command_scaled(pItem, pData, cause_of_transmission, buffer, len); //设定标度化值命令
break;
case C_SE_NC_1: //设定命令,短浮点数.没有总召唤,不响应设定报文
if (!pItem->interrogation_finish) return TRUE;
Receive_Set_point_command_short_floating(pItem, pData, cause_of_transmission, buffer, len); //设定短浮点值命令
break;
case GDW_F_FR_NA_1:
Receive_FileTrans(pItem, pData, cause_of_transmission);
break;
default:
vLog(LOG_WARN, "Unit(%d) Unsupported I frame type = 0x%02x\n", uid, (int)pBuf[0]);
len = count;
memcpy(buffer, pBuf, count);
buffer[1] = 1;
SetCOT(&buffer[2], (IEC_101_104_COT_UNKNOWN_TI | IEC_101_104_COT_PN));
}
if (len)
{
return SendIFrame(buffer, len, ord);
}
return TRUE;
}
BOOLEAN CSubGDW104Process::OnUFrameReceived(BOOLEAN STARTDT_ACT, BOOLEAN STARTDT_CON, BOOLEAN STOPDT_ACT, BOOLEAN STOPDT_CON, BOOLEAN TESTFR_ACT, BOOLEAN TESTFR_CON, int ord)
{
int uid;
BYTE phy_addr[6];
CIEC104ProcessItem* pItem = (CIEC104ProcessItem *)GetItem(ord);
if (NULL == pItem) return FALSE;
uid = (int)pItem->GetUnitID();
if (uid < 0 || uid >= UNIT_NUM) return FALSE;
vLog(LOG_DEBUG, "Unit(%d) Received U Frame%s%s%s%s%s%s\n",
uid,
(STARTDT_ACT ? " STARTDT active": ""),
(STOPDT_ACT ? " STOPDT active": ""),
(TESTFR_ACT ? " TESTFR active": ""),
(STARTDT_CON ? " STARTDT confirm": ""),
(STOPDT_CON ? " STOPDT confirm": ""),
(TESTFR_CON ? " TESTFR confirm": ""));
if (STARTDT_ACT)
{
if (!SendUFrame(FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ord)) return FALSE;
//链路链接建立
if (!GetUnitAddr(uid, (BYTE *)phy_addr, 6))
{
pItem->apdu_addr = 0x0001;
}
else
{
pItem->apdu_addr = ((phy_addr[5] << 8) | phy_addr[4]);
}
vLog(LOG_DEBUG, "Unit(%d) apdu_addr(%d)\n", uid, pItem->apdu_addr);
pItem->apdu_setup = TRUE;
pItem->apdu_ns = 0;
pItem->apdu_nr = 0;
pItem->apdu_ack = 0;
pItem->apdu_t3_begin = system32.timers; //启动t3计时
pItem->apdu_wait_test = FALSE;
pItem->apdu_k = 0;
pItem->interrogation_start = FALSE;
pItem->interrogation_yx_fin = FALSE;
pItem->interrogation_yc_fin = FALSE;
pItem->total_yx = GetUnitYXCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total yx count is %d.\n", uid, pItem->total_yx);
pItem->total_yc = GetUnitYCCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total yc count is %d.\n", uid, pItem->total_yc);
pItem->total_ym = GetUnitYMCount(uid);
vLog(LOG_DEBUG, "Unit(%d) total ym count is %d.\n", uid, pItem->total_ym);
pItem->yx_pos = 0;
pItem->yc_pos = 0;
pItem->ym_pos = 0;
//初始化结束帧
if (!pItem->end_of_initialisation)
{
pItem->end_of_initialisation = TRUE;
if (!Send_End_of_initialisation(pItem, ord)) return FALSE;
}
}
if (STARTDT_CON)
{
vLog(LOG_WARN, "UNSUPPORT STARTDT CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (STOPDT_ACT)
{
vLog(LOG_WARN, "UNSUPPORT STOPDT COMMAND! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (STOPDT_CON)
{
vLog(LOG_WARN, "UNSUPPORT STOPDT CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
if (TESTFR_ACT)
{
if (!SendUFrame(FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ord))
{
vLog(LOG_WARN, "Send U Frame Error.\n");
pItem->Release();
return FALSE;
}
pItem->apdu_t1_begin = 0;
pItem->apdu_t3_begin = system32.timers; //重置t3计时
}
if (TESTFR_CON)
{
if (pItem->apdu_wait_test)
{
pItem->apdu_t1_begin = 0;
pItem->apdu_t3_begin = system32.timers; //重置t3计时
pItem->apdu_wait_test = FALSE;
}
else
{
vLog(LOG_WARN, "UNSUPPORT TESTFR CONFIRM! Disconnect link!\n");
pItem->Release();
return FALSE;
}
}
return TRUE;
}
int CSubGDW104Process::MakeYKFrame(CIEC104ProcessItem* pItem, int ord)
{
BYTE buffer[32];
if (NULL == pItem) return -1;
int order;
BYTE value, action, result;
if (!GetUnitYK(pItem->GetUnitID(), order, value, action, result))
{
return 0;
}
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s\n", pItem->GetUnitID(), order, (value ? "CLOSE" : "TRIP"), val_to_str(action, yk_state, "STATE=%d"), val_to_str(result, yk_result, "RESULT=%d"));
memset(buffer, 0, sizeof(buffer));
if (YKS_SELED == action && YKR_FAIL == result)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length] |= IEC_101_104_SE;
action = YKS_ABRED;
}
else if (YKS_SELREQ == action && YKR_OVER == result)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length] |= IEC_101_104_SE;
action = YKS_ABRED;
}
else if (YKS_SELING == action && YKR_OVER == result)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length] |= IEC_101_104_SE;
action = YKS_ABRED;
}
BYTE* param;
BOOLEAN yk_type;
//BYTE relay_type;
DWORD ioa;
param = GetUnitYKParamByPoint(pItem->GetUnitID(), order);
ioa = MAKEDWORD(MAKEWORD(param[0], param[1]), MAKEWORD(param[2], param[3]));
yk_type = param[4];
//relay_type = param[5];
if (yk_type == USE_YK_DC || yk_type == USE_YK_DEF)
{ //双点遥控
buffer[0] = C_DC_NA_1;
buffer[2 + cot_length + asdu_addr_length + info_addr_length] |= value ? DCO_ON : DCO_OFF;
}
else
{
buffer[0] = C_SC_NA_1;
buffer[2 + cot_length + asdu_addr_length + info_addr_length] |= value ? SCO_ON : SCO_OFF;
}
buffer[1] = 1;
if (YKS_SELED == action)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length] |= IEC_101_104_SE;
SetCOT(&buffer[2], IEC_101_104_COT_ACTCON);
m_gdwFile.PushYKLog(system32.now, ioa, value, YKT_SELRET, YKS_PROC, pItem->GetUnitID());
}
else if (YKS_ABRED == action)
{
SetCOT(&buffer[2], IEC_101_104_COT_DEACTCON);
}
else if (YKS_EXEED == action)
{
SetCOT(&buffer[2], IEC_101_104_COT_ACTTREM);
m_gdwFile.PushYKLog(system32.now, ioa, value, YKT_EXERET, YKS_PROC, pItem->GetUnitID());
}
else
{
return 0;
}
SetAsduAddr(&buffer[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&buffer[2 + cot_length + asdu_addr_length], ioa);
if (!SendIFrame(buffer, (3 + cot_length + asdu_addr_length + info_addr_length), ord)) return -1;
return 1;
}
int CSubGDW104Process::MakeYTFrame(CIEC104ProcessItem* pItem, int ord)
{
BYTE buffer[32];
if (NULL == pItem) return -1;
int order;
BYTE action, result;
DWORD value;
if (!GetUnitYT(pItem->GetUnitID(), order, value, action, result))
{
return 0;
}
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is %s result is %s\n", pItem->GetUnitID(), order, value, val_to_str(action, yt_state, "STATE=%d"), val_to_str(result, yt_result, "RESULT=%d"));
memset(buffer, 0, sizeof(buffer));
BYTE* param;
BOOLEAN yt_type;
DWORD ioa;
int data_length = 2;
param = GetUnitYTParamByPoint(pItem->GetUnitID(), order);
ioa = MAKEDWORD(MAKEWORD(param[0], param[1]), MAKEWORD(param[2], param[3]));
yt_type = param[4];
if (yt_type == USE_YT_NA)
{ //双点遥控
data_length = 2;
buffer[0] = C_SE_NA_1;
buffer[2 + cot_length + asdu_addr_length + info_addr_length] = value & 0xff;
buffer[2 + cot_length + asdu_addr_length + info_addr_length + 1] = (value >> 8) & 0xff;
}
else if (yt_type == USE_YT_NB)
{
data_length = 2;
buffer[0] = C_SE_NB_1;
buffer[2 + cot_length + asdu_addr_length + info_addr_length] = value & 0xff;
buffer[2 + cot_length + asdu_addr_length + info_addr_length + 1] = (value >> 8) & 0xff;
}
else
{
data_length = 4;
buffer[0] = C_SE_NC_1;
buffer[2 + cot_length + asdu_addr_length + info_addr_length] = value & 0xff;
buffer[2 + cot_length + asdu_addr_length + info_addr_length + 1] = (value >> 8) & 0xff;
buffer[2 + cot_length + asdu_addr_length + info_addr_length + 2] = (value >> 16) & 0xff;
buffer[2 + cot_length + asdu_addr_length + info_addr_length + 3] = (value >> 24) & 0xff;
}
buffer[1] = 1;
if (YTS_SELED == action && YTR_FAIL == result)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length + data_length] |= IEC_101_104_SE;
action = YTS_ABRED;
}
else if (YTS_SELREQ == action && YTR_OVER == result)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length + data_length] |= IEC_101_104_SE;
action = YTS_ABRED;
}
else if (YTS_SELING == action && YTR_OVER == result)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length + data_length] |= IEC_101_104_SE;
action = YTS_ABRED;
}
if (YTS_SELED == action)
{
buffer[2 + cot_length + asdu_addr_length + info_addr_length + data_length] |= IEC_101_104_SE;
SetCOT(&buffer[2], IEC_101_104_COT_ACTCON);
}
else if (YTS_ABRED == action)
{
SetCOT(&buffer[2], IEC_101_104_COT_DEACTCON);
}
else if (YTS_EXEED == action)
{
SetCOT(&buffer[2], IEC_101_104_COT_ACTTREM);
}
else
{
return FALSE;
}
SetAsduAddr(&buffer[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&buffer[2 + cot_length + asdu_addr_length], ioa);
if (!SendIFrame(buffer, (3 + cot_length + asdu_addr_length + info_addr_length + data_length), ord)) return -1;
return 1;
}
int CSubGDW104Process::MakeFileFrame(CIEC104ProcessItem* pItem, int ord)
{
//BYTE buffer[256];
if (NULL == pItem) return -1;
//文件上送判断
m_dwFileType = m_gdwFile.getCMD();
if (m_dwFileType)
{
if ((m_dwFileType & FIOCMD_VALID) == FIOCMD_READ_DIR)
{
return Send_CallFileDir_Confirm(pItem, m_dwFileType, ord);
}
else if ((m_dwFileType & FIOCMD_VALID) == FIOCMD_OPEN_FILE)
{
return Send_CallFileSel_Confirm(pItem, m_dwFileType, ord);
}
else if ((m_dwFileType & FIOCMD_VALID) == FIOCMD_READ_FILE)
{
return Send_CallFileDat_Ack(pItem, m_dwFileType, ord);
}
}
return 0;
}
int CSubGDW104Process::Receive_Single_command(CIEC104ProcessItem* pItem, const BYTE* pBuf, BYTE cause_of_transmission, BYTE* pTarget, int& count) //单点令
{
BYTE* pData = (BYTE*)pBuf;
BYTE command;
int uid, point;
DWORD information_address;
BOOLEAN value;
BYTE SE;
if (NULL == pItem) return ERROR_UNKNOWN;
information_address = GetInformationAddr(pData); pData += info_addr_length;
command = *pData;
pTarget[0] = C_SC_NA_1;
pTarget[1] = 1;
SetAsduAddr(&pTarget[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&pTarget[2 + cot_length + asdu_addr_length], information_address);
pTarget[2 + cot_length + asdu_addr_length + info_addr_length] = command;
count = 3 + cot_length + asdu_addr_length + info_addr_length;
if (IEC_101_104_COT_ACT == cause_of_transmission || IEC_101_104_COT_DEACT == cause_of_transmission)
{
uid = pItem->GetUnitID();
BYTE ioa[4];
ioa[0] = information_address & 0xff;
ioa[1] = (information_address >> 8) & 0xff;
ioa[2] = (information_address >> 16) & 0xff;
ioa[3] = (information_address >> 24) & 0xff;
point = GetUnitYKPointByParam(uid, ioa, 4);
if (point < 0)
{ //信息体地址错误
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_INFO);
return ERROR_INFORMATION_ADDRESS;
}
SE = GET_SE(command);
value = GET_SCO(command); pData++;
//判断该点是否为单点遥控及参数状态
BYTE* param;
BOOLEAN yk_type;
BYTE relay_type;
param = GetUnitYKParamByPoint(uid, point);
yk_type = param[4];
relay_type = param[5];
if (yk_type != USE_YK_SC)
{ //遥控类型错误,返回否定确认
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
if (relay_type)
{
if (relay_type == 1)
{ //Only on
if (!value)
{
vLog(LOG_ERROR, "Only on,Cann't off!\n");
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
}
else
{ //Only off
if (value)
{
vLog(LOG_ERROR, "Only off,Cann't on!\n");
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
}
}
if (IEC_101_104_COT_ACT == cause_of_transmission)
{ //激活
if (SE)
{ //选择
count = 0;
SetUnitYK(uid, point, value, YKS_SELREQ, YKR_IDLE);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
m_gdwFile.PushYKLog(system32.now, information_address, value, YKT_SELREQ, YKS_PROC, uid);
return NO_ERROR;
}
else
{ //执行
SetUnitYK(uid, point, value, YKS_EXEREQ, YKR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_ACTCON);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
m_gdwFile.PushYKLog(system32.now, information_address, value, YKT_EXEREQ, YKS_PROC, uid);
return NO_ERROR;
}
}
else if (IEC_101_104_COT_DEACT == cause_of_transmission)
{ //激活终止
SetUnitYK(uid, point, value, YKS_ABRREQ, YKR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_DEACTCON);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
m_gdwFile.PushYKLog(system32.now, information_address, value, YKT_ABRREQ, YKS_PROC, uid);
return NO_ERROR;
}
}
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_COT);
return ERROR_CAUSE_OF_TRANSMISSION;
}
int CSubGDW104Process::Receive_Double_command(CIEC104ProcessItem* pItem, const BYTE* pBuf, BYTE cause_of_transmission, BYTE* pTarget, int& count) //单点令
{
BYTE* pData = (BYTE*)pBuf;
BYTE command;
int uid, point;
DWORD information_address;
BOOLEAN value;
BYTE SE;
if (NULL == pItem) return ERROR_UNKNOWN;
information_address = GetInformationAddr(pData); pData += info_addr_length;
command = *pData;
pTarget[0] = C_DC_NA_1;
pTarget[1] = 1;
SetAsduAddr(&pTarget[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&pTarget[2 + cot_length + asdu_addr_length], information_address);
pTarget[2 + cot_length + asdu_addr_length + info_addr_length] = command;
count = 3 + cot_length + asdu_addr_length + info_addr_length;
if (IEC_101_104_COT_ACT == cause_of_transmission || IEC_101_104_COT_DEACT == cause_of_transmission)
{
uid = pItem->GetUnitID();
BYTE ioa[4];
ioa[0] = information_address & 0xff;
ioa[1] = (information_address >> 8) & 0xff;
ioa[2] = (information_address >> 16) & 0xff;
ioa[3] = (information_address >> 24) & 0xff;
point = GetUnitYKPointByParam(uid, ioa, 4);
if (point < 0)
{
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_INFO);
count = 3 + cot_length + asdu_addr_length + info_addr_length;
return ERROR_INFORMATION_ADDRESS;
}
SE = GET_SE(command);
value = GET_DCO(command); pData++;
//判断该点是否为单点遥控及参数状态
BYTE* param;
BOOLEAN yk_type;
//BYTE relay_type;
param = GetUnitYKParamByPoint(uid, point);
yk_type = param[4];
//relay_type = param[5];
if (yk_type == USE_YK_SC)
{ //遥控类型错误,返回否定确认
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
if (IEC_101_104_COT_ACT == cause_of_transmission)
{ //激活
if (SE)
{ //选择
count = 0;
SetUnitYK(uid, point, value, YKS_SELREQ, YKR_IDLE);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
m_gdwFile.PushYKLog(system32.now, information_address, value, YKT_SELREQ, YKS_PROC, uid);
return NO_ERROR;
}
else
{ //执行
SetUnitYK(uid, point, value, YKS_EXEREQ, YKR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_ACTCON);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
m_gdwFile.PushYKLog(system32.now, information_address, value, YKT_EXEREQ, YKS_PROC, uid);
return NO_ERROR;
}
}
else if (IEC_101_104_COT_DEACT == cause_of_transmission)
{ //激活终止
SetUnitYK(uid, point, value, YKS_ABRREQ, YKR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_DEACTCON);
vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRREQ result is YKR_IDLE.\n", uid, point, (value ? "CLOSE" : "TRIP"));
m_gdwFile.PushYKLog(system32.now, information_address, value, YKT_ABRREQ, YKS_PROC, uid);
return NO_ERROR;
}
}
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_COT);
return ERROR_CAUSE_OF_TRANSMISSION;
}
int CSubGDW104Process::Receive_Set_point_command_normalized(CIEC104ProcessItem* pItem, const BYTE* pBuf, BYTE cause_of_transmission, BYTE* pTarget, int& count) //设定规一化值命令
{
BYTE* pData = (BYTE*)pBuf;
BYTE command;
int uid, point;
int information_address;
WORD value = 0;
BYTE SE;
if (NULL == pItem) return ERROR_UNKNOWN;
information_address = GetInformationAddr(pData);
pData += info_addr_length;
value = (WORD)(pData[0] | pData[1] << 8);
pData += 2;
command = *pData;
pTarget[0] = C_SE_NA_1;
pTarget[1] = 1;
SetAsduAddr(&pTarget[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&pTarget[2 + cot_length + asdu_addr_length], information_address);
pTarget[2 + cot_length + asdu_addr_length + info_addr_length] = value & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 1] = (value >> 8) & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 2] = command;
count = 3 + cot_length + asdu_addr_length + info_addr_length + 2;
if (IEC_101_104_COT_ACT == cause_of_transmission || IEC_101_104_COT_DEACT == cause_of_transmission)
{
uid = pItem->GetUnitID();
BYTE ioa[4];
ioa[0] = information_address & 0xff;
ioa[1] = (information_address >> 8) & 0xff;
ioa[2] = (information_address >> 16) & 0xff;
ioa[3] = (information_address >> 24) & 0xff;
point = GetUnitYTPointByParam(uid, ioa, 4);
if (point < 0)
{
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_INFO);
count = 3 + cot_length + asdu_addr_length + info_addr_length + 2;
return ERROR_INFORMATION_ADDRESS;
}
SE = GET_SE(command);
//判断该点是否为单点遥控及参数状态
BYTE* param;
BOOLEAN yt_type;
param = GetUnitYTParamByPoint(pItem->GetUnitID(), point);
yt_type = param[4];
if (yt_type != USE_YT_NA)
{ //遥控类型错误,返回否定确认
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
if (IEC_101_104_COT_ACT == cause_of_transmission)
{ //激活
if (SE)
{ //选择
count = 0;
SetUnitYT(uid, point, value, YTS_SELREQ, YTR_IDLE);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_SELREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
else
{ //执行
SetUnitYT(uid, point, value, YTS_EXEREQ, YTR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_ACTCON);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
}
else if (IEC_101_104_COT_DEACT == cause_of_transmission)
{ //激活终止
SetUnitYT(uid, point, value, YTS_ABRREQ, YTR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_DEACTCON);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
}
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_COT);
return ERROR_CAUSE_OF_TRANSMISSION;
}
int CSubGDW104Process::Receive_Set_point_command_scaled(CIEC104ProcessItem* pItem, const BYTE* pBuf, BYTE cause_of_transmission, BYTE* pTarget, int& count) //设定标度化值命令
{
BYTE* pData = (BYTE*)pBuf;
BYTE command;
int uid, point;
int information_address;
WORD value = 0;
BYTE SE;
if (NULL == pItem) return ERROR_UNKNOWN;
information_address = GetInformationAddr(pData);
pData += info_addr_length;
value = (WORD)(pData[0] | pData[1] << 8);
pData += 2;
command = *pData;
pTarget[0] = C_SE_NB_1;
pTarget[1] = 1;
SetAsduAddr(&pTarget[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&pTarget[2 + cot_length + asdu_addr_length], information_address);
pTarget[2 + cot_length + asdu_addr_length + info_addr_length] = value & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 1] = (value >> 8) & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 2] = command;
count = 3 + cot_length + asdu_addr_length + info_addr_length + 2;
if (IEC_101_104_COT_ACT == cause_of_transmission || IEC_101_104_COT_DEACT == cause_of_transmission)
{
uid = pItem->GetUnitID();
BYTE ioa[4];
ioa[0] = information_address & 0xff;
ioa[1] = (information_address >> 8) & 0xff;
ioa[2] = (information_address >> 16) & 0xff;
ioa[3] = (information_address >> 24) & 0xff;
point = GetUnitYTPointByParam(uid, ioa, 4);
if (point < 0)
{
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_INFO);
count = 3 + cot_length + asdu_addr_length + info_addr_length + 2;
return ERROR_INFORMATION_ADDRESS;
}
SE = GET_SE(command);
//判断该点是否为单点遥控及参数状态
BYTE* param;
BOOLEAN yt_type;
param = GetUnitYTParamByPoint(pItem->GetUnitID(), point);
yt_type = param[4];
if (yt_type != USE_YT_NB)
{ //遥控类型错误,返回否定确认
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
if (IEC_101_104_COT_ACT == cause_of_transmission)
{ //激活
if (SE)
{ //选择
count = 0;
SetUnitYT(uid, point, value, YTS_SELREQ, YTR_IDLE);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_SELREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
else
{ //执行
SetUnitYT(uid, point, value, YTS_EXEREQ, YTR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_ACTCON);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
}
else if (IEC_101_104_COT_DEACT == cause_of_transmission)
{ //激活终止
SetUnitYT(uid, point, value, YTS_ABRREQ, YTR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_DEACTCON);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
}
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_COT);
return ERROR_CAUSE_OF_TRANSMISSION;
}
int CSubGDW104Process::Receive_Set_point_command_short_floating(CIEC104ProcessItem* pItem, const BYTE* pBuf, BYTE cause_of_transmission, BYTE* pTarget, int& count) //设定短浮点值命令
{
BYTE* pData = (BYTE*)pBuf;
BYTE command;
int uid, point;
int information_address;
DWORD value;
BYTE SE;
if (NULL == pItem) return ERROR_UNKNOWN;
information_address = GetInformationAddr(pData);
pData += info_addr_length;
value = (DWORD)(pData[0] | (pData[1] << 8) | (pData[2] << 16) | (pData[3] << 24));
pData += 4;
command = *pData;
pTarget[0] = C_SE_NC_1;
pTarget[1] = 1;
SetAsduAddr(&pTarget[2 + cot_length], pItem->apdu_addr);
SetInformationAddr(&pTarget[2 + cot_length + asdu_addr_length], information_address);
pTarget[2 + cot_length + asdu_addr_length + info_addr_length] = value & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 1] = (value >> 8) & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 2] = (value >> 16) & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 3] = (value >> 24) & 0xff;
pTarget[2 + cot_length + asdu_addr_length + info_addr_length + 4] = command;
count = 3 + cot_length + asdu_addr_length + info_addr_length + 4;
if (IEC_101_104_COT_ACT == cause_of_transmission || IEC_101_104_COT_DEACT == cause_of_transmission)
{
uid = pItem->GetUnitID();
BYTE ioa[4];
ioa[0] = information_address & 0xff;
ioa[1] = (information_address >> 8) & 0xff;
ioa[2] = (information_address >> 16) & 0xff;
ioa[3] = (information_address >> 24) & 0xff;
point = GetUnitYTPointByParam(uid, ioa, 4);
if (point < 0)
{
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_INFO);
count = 3 + cot_length + asdu_addr_length + info_addr_length + 4;
return ERROR_INFORMATION_ADDRESS;
}
SE = GET_SE(command);
//判断该点是否为单点遥控及参数状态
BYTE* param;
BOOLEAN yt_type;
param = GetUnitYTParamByPoint(pItem->GetUnitID(), point);
yt_type = param[4];
if (yt_type != USE_YT_NC)
{ //遥控类型错误,返回否定确认
SetCOT(&pTarget[2], ((cause_of_transmission + 1) | IEC_101_104_COT_PN));
return ERROR_PARAM;
}
if (IEC_101_104_COT_ACT == cause_of_transmission)
{ //激活
if (SE)
{ //选择
count = 0;
SetUnitYT(uid, point, value, YTS_SELREQ, YTR_IDLE);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_SELREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
else
{ //执行
SetUnitYT(uid, point, value, YTS_EXEREQ, YTR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_ACTCON);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
}
else if (IEC_101_104_COT_DEACT == cause_of_transmission)
{ //激活终止
SetUnitYT(uid, point, value, YTS_ABRREQ, YTR_IDLE);
SetCOT(&pTarget[2], IEC_101_104_COT_DEACTCON);
vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, point, value);
return NO_ERROR;
}
}
SetCOT(&pTarget[2], IEC_101_104_COT_UNKNOWN_COT);
return ERROR_CAUSE_OF_TRANSMISSION;
}
int CSubGDW104Process::Receive_FileTrans(CIEC104ProcessItem* pItem, const BYTE* pBuf, BYTE cause_of_transmission) //读取文件
{
BYTE* pData = (BYTE*)pBuf;
if (NULL == pItem) return ERROR_UNKNOWN;
int information_address = GetInformationAddr(pData); pData += info_addr_length;
if (information_address != 0) return ERROR_CAUSE_OF_TRANSMISSION;
BYTE frameType = *pData; pData++;
if (frameType != FILE_TRS_TYPE) return ERROR_UNKNOWN;
BYTE command = *pData; pData++;
if (command == ReadFileDirAct)
{
return parseFileReadDirAct(pItem, pData);
}
else if (command == ReadFileSelAct)
{
return parseFileReadFileSelAct(pItem, pData);
}
else if (command == ReadFileDataCon)
{
return parseFileReadFileDataCon(pItem, pData);
}
else if (command == WriteFileSelAct)
{
}
else if (command == WriteFileDataAct)
{
}
else
{
vLog(LOG_ERROR, "文件传输报文错误,不识别的操作标识 = %d.\n", command);
}
return ERROR_UNKNOWN;
}
BOOLEAN CSubGDW104Process::parseFileReadDirAct(CIEC104ProcessItem* pItem, const BYTE* pData)
{
DWORD dirID = (DWORD)(pData[0] | (pData[1] << 8) | (pData[2] << 16) | (pData[3] << 24)); pData += 4;
BYTE dirNameLength = *pData; pData++;
char dirName[FILE_PATH_LEN];
memset(dirName, '\0', sizeof(dirName));
if (dirNameLength > 0)
{
memcpy(dirName, pData, dirNameLength);
pData += dirNameLength;
}
BYTE callFlag = *pData; pData++;
BOOLEAN callAllFiles = (callFlag == 0) ? TRUE : FALSE;
unionCP56Time startTime;
memcpy(&startTime, &system32.now, sizeof(startTime));
unionCP56Time endTime;
memcpy(&endTime, &system32.now, sizeof(endTime));
if (!callAllFiles)
{
startTime.millisecond = *pData; pData++;
startTime.millisecond |= (*pData << 8); pData++;
startTime.minute = *pData & 0x3f;
startTime.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
startTime.hour = *pData & 0x1f;
startTime.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
startTime.dayofmonth = *pData & 0x1f;
startTime.dayofweek = ((*pData & 0xe0) >> 5); pData++;
startTime.month = *pData & 0x0f; pData++;
startTime.year = *pData & 0x7f; pData++;
endTime.millisecond = *pData; pData++;
endTime.millisecond |= (*pData << 8); pData++;
endTime.minute = *pData & 0x3f;
endTime.IV = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
endTime.hour = *pData & 0x1f;
endTime.SU = (*pData & 0x80) == 0x80 ? TRUE : FALSE; pData++;
endTime.dayofmonth = *pData & 0x1f;
endTime.dayofweek = ((*pData & 0xe0) >> 5); pData++;
endTime.month = *pData & 0x0f; pData++;
endTime.year = *pData & 0x7f; pData++;
}
//判断文件目录
memset(&m_FileDir, 0, sizeof(stCallFileDir));
m_FileDir.allfile = callAllFiles;
strcpy(m_FileDir.dirname, dirName);
m_FileDir.loadptr = 0;
m_FileDir.dirID = dirID;
m_gdwFile.ReadDir(dirName, callAllFiles, startTime, endTime);
return TRUE;
}
BOOLEAN CSubGDW104Process::parseFileReadFileSelAct(CIEC104ProcessItem* pItem, const BYTE* pData)
{
int fileNameLen = 0;
fileNameLen = *pData; pData++;
if (fileNameLen <= 0)
{
vLog(LOG_ERROR, "文件名长度错误,文件名长度 = %d\n", fileNameLen);
return FALSE;
}
char fileName[FILE_PATH_LEN];
memset(fileName, '\0', sizeof(fileName));
memcpy(fileName, pData, fileNameLen); pData += fileNameLen;
strcpy(m_FileDir.filename, fileName);
m_FileDir.length = m_gdwFile.FileLength(fileName);
m_gdwFile.OpenFile(fileName);
return TRUE;
}
BOOLEAN CSubGDW104Process::parseFileReadFileDataCon(CIEC104ProcessItem* pItem, const BYTE* pData)
{
LONG fileID = (DWORD)(pData[0] | (pData[1] << 8) | (pData[2] << 16) | (pData[3] << 24)); pData += 4;
LONG filePos = (DWORD)(pData[0] | (pData[1] << 8) | (pData[2] << 16) | (pData[3] << 24)); pData += 4;
vLog(LOG_DEBUG, "收到文件ID = %d 传输确认,数据段号 = %d, 原始文件应有长度 = %d\n", fileID, filePos, m_FileDir.length);
m_gdwFile.CloseFile();
return FALSE;
}
int CSubGDW104Process::Send_FileDir(CIEC104ProcessItem* pItem, BOOLEAN bErr, BOOLEAN follow, int count, int pos, int ord)
{
int len = 0;
BYTE buffer[1024];
if (pItem == NULL) return -1;
buffer[len++] = GDW_F_FR_NA_1;
buffer[len++] = 0; //VSQ此处无效
SetCOT(&buffer[len], IEC_101_104_COT_ACTCON); len += cot_length;
SetAsduAddr(&buffer[len], pItem->apdu_addr); len += asdu_addr_length;
SetInformationAddr(&buffer[len], 0); len += info_addr_length;
buffer[len++] = FILE_TRS_TYPE; //文件传输
buffer[len++] = ReadFileDirCon; //读目录
if (bErr)
{
buffer[len++] = 1;
if (!SendIFrame(buffer, len, ord)) return -1;
return 1;
}
//结果描述字
buffer[len++] = 0; //成功
//目录ID
buffer[len++] = (m_FileDir.dirID & 0xff);
buffer[len++] = ((m_FileDir.dirID >> 8) & 0xff);
buffer[len++] = ((m_FileDir.dirID >> 16) & 0xff);
buffer[len++] = ((m_FileDir.dirID >> 24) & 0xff);
buffer[len++] = follow; //无后续
buffer[len++] = count; //文件数量
for (int i = 0; i < count; i++)
{
std::string filename = m_gdwFile.FileName(i + pos);
//名称长度
buffer[len++] = filename.length();
//文件名称
for (int j = 0; j < (int)filename.length(); j ++)
{
buffer[len++] = filename[j];
}
//文件属性
buffer[len++] = 0;
//文件大小
len += ValToBuf(&buffer[len], m_gdwFile.FileLength(i + pos), 4);
//文件时间
unionCP56Time ct;
ct = Time_ttounionCP56Time(m_gdwFile.FileTime(i + pos));
len += unionCP56TimeToBuf(&buffer[len], ct);
}
if (!SendIFrame(buffer, len, ord)) return -1;
return 1;
}
int CSubGDW104Process::Send_CallFileDir_Confirm(CIEC104ProcessItem* pItem, DWORD cmd, int ord)
{
if (cmd & CMD_EXEC_ERR)
{
return Send_FileDir(pItem, TRUE, FALSE, 0, 0, ord);
}
int count = m_gdwFile.FileCount();
//默认文件名长度为32个字节
//一个文件信息长度为文件名称长度1+文件名长度32+文件属性1+文件大小4+文件时间7
//默认一个文件信息占用48字节
//到此信息计算出一帧报文所能携带文件个数
int acount = (max_frame - 17 - cot_length - asdu_addr_length - info_addr_length) / 48; // = 4
int full_frame = count / acount;
int si_frame = count % acount;
int pos = 0;
for (int i = 0; i < full_frame; i++)
{
Send_FileDir(pItem, FALSE, TRUE, acount, pos, ord);
pos += acount;
}
if (si_frame) Send_FileDir(pItem, FALSE, FALSE, si_frame, pos, ord);
return 1;
}
int CSubGDW104Process::Send_CallFileSel_Confirm(CIEC104ProcessItem* pItem, DWORD cmd, int ord)
{
int len = 0;
BYTE buffer[1024];
if (pItem == NULL) return -1;
buffer[len++] = GDW_F_FR_NA_1;
buffer[len++] = 0; //VSQ此处无效
SetCOT(&buffer[len], IEC_101_104_COT_ACTCON); len += cot_length;
SetAsduAddr(&buffer[len], pItem->apdu_addr); len += asdu_addr_length;
SetInformationAddr(&buffer[len], 0); len += info_addr_length;
buffer[len++] = FILE_TRS_TYPE; //文件传输
buffer[len++] = ReadFileSelCon; //读文件激活确认
if (cmd & CMD_EXEC_ERR)
{
//结果描述字
buffer[len++] = 1; //失败
//没有文件
if (!SendIFrame(buffer, len, ord)) return -1;
return 1;
}
//结果描述字
buffer[len++] = 0; //成功
std::string filename = m_FileDir.filename;
//名称长度
buffer[len++] = filename.length();
//文件名称
for (int j = 0; j < (int)filename.length(); j ++)
{
buffer[len++] = filename[j];
}
//文件ID
len += ValToBuf(&buffer[len], 0, 4);
//文件大小
len += ValToBuf(&buffer[len], m_FileDir.length, 4);
if (!SendIFrame(buffer, len, ord)) return -1;
m_gdwFile.ReadFile();
return 1;
}
int CSubGDW104Process::Send_CallFileDat_Ack(CIEC104ProcessItem* pItem, DWORD cmd, int ord)
{
int len = 0;
BYTE buffer[1024];
if (pItem == NULL) return -1;
buffer[len++] = GDW_F_FR_NA_1;
buffer[len++] = 0; //VSQ此处无效
SetCOT(&buffer[len], IEC_101_104_COT_ACTCON); len += cot_length;
SetAsduAddr(&buffer[len], pItem->apdu_addr); len += asdu_addr_length;
SetInformationAddr(&buffer[len], 0); len += info_addr_length;
buffer[len++] = FILE_TRS_TYPE; //文件传输
buffer[len++] = ReadFileDataAct; //读文件激活确认
//文件ID
len += ValToBuf(&buffer[len], 0, 4);
//结果描述字
len += m_gdwFile.FileData(&buffer[len]);
if (!SendIFrame(buffer, len, ord)) return -1;
return 1;
}