map/das-dn/comm/public.cpp

1470 lines
41 KiB
C++
Raw Normal View History

2024-07-08 10:27:17 +08:00
#include "public.h"
#include "soe.h"
#include "ycbw.h"
#include "yxbw.h"
#include "yklog.h"
#include "ytlog.h"
#include "process.h"
#include "iec_101_104_lib.h"
#include <signal.h>
#include <iostream>
#include <fstream>
#ifdef USE_SQLITE3
#include "KompexSQLitePrerequisites.h"
#include "KompexSQLiteDatabase.h"
#include "KompexSQLiteStatement.h"
#include "KompexSQLiteException.h"
#include "KompexSQLiteStreamRedirection.h"
#include "KompexSQLiteBlob.h"
using namespace Kompex;
#endif
#include "json.h"
2024-11-27 11:56:30 +08:00
#include "ry.h"
2024-07-08 10:27:17 +08:00
#define PARAMTER_TYPE_MODBUS 1
#define PARAMTER_TYPE_104 2
#define PARAMTER_TYPE_9712 3
#define MAX_THREAD_NUM 2
#define THREAD_ID_MAIN 0
#define THREAD_ID_IDLE 1
BOOLEAN systemRunFlag = FALSE;
BOOLEAN synchronized = FALSE;
BOOLEAN zlog_inited = FALSE;
struSystem system32;
struConfig config;
struDatabase database;
CYCBW ycbw;
CYXBW yxbw;
CSOE soe;
CYKLog yklog;
CYTLog ytlog;
CProcess* procs[PROCESSES_NUM];
struUnitStatic static_units[UNIT_NUM];
struDispBuffer channelBuffer;
struMsgBuffer msgBuffer;
struNodeOption nodes;
char configpath[MAX_PATH] = "./conf"; //配置文件所在目录
char configfile[MAX_PATH] = "./conf/config.db"; //配置文件
QWORD system_timems;
2024-12-03 10:36:06 +08:00
#ifndef USE_NOPOLL_WEBSOCKET
2024-11-27 11:56:30 +08:00
CRYDevice* g_conn;
#else
2024-10-21 10:53:15 +08:00
noPollConn *g_conn;
2024-11-27 11:56:30 +08:00
#endif
2024-10-21 10:53:15 +08:00
Snowflake g_sf = {1, 1, 0, 0};
2024-07-08 10:27:17 +08:00
static eLogLevel eLevelMax = LOG_DEBUG; //LOG_DEBUG;
static const char* arszLevel2Str[] = { "NULL", "ERROR", "WARN", "INFO", "DEBUG" };
static pthread_t p_id[MAX_THREAD_NUM];
static DWORD WriteMsgRingBuff(const char *wbuff, DWORD len)
{
DWORD l;
if (msgBuffer.buf == NULL) return -1;
len = wMin(len, MAX_DISPLAY_BUFFER_SIZE - msgBuffer.save + msgBuffer.load);
/* 第一部分的拷贝:从环形缓冲区写入数据直至缓冲区最后一个地址 */
l = wMin(len, MAX_DISPLAY_BUFFER_SIZE - (msgBuffer.save & (MAX_DISPLAY_BUFFER_SIZE - 1)));
memcpy(msgBuffer.buf + (msgBuffer.save & (MAX_DISPLAY_BUFFER_SIZE - 1)), wbuff, l);
/* 如果溢出则在缓冲区头写入剩余的部分如果没溢出这句代码相当于无效 */
memcpy(msgBuffer.buf, wbuff + l, len - l);
msgBuffer.save += len;
return len;
}
DWORD ReadMsgRingBuff(char *rbuff, DWORD len)
{
DWORD l;
if (msgBuffer.buf == NULL) return -1;
len = wMin(len, msgBuffer.save - msgBuffer.load);
/* 第一部分的拷贝:从环形缓冲区读取数据直至缓冲区最后一个 */
l = wMin(len, MAX_DISPLAY_BUFFER_SIZE - (msgBuffer.load & (MAX_DISPLAY_BUFFER_SIZE - 1)));
memcpy(rbuff, msgBuffer.buf + (msgBuffer.load & (MAX_DISPLAY_BUFFER_SIZE - 1)), l);
/* 如果溢出则在缓冲区头读取剩余的部分如果没溢出这句代码相当于无效 */
memcpy(rbuff + l, msgBuffer.buf, len - l);
msgBuffer.load += len;
return len;
}
void vLog(eLogLevel eLevel, const char* szFmt, ...)
{
if (eLevel <= eLevelMax)
{
int len;
char buffer[4096]; //dlt698.45-1867可能会比较长的报文.此处避免错误
va_list args;
len = snprintf(buffer, sizeof(buffer), "%04d/%02d/%02d %02d:%02d:%02d.%03d ",\
system32.now.year+2000, system32.now.month, system32.now.dayofmonth,\
system32.now.hour, system32.now.minute, system32.now.millisecond / 1000, system32.now.millisecond % 1000);
WriteMsgRingBuff(buffer, len);
len = snprintf(buffer, sizeof(buffer), "%s: ", arszLevel2Str[eLevel]);
WriteMsgRingBuff(buffer, len);
va_start(args, szFmt);
len = vsnprintf(buffer, sizeof(buffer), szFmt, args);
va_end(args);
WriteMsgRingBuff(buffer, len);
if (zlog_inited)
{
if (eLevel == LOG_DEBUG) dzlog_debug("%s", buffer);
else if (eLevel == LOG_INFO) dzlog_info("%s", buffer);
else if (eLevel == LOG_WARN) dzlog_warn("%s", buffer);
else if (eLevel == LOG_ERROR) dzlog_error("%s", buffer);
}
}
}
int GetFileSize(const char* fname)
{
struct stat statbuf;
if (stat(fname,&statbuf) == 0)
{
return statbuf.st_size;
}
return -1;
}
const char* match_strval_idx(DWORD val, const value_string* vs, int* idx)
{
int i = 0;
if (vs)
{
while (vs[i].strptr)
{
if (vs[i].value == val)
{
*idx = i;
return(vs[i].strptr);
}
i++;
}
}
*idx = -1;
return NULL;
}
char* ep_strdup_printf(const char* fmt, ...)
{
va_list ap;
char* dst;
dst = new char[2048];
if (dst == NULL) return NULL;
memset(dst, 0, 2048);
va_start(ap, fmt);
vsnprintf(dst, 2048, fmt, ap);
va_end(ap);
return dst;
}
const char* match_strval(DWORD val, const value_string* vs)
{
int ignore_me;
return match_strval_idx(val, vs, &ignore_me);
}
const char* val_to_str(DWORD val, const value_string* vs, const char* fmt)
{
const char* ret;
if (fmt == NULL) return NULL;
ret = match_strval(val, vs);
if (ret != NULL) return ret;
return ep_strdup_printf(fmt, val);
}
void StringToHex(const char* pStr, BYTE* pData)
{
int i;
BYTE data;
int len = strlen(pStr);
char* pBuf = (char*)pStr;
for (i = 0; i < len; i++, pBuf++)
{
if (*pBuf >= '0' && *pBuf <= '9')
{
data = *pBuf - '0';
}
else if (*pBuf >= 'a' && *pBuf <= 'f')
{
data = *pBuf - 'a' + 0x0a;
}
else if (*pBuf >= 'A' && *pBuf <= 'F')
{
data = *pBuf - 'A' + 0x0a;
}
else
{
break;
}
data = data << 4;
i++, pBuf++;
if (*pBuf >= '0' && *pBuf <= '9')
{
data |= *pBuf - '0';
}
else if (*pBuf >= 'a' && *pBuf <= 'f')
{
data |= *pBuf - 'a' + 0x0a;
}
else if (*pBuf >= 'A' && *pBuf <= 'F')
{
data |= *pBuf - 'A' + 0x0a;
}
else
{
break;
}
*pData = data;
pData++;
}
}
void HexToString(const BYTE* pData, char* pStr, int count)
{
int i;
char text[16];
BYTE* pCurData = (BYTE*)pData;
strcpy(pStr, "");
for (i = 0; i < count; i++, pCurData++)
{
sprintf(text, "%02X", (int)(*pCurData));
strcat(pStr, text);
}
count = count << 1;
for (i = count-1; i > 0; i -= 2)
{
if (pStr[i] == '0' && pStr[i-1] == '0')
{
pStr[i-1] = '\0';
}
else
{
break;
}
}
if (pStr[0] == '\0')
{
strcpy(pStr, "00");
}
}
DWORD bcd_to_int(const BYTE *bcd, int length)
{
DWORD result = 0;
for (; length > 0;)
{
length--;
result *= 10;
result += (bcd[length] >> 4) & 0x0f;
result *= 10;
result += bcd[length] & 0x0f;
}
return result;
}
void int_to_bcd(int dec, BYTE *bcd, int length)
{
int i;
int temp;
for (i = length - 1; i >= 0; i--)
{
temp = dec % 100;
bcd[i] = ((temp / 10) << 4) + ((temp % 10) & 0x0F);
dec /= 100;
}
}
int ValToBuf(BYTE* buf, DWORD val, int lenth, BOOLEAN bBigEndian)
{
if (lenth <= 0) return 0;
for (int i = 0; i < lenth; i++)
{
if (bBigEndian)
{
buf[lenth - (i + 1)] = (val >> (i << 3)) & 0xff;
}
else
{
buf[i] = (val >> (i << 3)) & 0xff;
}
}
return lenth;
}
DWORD BufToVal(BYTE* buf, int lenth, BOOLEAN bBigEndian)
{
DWORD sum = 0;
if (lenth <= 0) return 0;
for (int i = 0; i < lenth; i++)
{
if (bBigEndian)
{
sum += buf[lenth - (i + 1)] << (i << 3);
}
else
{
sum += buf[i] << (i << 3);
}
}
return sum;
}
2024-11-15 16:12:14 +08:00
std::vector<std::string> split(const std::string &s, char delimiter)
{
std::vector<std::string> tokens;
std::istringstream tokenStream(s);
std::string token;
while (std::getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}
// 计算新字符串的长度,考虑到每个指定字符都可能被替换为更长的转义序列
size_t calculate_escaped_length(const char *str, char escape_char)
{
size_t length = 0;
size_t i;
for (i = 0; str[i] != '\0'; i++)
{
if (str[i] == escape_char)
{
length += 3; // 每个指定字符替换为"\xXX"形式长度为3
}
else
{
length += 1; // 其他字符保持不变
}
}
return length + 1; // 加1是为了字符串末尾的空字符
}
// 实现字符转义
char* escape_char_in_string(const char *str, char escape_char)
{
size_t new_length = calculate_escaped_length(str, escape_char);
char *escaped_str = (char *)malloc(new_length);
if (escaped_str == NULL)
{
return NULL; // 内存分配失败
}
size_t j = 0;
for (size_t i = 0; str[i] != '\0'; i++)
{
if (str[i] == escape_char)
{
sprintf(escaped_str + j, "%s", "\%20");
j += 3;
}
else
{
escaped_str[j++] = str[i];
}
}
escaped_str[j] = '\0'; // 添加字符串末尾的空字符
return escaped_str;
}
2024-07-08 10:27:17 +08:00
int unionCP56TimeToBuf(BYTE* buf, unionCP56Time st)
{
int len = 0;
len = ValToBuf(buf, st.millisecond, 2);
buf[len++] = st.minute;
buf[len++] = st.hour;
buf[len++] = st.dayofmonth;
buf[len++] = st.month;
buf[len++] = st.year;
return len;
}
QWORD getTimeInMs()
{
return system_timems;
}
BOOLEAN get_system_time(unionCP56Time* lpSystemTime)
{
struct timeval tv;
struct tm stru_tmp;
if (gettimeofday(&tv, NULL) < 0) return FALSE;
localtime_r(&tv.tv_sec, &stru_tmp);
lpSystemTime->millisecond = (WORD)((stru_tmp.tm_sec * 1000) + (tv.tv_usec / 1000));
lpSystemTime->minute = stru_tmp.tm_min;
lpSystemTime->hour = stru_tmp.tm_hour;
lpSystemTime->dayofmonth = stru_tmp.tm_mday;
lpSystemTime->dayofweek = stru_tmp.tm_wday;
lpSystemTime->month = stru_tmp.tm_mon + 1;
lpSystemTime->year = stru_tmp.tm_year + 1900 - 2000;
system32.timers = (DWORD)tv.tv_sec;
system_timems = ((QWORD) tv.tv_sec * 1000LL) + (tv.tv_usec / 1000);
return TRUE;
}
int write_to_hardclock()// for linux
{
FILE *fp = NULL;
fp = popen("hwclock -w","r");
if (fp == NULL) return 0;
pclose(fp);
return 1;
}
BOOLEAN set_system_time(unionCP56Time* lpSystemTime)
{
struct timeval tv;
struct tm p;
time_t temp;
if (gettimeofday(&tv, NULL) < 0)
{
vLog(LOG_ERROR, "gettimeofday error(%d,%s).\n", errno, strerror(errno));
return FALSE;
}
localtime_r(&tv.tv_sec, &p);
p.tm_year = lpSystemTime->year + 2000 - 1900;
p.tm_mon = lpSystemTime->month - 1;
p.tm_mday = lpSystemTime->dayofmonth;
p.tm_hour = lpSystemTime->hour;
p.tm_min = lpSystemTime->minute;
p.tm_sec = lpSystemTime->millisecond / 1000;
temp = mktime(&p);
tv.tv_sec = (long)temp;
tv.tv_usec = lpSystemTime->millisecond % 1000;
if (settimeofday(&tv, NULL) < 0)
{
vLog(LOG_ERROR, "settimeofday error(%d,%s).\n", errno, strerror(errno));
return FALSE;
}
vLog(LOG_DEBUG, "system synchronized!\r\n");
synchronized = TRUE;
vLog(LOG_DEBUG, "system clock synchronized! %04d/%02d/%02d %02d:%02d:%02d=>%04d/%02d/%02d %02d:%02d:%02d\n",
system32.now.year+2000, system32.now.month, system32.now.dayofmonth,
system32.now.hour, system32.now.minute, system32.now.millisecond / 1000,
lpSystemTime->year + 2000, lpSystemTime->month, lpSystemTime->dayofmonth,
lpSystemTime->hour, lpSystemTime->minute, lpSystemTime->millisecond / 1000);
return TRUE;
}
time_t unionCP56TimetoTime_t(unionCP56Time* st)
{
time_t temp;
struct timeval tv;
struct tm p;
if (gettimeofday(&tv, NULL) < 0)
{
vLog(LOG_ERROR, "gettimeofday error(%d,%s).\n", errno, strerror(errno));
return FALSE;
}
localtime_r(&tv.tv_sec, &p);
p.tm_year = st->year + 2000 - 1900;
p.tm_mon = st->month - 1;
p.tm_mday = st->dayofmonth;
p.tm_hour = st->hour;
p.tm_min = st->minute;
p.tm_sec = st->millisecond / 1000;
temp = mktime(&p);
return temp;
}
unionCP56Time Time_ttounionCP56Time(time_t st)
{
unionCP56Time ct;
struct tm stru_tmp;
localtime_r((long *)&st, &stru_tmp);
ct.millisecond = (stru_tmp.tm_sec * 1000);
ct.minute = stru_tmp.tm_min;
ct.hour = stru_tmp.tm_hour;
ct.dayofmonth = stru_tmp.tm_mday;
ct.dayofweek = stru_tmp.tm_wday;
ct.month = stru_tmp.tm_mon + 1;
ct.year = stru_tmp.tm_year + 1900 - 2000;
return ct;
}
2024-10-21 10:53:15 +08:00
QLONG filetime_to_unix(QLONG ft)
{
uint64_t winTime = ft;
// 将100纳秒间隔转换为毫秒
winTime /= 10000;
// 减去从1601年到1970年的毫秒数
winTime -= 11644473600000LL;
// 将毫秒转换为秒
return (winTime);
}
QWORD current_time()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}
QWORD snowflake_next_id(void)
{
QWORD timestamp = current_time();
if (timestamp < g_sf.last_timestamp) {
return 0;
}
if (g_sf.last_timestamp == timestamp) {
g_sf.sequence = (g_sf.sequence + 1) & SEQUENCE_MASK;
if (g_sf.sequence == 0) {
while (current_time() <= g_sf.last_timestamp);
}
} else {
g_sf.sequence = 0; // reset sequence
}
g_sf.last_timestamp = timestamp;
return ((timestamp - EPOCH) << (WORKER_ID_BITS + DATA_CENTER_ID_BITS + SEQUENCE_BITS)) |
(g_sf.data_center_id << (WORKER_ID_BITS + SEQUENCE_BITS)) |
(g_sf.worker_id << SEQUENCE_BITS) |
g_sf.sequence;
}
2024-07-08 10:27:17 +08:00
void alarm(void)
{
}
BOOLEAN InitializeMemory(void)
{
int i, j;
synchronized = FALSE;
systemRunFlag = FALSE;
memset(&system32, 0, sizeof(system32));
memset(&config, 0, sizeof(config));
memset(&database, 0, sizeof(database));
memset(procs, 0, sizeof(procs));
memset(&channelBuffer, 0, sizeof(channelBuffer));
memset(&msgBuffer, 0, sizeof(msgBuffer));
memset(&nodes, 0, sizeof(nodes));
// memset(units_state, 0, sizeof(units_state)); //为UI添加专用单元状态
database.yxs = new struYX[DATABASE_YX_NUM];
if (database.yxs == NULL) return FALSE;
memset(database.yxs, 0, sizeof(struYX) * DATABASE_YX_NUM);
database.ycs = new struYC[DATABASE_YC_NUM];
if (database.ycs == NULL) return FALSE;
memset(database.ycs, 0, sizeof(struYC) * DATABASE_YC_NUM);
database.yms = new struYM[DATABASE_YM_NUM];
if (database.yms == NULL) return FALSE;
memset(database.yms, 0, sizeof(struYM) * DATABASE_YM_NUM);
database.yks = new struYK[DATABASE_YK_NUM];
if (database.yks == NULL) return FALSE;
memset(database.yks, 0, sizeof(struYK) * DATABASE_YK_NUM);
database.yts = new struYT[DATABASE_YT_NUM];
if (database.yts == NULL) return FALSE;
memset(database.yts, 0, sizeof(struYT) * DATABASE_YT_NUM);
msgBuffer.buf = new char[MAX_DISPLAY_BUFFER_SIZE];
if (msgBuffer.buf != NULL)
{
memset(msgBuffer.buf, 0, sizeof(char) * MAX_DISPLAY_BUFFER_SIZE);
}
channelBuffer.buf = new char[MAX_DISPLAY_BUFFER_SIZE];
if (channelBuffer.buf != NULL)
{
memset(channelBuffer.buf, 0, sizeof(char) * MAX_DISPLAY_BUFFER_SIZE);
}
strcpy(system32.yk_pass, "12345");
system32.yk_keep = 30;
system32.interval_time = 2;
system32.log_enabled = FALSE;
system32.zjd_log_bind_addr = INADDR_ANY;
system32.zjd_log_bind_port = 0;
for (i = 0; i < HARDWARE_PORTS_NUM; i++)
{
snprintf(config.hardware.ports[i].name, MAX_NAME_SIZE, "ttyS%d", i + 100);
config.hardware.ports[i].baud = 9600;
config.hardware.ports[i].data = 8;
config.hardware.ports[i].parity = 0;
config.hardware.ports[i].stop = 0;
config.hardware.ports[i].timeout = 1000; //1s
}
for (i = 0; i < PROCESSES_NUM; i++)
{
snprintf(config.processes[i].name, MAX_NAME_SIZE, "PROC%02d", i);
2024-12-30 17:20:28 +08:00
//config.processes[i].softdog = 0;
config.processes[i].real_softdog = 0;
config.processes[i].ftp_softdog = 0;
2024-07-08 10:27:17 +08:00
for (j = 0; j < PROCESS_UNIT_NUM; j++)
{
config.processes[i].units[j] = -1;
}
}
for (i = 0; i < UNIT_NUM; i++)
{
2024-12-30 17:20:28 +08:00
//config.units[i].softdog = 0;
config.units[i].real_softdog = 0;
config.units[i].ftp_softdog = 0;
2024-07-08 10:27:17 +08:00
}
return TRUE;
}
BOOLEAN ReadSystemCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_SYSTEM_CONFIG);
pf = fopen(pathName, "rb");
if (pf != NULL)
{
fread(&system32, sizeof(system32), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteSystemCFG(void)
{
FILE* pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_SYSTEM_CONFIG);
pf = fopen(pathName, "wb+");
if (pf != NULL)
{
fwrite(&system32, sizeof(system32), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN ReadNodeCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_NODE_CONFIG);
pf = fopen(pathName, "rb");
if (pf != NULL)
{
fread(&nodes, sizeof(nodes), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteNodeCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_NODE_CONFIG);
pf = fopen(pathName, "wb+");
if (pf != NULL)
{
fwrite(&nodes, sizeof(nodes), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN ReadHardwareCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_HARDWARE_CONFIG);
pf = fopen(pathName, "rb");
if (pf != NULL)
{
fread(&config.hardware, sizeof(config.hardware), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteHardwareCFG(void)
{
FILE* pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_HARDWARE_CONFIG);
pf = fopen(pathName, "wb+");
if (pf != NULL)
{
fwrite(&config.hardware, sizeof(config.hardware), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN ReadProcessCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_PROCESS_CONFIG);
pf = fopen(pathName, "rb");
if (pf != NULL)
{
fread(&config.processes, sizeof(config.processes), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteProcessCFG(void)
{
FILE* pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_PROCESS_CONFIG);
pf = fopen(pathName, "wb+");
if (pf != NULL)
{
fwrite(&config.processes, sizeof(config.processes), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN ReadUnitCFG(void)
{
int i, j;
char pathName[512];
char filename[512];
FILE *pf = NULL;
FILE *pfPoint = NULL;
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_UNIT_CONFIG);
pf = fopen(pathName, "rb");
if (pf != NULL)
{
for (i = 0; i < UNIT_NUM; i++)
{
if (feof(pf)) break;
if (fread(&config.units[i], sizeof(config.units[i]), 1, pf) != 1) break;
config.units[i].yxs = NULL;
config.units[i].ycs = NULL;
config.units[i].yms = NULL;
config.units[i].yks = NULL;
config.units[i].yts = NULL;
if (config.units[i].yxcount > 0)
{
config.units[i].yxs = new struUnitYX[config.units[i].yxcount];
if (NULL == config.units[i].yxs) return FALSE;
memset(config.units[i].yxs, 0, sizeof(struUnitYX)*config.units[i].yxcount);
snprintf(filename, sizeof(filename), FILE_UNIT_YX_CONFIG, configpath, i);
pfPoint = fopen(filename, "rb");
if (pfPoint != NULL)
{
fread(config.units[i].yxs, sizeof(struUnitYX)*config.units[i].yxcount, 1, pfPoint);
fclose(pfPoint);
}
else
{
for (j = 0; j < config.units[i].yxcount; j++)
{
config.units[i].yxs[j].order = -1;
config.units[i].yxs[j].qds = 0x80;
}
}
}
if (config.units[i].yccount > 0)
{
config.units[i].ycs = new struUnitYC[config.units[i].yccount];
if (NULL == config.units[i].ycs) return FALSE;
memset(config.units[i].ycs, 0, sizeof(struUnitYC)*config.units[i].yccount);
snprintf(filename, sizeof(filename), FILE_UNIT_YC_CONFIG, configpath, i);
pfPoint = fopen(filename, "rb");
if (pfPoint != NULL)
{
fread(config.units[i].ycs, sizeof(struUnitYC)*config.units[i].yccount, 1, pfPoint);
fclose(pfPoint);
}
else
{
for (j = 0; j < config.units[i].yccount; j++)
{
config.units[i].ycs[j].order = -1;
config.units[i].ycs[j].factor = 1;
config.units[i].ycs[j].qds = 0x80;
}
}
}
if (config.units[i].ymcount > 0)
{
config.units[i].yms = new struUnitYM[config.units[i].ymcount];
if (NULL == config.units[i].yms) return FALSE;
memset(config.units[i].yms, 0,sizeof(struUnitYM)*config.units[i].ymcount);
snprintf(filename, sizeof(filename), FILE_UNIT_YM_CONFIG, configpath, i);
pfPoint = fopen(filename, "rb");
if (pfPoint != NULL)
{
fread(config.units[i].yms, sizeof(struUnitYM)*config.units[i].ymcount, 1, pfPoint);
fclose(pfPoint);
}
else
{
for (j = 0; j < config.units[i].ymcount; j++)
{
config.units[i].yms[j].order = -1;
}
}
}
if (config.units[i].ykcount > 0)
{
config.units[i].yks = new struUnitYK[config.units[i].ykcount];
if (NULL == config.units[i].yks) return FALSE;
memset(config.units[i].yks, 0, sizeof(struUnitYK)*config.units[i].ykcount);
snprintf(filename, sizeof(filename), FILE_UNIT_YK_CONFIG, configpath, i);
pfPoint = fopen(filename, "rb");
if (pfPoint != NULL)
{
fread(config.units[i].yks, sizeof(struUnitYK)*config.units[i].ykcount, 1, pfPoint);
fclose(pfPoint);
}
else
{
for (j = 0; j < config.units[i].ykcount; j++)
{
config.units[i].yks[j].order = -1;
}
}
}
if (config.units[i].ytcount > 0)
{
config.units[i].yts = new struUnitYT[config.units[i].ytcount];
if (NULL == config.units[i].yts) return FALSE;
memset(config.units[i].yts, 0, sizeof(struUnitYT)*config.units[i].ytcount);
snprintf(filename, sizeof(filename), FILE_UNIT_YT_CONFIG, configpath, i);
pfPoint = fopen(filename, "rb");
if (pfPoint != NULL)
{
fread(config.units[i].yts, sizeof(struUnitYT)*config.units[i].ytcount, 1, pfPoint);
fclose(pfPoint);
}
else
{
for (j = 0; j < config.units[i].ytcount; j++)
{
config.units[i].yts[j].order = -1;
}
}
}
}
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteUnitCFG(void)
{
int i;
char filename[512];
char pathName[512];
FILE *pf = NULL;
FILE *pfPoint = NULL;
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_UNIT_CONFIG);
pf = fopen(pathName, "wb+");
if (pf != NULL)
{
for (i = 0; i < UNIT_NUM; i++)
{
if (fwrite(&config.units[i], sizeof(config.units[i]), 1, pf) != 1) break;
if (config.units[i].yxcount > 0)
{
if (config.units[i].yxs != NULL)
{
snprintf(filename, sizeof(filename), FILE_UNIT_YX_CONFIG, configpath, i);
pfPoint = fopen(filename, "wb+");
if (pfPoint != NULL)
{
fwrite(config.units[i].yxs, sizeof(struUnitYX)*config.units[i].yxcount, 1, pfPoint);
fclose(pfPoint);
}
}
}
if (config.units[i].yccount > 0)
{
if (config.units[i].ycs != NULL)
{
snprintf(filename, sizeof(filename), FILE_UNIT_YC_CONFIG, configpath, i);
pfPoint = fopen(filename, "wb+");
if (pfPoint != NULL)
{
fwrite(config.units[i].ycs, sizeof(struUnitYC)*config.units[i].yccount, 1, pfPoint);
fclose(pfPoint);
}
}
}
if (config.units[i].ymcount > 0)
{
if (config.units[i].yms != NULL)
{
snprintf(filename, sizeof(filename), FILE_UNIT_YM_CONFIG, configpath, i);
pfPoint = fopen(filename, "wb+");
if (pfPoint != NULL)
{
fwrite(config.units[i].yms, sizeof(struUnitYM)*config.units[i].ymcount, 1, pfPoint);
fclose(pfPoint);
}
}
}
if (config.units[i].ykcount > 0)
{
if (config.units[i].yks != NULL)
{
snprintf(filename, sizeof(filename), FILE_UNIT_YK_CONFIG, configpath, i);
pfPoint = fopen(filename, "wb+");
if (pfPoint != NULL)
{
fwrite(config.units[i].yks, sizeof(struUnitYK)*config.units[i].ykcount, 1, pfPoint);
fclose(pfPoint);
}
}
}
if (config.units[i].ytcount > 0)
{
if (config.units[i].yts != NULL)
{
snprintf(filename, sizeof(filename), FILE_UNIT_YT_CONFIG, configpath, i);
pfPoint = fopen(filename, "wb+");
if (pfPoint != NULL)
{
fwrite(config.units[i].yts, sizeof(struUnitYT)*config.units[i].ytcount, 1, pfPoint);
fclose(pfPoint);
}
}
}
}
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN ReadStaticUnitCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_UNIT_STATIC);
pf = fopen(pathName, "rb");
if (pf)
{
fread(static_units, sizeof(static_units), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteStaticUnitCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_UNIT_STATIC);
pf = fopen(pathName, "w+");
if (pf != NULL)
{
fwrite(static_units, sizeof(static_units), 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN ReadDatabaseCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_DATABASE_CONFIG);
pf = fopen(pathName, "rb");
if (pf != NULL)
{
if (!feof(pf))
{
fread(database.yxs, sizeof(struYX) * DATABASE_YX_NUM, 1, pf);
}
if (!feof(pf))
{
fread(database.ycs, sizeof(struYC) * DATABASE_YC_NUM, 1, pf);
}
if (!feof(pf))
{
fread(database.yms, sizeof(struYM) * DATABASE_YM_NUM, 1, pf);
}
if (!feof(pf))
{
fread(database.yks, sizeof(struYK) * DATABASE_YK_NUM, 1, pf);
}
if (!feof(pf))
{
fread(database.yts, sizeof(struYT) * DATABASE_YT_NUM, 1, pf);
}
fclose(pf);
return TRUE;
}
return FALSE;
}
BOOLEAN WriteDatabaseCFG(void)
{
FILE *pf;
char pathName[512];
snprintf(pathName, sizeof(pathName), "%s/%s", configpath, FILE_DATABASE_CONFIG);
pf = fopen(pathName, "wb+");
if (pf != NULL)
{
fwrite(database.yxs, sizeof(struYX) * DATABASE_YX_NUM, 1, pf);
fwrite(database.ycs, sizeof(struYC) * DATABASE_YC_NUM, 1, pf);
fwrite(database.yms, sizeof(struYM) * DATABASE_YM_NUM, 1, pf);
fwrite(database.yks, sizeof(struYK) * DATABASE_YK_NUM, 1, pf);
fwrite(database.yts, sizeof(struYT) * DATABASE_YT_NUM, 1, pf);
fclose(pf);
return TRUE;
}
return FALSE;
}
void dumpLogs(void)
{
if (system32.log_enabled)
{ //保存日志
yxbw.DumpYXBW();
soe.DumpSOE();
yklog.DumpYKLog();
ytlog.DumpYTLog();
}
WriteDatabaseCFG();
FILE* pf = fopen("./stop.log", "w+");
if (pf)
{
fwrite(&system32.now, sizeof(unionCP56Time), 1, pf);
fwrite(&system32.timers, sizeof(DWORD), 1, pf);
fclose(pf);
}
}
////////////////////////////////
// 空闲进程
////////////////////////////////
void yk(void)
{
int i;
struYK* pYK;
for (i = 0; i < DATABASE_YK_NUM; i++)
{
pYK = &database.yks[i];
if (pYK->state != YKS_IDLE)
{
if (pYK->result == YKR_IDLE || pYK->result == YKR_OPER)
{
if ((short)(system32.timers - pYK->op_time) > system32.yk_keep)
{
pYK->result = YKR_OVER;
if (pYK->state == YKS_EXEREQ || pYK->state == YKS_EXEING)
{
yklog.PushYKLog(system32.now, i, pYK->value, YKT_EXEOUT, YKS_AUTO, -1);
}
else
{
yklog.PushYKLog(system32.now, i, pYK->value, YKT_SELOUT, YKS_AUTO, -1);
}
}
}
else if (pYK->result == YKR_SUCC)
{
if (pYK->state == YKS_EXEED)
{
if ((short)(system32.timers - pYK->op_time) > system32.yk_keep)
{
pYK->state = YKS_IDLE;
pYK->result = YKR_IDLE;
pYK->op_unit = -1;
}
}
else
{
if ((short)(system32.timers - pYK->op_time) > system32.yk_keep)
{
pYK->result = YKR_OVER;
yklog.PushYKLog(system32.now, i, pYK->value, YKT_SELOUT, YKS_AUTO, -1);
}
}
}
else if (pYK->result == YKR_OVER)
{
if ((short)(system32.timers - pYK->op_time) > (system32.yk_keep + 5))
{
pYK->state = YKS_IDLE;
pYK->result = YKR_IDLE;
pYK->op_unit = -1;
}
}
}
else
{
pYK->op_unit = -1;
}
}
}
void yt(void)
{
int i;
struYT* pYT;
for (i = 0; i < DATABASE_YT_NUM; i++)
{
pYT = &database.yts[i];
if (pYT->state != YTS_IDLE)
{
if (pYT->result == YTR_IDLE || pYT->result == YTR_OPER)
{
if ((short)(system32.timers - pYT->op_time) > system32.yk_keep)
{
pYT->result = YTR_OVER;
if (pYT->state == YTS_EXEREQ || pYT->state == YTS_EXEING)
{
ytlog.PushYTLog(system32.now, i, pYT->value, YTT_EXEOUT, YTS_AUTO, -1);
}
else
{
ytlog.PushYTLog(system32.now, i, pYT->value, YTT_SELOUT, YTS_AUTO, -1);
}
}
}
else if (pYT->result == YTR_SUCC)
{
if (pYT->state == YTS_EXEED)
{
if ((short)(system32.timers - pYT->op_time) > system32.yk_keep)
{
pYT->state = YTS_IDLE;
pYT->result = YTR_IDLE;
pYT->op_unit = -1;
}
}
else
{
if ((short)(system32.timers - pYT->op_time) > system32.yk_keep)
{
pYT->result = YTR_OVER;
ytlog.PushYTLog(system32.now, i, pYT->value, YTT_SELOUT, YTS_AUTO, 1);
}
}
}
else if (pYT->result == YTR_OVER)
{
if ((short)(system32.timers - pYT->op_time) > (system32.yk_keep + 5))
{
pYT->state = YTS_IDLE;
pYT->result = YTR_IDLE;
pYT->op_unit = -1;
}
}
}
else
{
pYT->op_unit = -1;
}
}
}
void* idle_process(void* param)
{
int yxbw_save = 0, yxbw_load = 0;
while (systemRunFlag)
{
sleep(1);
yk();
yt();
//操作保存系统操作Log
2024-08-09 08:50:19 +08:00
if ((system32.timers % 3600) == 0) { //过整点保存
if (system32.log_enabled) {
2024-07-08 10:27:17 +08:00
yxbw.DumpYXBW();
soe.DumpSOE();
yklog.DumpYKLog();
ytlog.DumpYTLog();
}
yxbw_save = yxbw.GetSavePos();
2024-08-09 08:50:19 +08:00
if (yxbw_load != yxbw_save) { //有变位信息
2024-07-08 10:27:17 +08:00
WriteDatabaseCFG();
yxbw_load = yxbw_save;
}
}
2024-08-09 08:50:19 +08:00
for (int i = 0; i < PROCESSES_NUM; i++) {
2024-12-30 17:20:28 +08:00
config.processes[i].real_softdog++;
if (config.processes[i].real_softdog > PROCESS_WATCHDOG_TIME) {
config.processes[i].real_softdog = PROCESS_WATCHDOG_TIME;
}
config.processes[i].ftp_softdog++;
if (config.processes[i].ftp_softdog > PROCESS_WATCHDOG_TIME) {
config.processes[i].ftp_softdog = PROCESS_WATCHDOG_TIME;
2024-07-08 10:27:17 +08:00
}
}
2024-08-09 08:50:19 +08:00
for (int i = 0; i < UNIT_NUM; i++) {
2024-12-30 17:20:28 +08:00
config.units[i].real_softdog++;
if (config.units[i].real_softdog > UNIT_WATCHDOG_TIME) {
config.units[i].real_softdog = UNIT_WATCHDOG_TIME;
2024-12-11 13:33:15 +08:00
config.units[i].value |= SPI_ON;
2024-08-09 08:50:19 +08:00
} else {
2024-12-11 13:33:15 +08:00
config.units[i].value &= ~SPI_ON;
2024-07-08 10:27:17 +08:00
}
2024-12-30 17:20:28 +08:00
config.units[i].ftp_softdog++;
if (config.units[i].ftp_softdog > UNIT_WATCHDOG_TIME) {
config.units[i].ftp_softdog = UNIT_WATCHDOG_TIME;
}
2024-07-08 10:27:17 +08:00
}
}
pthread_exit(0);
return ((void*)0);
}
////////////////////////////////
// 主进程,用于系统时间的更新
////////////////////////////////
void* main_process(void* param)
{
while (systemRunFlag)
{
struct timeval tv;
tv.tv_sec = 0;
//tv.tv_usec = 20000;
tv.tv_usec = TIME_TICKS;
select(0, NULL, NULL, NULL, &tv);
system32.ticks++; //每20ms累加一次
if (get_system_time(&system32.now))
{
system32.now.SU = FALSE;
//if (synchronized)
{
system32.now.IV = FALSE;
}
}
}
pthread_exit(0);
return ((void*)0);
}
void main_process_timer_handler(int signum)
{
system32.ticks++; //每20ms累加一次
if (get_system_time(&system32.now))
{
system32.now.SU = FALSE;
//if (synchronized)
{
system32.now.IV = FALSE;
}
}
}
BOOLEAN initialize_system(BOOLEAN usesqlite, BOOLEAN enable_auto_platform, const char* pathName, char *codeName)
{
if (!InitializeMemory())
{
vLog(LOG_ERROR, "Fail initialize memory!\n");
return FALSE;
}
if (usesqlite)
{
vLog(LOG_DEBUG, "read configuration from sqlite3 db file.\n");
2024-07-19 17:28:02 +08:00
BOOLEAN ret = FALSE;
2024-07-08 10:27:17 +08:00
#if 0
2024-07-19 17:28:02 +08:00
ret = ReadConfigFromSQLite(enable_auto_platform, pathName, codeName);
2024-07-08 10:27:17 +08:00
if (ret)
{
WriteSystemCFG();
WriteNodeCFG();
WriteHardwareCFG();
WriteProcessCFG();
WriteUnitCFG();
WriteStaticUnitCFG();
}
#endif
return ret;
}
else
{
vLog(LOG_DEBUG, "read configuration from struct files.\n");
vLog(LOG_DEBUG, "Loading system config...\n");
if (!ReadSystemCFG())
{
vLog(LOG_ERROR, "Fail load system config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
vLog(LOG_DEBUG, "Loading node config...\n");
if (!ReadNodeCFG())
{
vLog(LOG_ERROR, "Fail load node config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
vLog(LOG_DEBUG, "Loading database config...\n");
if (!ReadDatabaseCFG())
{
vLog(LOG_ERROR, "Fail load database config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
vLog(LOG_DEBUG, "Loading hardware config...\n");
if (!ReadHardwareCFG())
{
vLog(LOG_ERROR, "Fail load hardware config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
vLog(LOG_DEBUG, "Loading process config...\n");
if (!ReadProcessCFG())
{
vLog(LOG_ERROR, "Fail load processes config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
vLog(LOG_DEBUG, "Loading unit config...\n");
if (!ReadUnitCFG())
{
vLog(LOG_ERROR, "Fail load unit config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
vLog(LOG_DEBUG, "Loading static unit config...\n");
if (!ReadStaticUnitCFG())
{
vLog(LOG_ERROR, "Fail load static unit config!\n");
alarm();
2024-07-19 17:28:02 +08:00
return FALSE;
2024-07-08 10:27:17 +08:00
}
}
return TRUE;
}
BOOLEAN destroy_thread(void)
{
int i = 0;
if (!systemRunFlag) return FALSE;
dumpLogs();
systemRunFlag = FALSE;
for (i = 0; i < MAX_THREAD_NUM; i++)
{
if (p_id[i] != 0)
{
2024-12-11 16:30:53 +08:00
char name[16];
memset(name, '\0', sizeof(name));
if (pthread_getname_np(p_id[i], name, sizeof(name)) != 0)
{
memset(name, '\0', sizeof(name));
}
vLog(LOG_DEBUG, "waiting for system thread [%d,%s] destroy.\n", i, (name[0] != '\0') ? name : "unknow");
2024-07-08 10:27:17 +08:00
pthread_join(p_id[i], NULL);
2024-12-11 16:30:53 +08:00
vLog(LOG_DEBUG, "system protocol thread [%d,%s] is destroyed.\n", i, (name[0] != '\0') ? name : "unknow");
2024-07-08 10:27:17 +08:00
}
}
return TRUE;
}
BOOLEAN initialize_thread(void)
{
int ret;
pthread_attr_t attr;
systemRunFlag = TRUE;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, MEMERY_1M);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&p_id[THREAD_ID_MAIN], &attr, main_process, NULL);
if (ret < 0)
{
vLog(LOG_ERROR, "Create main_process thread error(%d,%s)!\n", errno, strerror(errno));
return FALSE;
}
#if 1
pthread_setname_np(p_id[THREAD_ID_MAIN], "main process");
#endif
ret = pthread_create(&p_id[THREAD_ID_IDLE], &attr, idle_process, NULL);
if (ret < 0)
{
vLog(LOG_ERROR, "Create idle_process thread error(%d,%s)!\n", errno, strerror(errno));
return FALSE;
}
#if 1
pthread_setname_np(p_id[THREAD_ID_IDLE], "idle process");
#endif
pthread_attr_destroy(&attr);
sleep(1);
if (!synchronized)
{
vLog(LOG_DEBUG, "system clock does't synchronized!\n");
}
return TRUE;
}