2543 lines
92 KiB
C++
2543 lines
92 KiB
C++
#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->call_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->call_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->call_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->call_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;
|
||
}
|