13 Commits

31 changed files with 4385 additions and 1329 deletions

View File

@@ -0,0 +1,175 @@
TEMPLATE = app
TARGET = pt61850netd_pqfe
DEPENDPATH += .
INCLUDEPATH += . \
./source \
./source/include \
./source/include/mmslite \
./source/include/pg_inst \
./source/include/curl \
./source/include/oss_sdk \
./source/include/rocketmq
QMAKE_ORIG_TARGET = $$(TARGET)
QT += core xml network
CONFIG += thread
DEFINES += _CRT_SECURE_NO_WARNINGS
DEFINES += MMS_LITE LINUX=2 MOSI LEAN_T TP0_ENABLED
DEFINES += CLIENT _DEBUG _REENTRANT _GNU_SOURCE _LARGEFILE64_SOURCE
# debug/release flags
CONFIG(debug, debug|release) {
message("Building debug version with debug symbols")
QMAKE_CFLAGS_DEBUG += -g -O0
QMAKE_CXXFLAGS_DEBUG += -g -O0
CONFIG += force_debug_info
} else {
message("Building release version")
QMAKE_CFLAGS_RELEASE += -O2
QMAKE_CXXFLAGS_RELEASE += -O2
}
win32 {
DEFINES -= UNICODE
DEFINES += _AFXDLL
CONFIG += console
}
win32 {
# RC_FILE=pt61850netd_pqfe.rc
SOURCES += source/mms/event.c
INCLUDEPATH += ./source/include/apr
QMAKE_LFLAGS += /NODEFAULTLIB:libcmt.lib
LIBS += -L./lib -L./lib/mmslite -lws2_32
CONFIG(debug, debug|release) {
DEFINES += DEBUG_SISCO
MMS_LIB_SUFFIX = _ld.lib
QMAKE_POST_LINK = $$QMAKE_COPY debug\\*.exe ..\\..\\usr_bin\\jspqfe_home\\bin
} else {
MMS_LIB_SUFFIX = _n.lib
QMAKE_POST_LINK = $$QMAKE_COPY release\\*.exe ..\\..\\usr_bin\\jspqfe_home\\bin
}
LIBS += ositcps$$MMS_LIB_SUFFIX \
mvl$$MMS_LIB_SUFFIX \
mmsle$$MMS_LIB_SUFFIX \
mmsl$$MMS_LIB_SUFFIX \
asn1$$MMS_LIB_SUFFIX \
mem$$MMS_LIB_SUFFIX \
meml$$MMS_LIB_SUFFIX \
slog$$MMS_LIB_SUFFIX \
utility$$MMS_LIB_SUFFIX \
ssec0$$MMS_LIB_SUFFIX
LIBS += -llibapr-1 -llibaprutil-1 -llibjclite
}
unix {
# 清掉旧标准
QMAKE_CXXFLAGS -= -std=gnu++98
QMAKE_CXXFLAGS -= -std=c++98
QMAKE_CXXFLAGS -= -std=gnu++11
QMAKE_CXXFLAGS -= -std=c++11
# 只保留一个
QMAKE_CXXFLAGS += -std=gnu++14
include(fe_common.pri)
SOURCES += source/mms/event2.c
INCLUDEPATH += ./source/include/apr-linux
LIBS += -L/FeProject/lib
# LIBS += -L/FeProject/lib/pgodbc
DEFINES += DEBUG_SISCO
VERSION = 1.0.0
# rpath
QMAKE_LFLAGS += -Wl,-rpath,/FeProject/lib \
-Wl,-rpath,/FeProject/lib/mmslite
LIBS += -lrt -lpthread
MMS_LIB_SUFFIX = _ld.a
LIBS += /FeProject/lib/mmslite/ositcps$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/mvl$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/mmsle$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/mmsl$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/asn1l$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/mem$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/slog$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/util$$MMS_LIB_SUFFIX \
/FeProject/lib/mmslite/ssec0$$MMS_LIB_SUFFIX \
/FeProject/lib/libcurl.so \
/FeProject/lib/libmxml4.so \
/FeProject/lib/librocketmq.so \
/FeProject/lib/libhttprun.so \
/FeProject/lib/liblog4cplus.so
LIBS += -lapr-1 -laprutil-1 -ljclite
LIBS += -lrdkafka++
LIBS += -lrdkafka
LIBS += -L/FeProject/lib -llog4cplus
LIBS += -L/root/JoyProject/3rdparty/boost_pic_aarch64/lib -Wl,--no-as-needed -lboost_iostreams -Wl,--as-needed
LIBS += -L/root/JoyProject/3rdparty/zlib_pic_aarch64/lib -lz
}
# install
target.path = ../../bin
INSTALLS += target
# Input
HEADERS += source/mms/db_interface.h \
source/include/otlv4.h \
source/mms/mmsclient.h \
source/mms/mmsop_en.h \
source/mms/rdb_client.h \
source/mms/ver_conf.h \
source/misc/SM4.h \
source/json/save2json.h \
source/json/mms_json_inter.h \
# source/json/rdkafka.h \
# source/json/rdkafkacpp.h \
# source/json/kafka_producer.h \
source/json/cjson.h \
source/rocketmq/SimpleProducer.h \
source/cfg_parse/custom_printf.h \
source/log4cplus/log4.h
SOURCES += source/mms/main.c \
source/mms/clntobj.c \
source/mms/logcfgx.c \
source/mms/mms_process.c \
source/mms/mmscli_rpt.c \
source/mms/mmsclient.c \
source/mms/mmslvar.c \
source/mms/mmsop_en.c \
source/mms/mvl_acse.c \
source/mms/mvlop_en.c \
source/mms/parse_xml.c \
source/mms/rdb_client.c \
source/mms/rdb_ext_utils.c \
source/mms/reject.c \
source/mms/mmscli_log.c \
source/misc/SM4.cpp \
source/misc/my_encrypt.cpp \
source/json/save2json.cpp \
source/cfg_parse/cfg_parser.cpp \
# source/json/kafka_producer.cpp \
source/json/create_json.cpp \
source/json/cjson.c \
source/cfg_parse/nacos.cpp \
source/cfg_parse/base64.cpp \
source/cfg_parse/SimpleProducer.cpp \
source/cfg_parse/log4.cpp \
# source/cfg_parse/oss_aliyun.cpp \
#source/cfg_parse/obs_huaweiyun.cpp \
# source/cfg_parse/datahub.cpp \
# source/cfg_parse/uds_huaweiyun.cpp

22
boot/feservice Normal file
View File

@@ -0,0 +1,22 @@
#!/bin/bash
case "$1" in
'start')
$FEP_ENV/boot/start_fe.sh
;;
'stop')
$FEP_ENV/boot/stop_fe.sh
;;
'restart')
$FEP_ENV/boot/stop_fe.sh
$FEP_ENV/boot/start_fe.sh
;;
*)
echo "Usage: feservice start|stop|restart"
exit 1
;;
esac

44
boot/ps_fe.sh Normal file
View File

@@ -0,0 +1,44 @@
#!/bin/bash
# @file: $RCSfile: ps_fe.sh,v $
# @brief: $ϵͳӦ<CDB3><D3A6><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>̽ű<CCBD>
# @version: $Revision: 1.2 $
# @date: $Date: 2017/02/23 03:42:58 $
# @author: $Author: zhanchengguo $
# @state: $State: Exp $
# @latest: $Id: ps_fe.sh,v 1.2 2017/02/23 03:42:58 zhanchengguo Exp $
echo ""
RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf"
while read LINE ; do
if [ -n "$LINE" ] ; then
if [ ${LINE:0:1} != "#" ]; then
BINPATH=`echo $LINE | awk -F '^' '{printf $1}'`
BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BINPATH
BIN=`echo $LINE | awk -F '^' '{printf $2}'`
BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BIN
SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'`
SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SPECIAL
SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'`
SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SLEEPSEC
STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'`
STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $STARTFLAG
# if [ "`echo $STARTFLAG`" != "IGNORE_START" ]; then
CMD_STR=" ps -w | grep `echo "'"``echo $BIN``echo "'"` | grep -v 'grep'"
BIN2=`echo $BIN`
ps -ef | grep "$BIN2" | grep -v 'grep'
# fi
fi
fi
done < $RUNTIME_CF_FILE
echo ""

106
boot/start_fe.sh Normal file
View File

@@ -0,0 +1,106 @@
#!/bin/bash
# @file: $RCSfile: start_fe.sh,v $
# @brief: $ϵͳӦ<CDB3><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ű<EFBFBD>
# @version: $Revision: 1.1 $
# @date: $Date: 2018/12/26 07:19:31 $
# @author: $Author: lizhongming $
# @state: $State: Exp $
# @latest: $Id: start_fe.sh,v 1.1 2018/12/26 07:19:31 lizhongming Exp $
QTDIR=/qt-4.8.4
export QTDIR
FEP_ENV=/FeProject
export FEP_ENV
PATH=$FEP_ENV/bin:$QTDIR/bin:$PATH
export PATH
LD_LIBRARY_PATH=$FEP_ENV/lib:$FEP_ENV/lib3rd:$QTDIR/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
check_log_file()
{
if [ -n "$1" ] ; then
FILE_SIZE=0
FILE_SIZE=`du $1 | awk '{print $1}'`
if [ $FILE_SIZE -ge 5120 ]
then
if [ -f "$1".3 ]; then
rm -f "$1".3
fi
if [ -f "$1".2 ]; then
mv "$1".2 "$1".3
fi
if [ -f "$1".1 ]; then
mv "$1".1 "$1".2
fi
mv "$1" "$1".1
fi
fi
}
LOGFILE="$FEP_ENV/dat/log/start_fe.log"
check_log_file $LOGFILE
echo "" ; echo ""
echo "******* `date "+%F %R:%S"` Start Processes *******"
echo "" >>"$LOGFILE"
echo "" >>"$LOGFILE"
echo "******* `date "+%F %R:%S"` Start Processes *******" >>"$LOGFILE"
#sysctl -w "kernel.core_pattern=/usr/local/sascore/%e.%p.%t.core" &> /dev/null
<>г<EFBFBD><D0B3><EFBFBD>·<EFBFBD><C2B7>^<5E><>ִ<EFBFBD>г<EFBFBD><D0B3><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ^<5E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD>^<5E>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD>^<5E><><EFBFBD><EFBFBD><EFBFBD>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>^<5E><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>^<5E>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
RUNTIME_CF_FILE="$FEP_ENV/etc/runtime.cf"
echo "Using config file name: $RUNTIME_CF_FILE"
echo "Using config file name: $RUNTIME_CF_FILE">>"$LOGFILE"
CURDIR=`pwd`
while read LINE ; do
if [ -n "$LINE" ] ; then
if [ ${LINE:0:1} != "#" ]; then
BINPATH=`echo $LINE | awk -F '^' '{printf $1}'`
BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BINPATH
BIN=`echo $LINE | awk -F '^' '{printf $2}'`
BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BIN
SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'`
SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SPECIAL
SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'`
SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SLEEPSEC
STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'`
STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $STARTFLAG
RESTARTFLAG=`echo $LINE | awk -F '^' '{printf $6}'`
RESTARTFLAG=`echo "$RESTARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
echo $RESTARTFLAG
if [ "$RESTARTFLAG" = "IGNORE_RESTART" ]; then
# echo "" ;
CMD_STR=" sleep `echo $SLEEPSEC` "
echo "$CMD_STR"
echo "$CMD_STR" >>"$LOGFILE"
$CMD_STR
CMD_STR=" `echo $BINPATH``echo $BIN` `echo $SPECIAL` "
echo "$CMD_STR"
echo "$CMD_STR" >>"$LOGFILE"
$CMD_STR &>/dev/null
fi
fi
fi
done < $RUNTIME_CF_FILE
cd $CURDIR
DT=`date "+%F %R:%S.%N"`
echo "******* ${DT:0:23} Start Processes Succcessfully *******"
echo "******* ${DT:0:23} Start Processes Succcessfully *******" >>"$LOGFILE"

107
boot/stop_fe.sh Normal file
View File

@@ -0,0 +1,107 @@
#!/bin/bash
# @file: $RCSfile: stop_fe.sh,v $
# @brief: $ϵͳӦ<CDB3><D3A6>ֹͣ<CDA3><D6B9><EFBFBD>̽ű<CCBD>
# @version: $Revision: 1.5 $
# @date: $Date: 2017/02/28 08:40:43 $
# @author: $Author: zhanchengguo $
# @state: $State: Exp $
# @latest: $Id: stop_fe.sh,v 1.5 2017/02/28 08:40:43 zhanchengguo Exp $
check_log_file()
{
if [ -n "$1" ] ; then
FILE_SIZE=0
FILE_SIZE=`du $1 | awk '{print $1}'`
if [ $FILE_SIZE -ge 5120 ]
then
if [ -f "$1".3 ]; then
rm -f "$1".3
fi
if [ -f "$1".2 ]; then
mv "$1".2 "$1".3
fi
if [ -f "$1".1 ]; then
mv "$1".1 "$1".2
fi
mv "$1" "$1".1
fi
fi
}
LOGFILE="/FeProject/dat/log/start_fe.log"
check_log_file $LOGFILE
echo "" ; echo ""
echo "****** `date "+%F %R:%S"` Stop Processes ******"
echo "" >>"$LOGFILE"
echo "" >>"$LOGFILE"
echo "****** `date "+%F %R:%S"` Stop Processes ******" >>"$LOGFILE"
RUNTIME_CF_FILE="/FeProject/etc/runtime.cf"
#cat $RUNTIME_CF_FILE |tac > /tmp/runtime.cf
sed '1!G;h;$!d' $RUNTIME_CF_FILE > /tmp/runtime.cf
echo "Using config file name: $RUNTIME_CF_FILE"
echo "Using config file name: $RUNTIME_CF_FILE">>"$LOGFILE"
while read LINE ; do
if [ -n "$LINE" ] ; then
if [ ${LINE:0:1} != "#" ]; then
BINPATH=`echo $LINE | awk -F '^' '{printf $1}'`
BINPATH=`echo "$BINPATH" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BINPATH
BIN=`echo $LINE | awk -F '^' '{printf $2}'`
BIN=`echo "$BIN" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $BIN
SPECIAL=`echo $LINE | awk -F '^' '{printf $4}'`
SPECIAL=`echo "$SPECIAL" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SPECIAL
SLEEPSEC=`echo $LINE | awk -F '^' '{printf $5}'`
SLEEPSEC=`echo "$SLEEPSEC" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $SLEEPSEC
STARTFLAG=`echo $LINE | awk -F '^' '{printf $7}'`
STARTFLAG=`echo "$STARTFLAG" | grep -o "[^ ]\+\( \+[^ ]\+\)*"`
# echo $STARTFLAG
if [ "`echo $STARTFLAG`" != "IGNORE_START" ]; then
# echo ""
# echo "" >>"$LOGFILE"
CMD_STR=" ps -w | grep `echo "'"``echo $BIN``echo "'"` | grep -v 'grep'"
BIN2=`echo $BIN`
BIN3=`echo $BIN |awk '{print$1}'`
# CMD_STR="killall `echo $BIN | awk '{print$1}'` 2>&1 "
PIDSTR=`ps -ef | grep "$BIN2" | grep -v 'grep'`
if [ -n "$PIDSTR" ] ; then
if [ "$BIN3" == "fe_main" ]; then
CMD_STR=" sleep 3 "
echo "$CMD_STR"
echo "$CMD_STR" >>"$LOGFILE"
$CMD_STR
fi
CMD_STR="kill -15 `echo $PIDSTR | awk '{print$2}'` "
echo " Kill process: \"$BIN\" with PID `echo $PIDSTR | awk '{print$2}'`"
echo " Kill process: \"$BIN\" with PID `echo $PIDSTR | awk '{print$2}'`" >>"$LOGFILE"
echo " Executing: $CMD_STR"
echo " Executing: $CMD_STR" >>"$LOGFILE"
CMD_RESULT=`$CMD_STR`
if [ -n "$CMD_RESULT" ] ; then
echo "$CMD_RESULT"
echo "$CMD_RESULT" >>"$LOGFILE"
fi
else
echo " Process \"$BIN\" not running."
fi
fi
fi
fi
done < /tmp/runtime.cf
DT=`date "+%F %R:%S.%N"`
echo "****** ${DT:0:23} Stop Processes Succcessfully ******"
echo "" >>"$LOGFILE"
echo "****** ${DT:0:23} Stop Processes Succcessfully ******" >>"$LOGFILE"

View File

@@ -3,6 +3,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <atomic>
#include <string>
#include "../mms/db_interface.h"
@@ -28,10 +29,14 @@
#include "../rocketmq/DefaultMQPushConsumer.h"
#include "../rocketmq/ConsumeType.h"
#include "../rocketmq/MQMessageListener.h"
#include "../rocketmq/MQMessageExt.h"
#include "../rocketmq/SessionCredentials.h"
// 引入提供的消费者接口头文件
#include "../rocketmq/CPushConsumer.h"
#include "../rocketmq/CCommon.h"
#include "../rocketmq/CMessageExt.h"
//#include "../rocketmq/CPushConsumer.h"
//#include "../rocketmq/CCommon.h"
//#include "../rocketmq/CMessageExt.h"
#include <map>
#include <pthread.h> // 用于互斥锁(在 C++98 中没有 std::mutex
#include <utility> // for std::pair
@@ -46,14 +51,19 @@ extern std::string G_ROCKETMQ_TOPIC;//topie
extern std::string G_ROCKETMQ_TAG;//tag
extern std::string G_ROCKETMQ_KEY;//key
extern std::string G_MQCONSUMER_TOPIC_LOG;
extern std::string G_MQCONSUMER_TOPIC_SET;
extern std::string G_MQCONSUMER_TOPIC_RC;
extern std::string G_MQCONSUMER_TOPIC_UD;
extern std::string G_MQCONSUMER_TOPIC_RT;
extern std::string FRONT_INST;
extern bool DEBUGOPEN;
#ifdef __cplusplus
extern "C" {
#endif
extern std::string G_MQCONSUMER_TOPIC_SET; // C++ 中的全局变量声明
#ifdef __cplusplus
}
#endif
@@ -73,20 +83,40 @@ extern std::string G_MQCONSUMER_CHANNEL;
class RocketMQConsumer;
// 全局映射CPushConsumer* -> RocketMQConsumer*
std::map<CPushConsumer*, RocketMQConsumer*> g_consumerMap;//
pthread_mutex_t g_consumerMapMutex = PTHREAD_MUTEX_INITIALIZER;
//std::map<CPushConsumer*, RocketMQConsumer*> g_consumerMap;//
//pthread_mutex_t g_consumerMapMutex = PTHREAD_MUTEX_INITIALIZER;
////////////////////////////////
int64_t G_APP_START_MS = []() -> int64_t {
using namespace std::chrono;
return duration_cast<milliseconds>(
system_clock::now().time_since_epoch()
).count();
}();
int64_t G_START_SKEW_MS = 1000;
bool should_process_after_start(const rocketmq::MQMessageExt& msg)
{
const int64_t born_ts = static_cast<int64_t>(msg.getBornTimestamp());
return born_ts >= (G_APP_START_MS - G_START_SKEW_MS);
}
///////////////////////////////
class InternalListener;
class RocketMQConsumer {
public:
// 构造函数:初始化消费者并启动
RocketMQConsumer(const std::string& consumerName, const std::string& nameServer, const std::string& groupId);
RocketMQConsumer(const std::string& consumerName, const std::string& nameServer);
// 禁用拷贝和赋值
RocketMQConsumer(const RocketMQConsumer&) {}
//RocketMQConsumer(const RocketMQConsumer&) {}
RocketMQConsumer& operator=(const RocketMQConsumer&) { return *this; }
// 订阅主题和标签,并注册回调
void subscribe(const std::string& topic, const std::string& tag, MessageCallBack callback);
void subscribe(const std::string& topic,
const std::string& tag,
MessageCallBack callback);
// 启动消费者
void start();
@@ -94,23 +124,47 @@ public:
//修改消费模式
void setConsumerMessageModel(const std::string& topic);
rocketmq::ConsumeStatus handleMessage(const rocketmq::MQMessageExt& msg);
// 析构函数:关闭并销毁消费者
~RocketMQConsumer();
private:
CPushConsumer* consumer_; // C 接口消费者指针
//CPushConsumer* consumer_; // C 接口消费者指针
//MessageCallBack messageCallback_; // 函数指针用于回调
rocketmq::DefaultMQPushConsumer consumer_;
InternalListener* listener_;
std::map<std::pair<std::string, std::string>, MessageCallBack> callbacks_; // 订阅到回调的映射
// 静态消息处理回调
/*// 静态消息处理回调
static int messageHandler(CPushConsumer* consumer, CMessageExt* msg);
// 实例消息处理函数
int handleMessage(CMessageExt* msg);
};
int handleMessage(CMessageExt* msg);*/
// 构造函数实现
RocketMQConsumer::RocketMQConsumer(const std::string& consumerName, const std::string& nameServer, const std::string& groupId)
};
class InternalListener : public rocketmq::MessageListenerConcurrently {
public:
explicit InternalListener(RocketMQConsumer* owner)
: owner_(owner) {}
rocketmq::ConsumeStatus consumeMessage(
const std::vector<rocketmq::MQMessageExt>& msgs) override
{
for (size_t i = 0; i < msgs.size(); ++i) {
rocketmq::ConsumeStatus ret = owner_->handleMessage(msgs[i]);
if (ret != rocketmq::CONSUME_SUCCESS) {
return ret;
}
}
return rocketmq::CONSUME_SUCCESS;
}
private:
RocketMQConsumer* owner_;
};
// 构造函数实现C
/*RocketMQConsumer::RocketMQConsumer(const std::string& consumerName, const std::string& nameServer, const std::string& groupId)
: consumer_(NULL)//, messageCallback_(NULL)
{
// 创建消费者
@@ -157,12 +211,29 @@ RocketMQConsumer::RocketMQConsumer(const std::string& consumerName, const std::s
pthread_mutex_unlock(&g_consumerMapMutex);
std::cout << "RocketMQ Consumer initialized and started." << std::endl;
}*/
//构造函数实现C++
RocketMQConsumer::RocketMQConsumer(const std::string& consumerGroup,
const std::string& nameServer)
: consumer_(consumerGroup),
listener_(NULL)
{
consumer_.setNamesrvAddr(nameServer);
consumer_.setSessionCredentials(
G_MQCONSUMER_ACCESSKEY,
G_MQCONSUMER_SECRETKEY,
G_MQCONSUMER_CHANNEL
);
listener_ = new InternalListener(this);
}
// 启动消费者
void RocketMQConsumer::start()
{
if (StartPushConsumer(consumer_) != 0) {
/*if (StartPushConsumer(consumer_) != 0) {
pthread_mutex_lock(&g_consumerMapMutex);
g_consumerMap.erase(consumer_);
pthread_mutex_unlock(&g_consumerMapMutex);
@@ -171,21 +242,26 @@ void RocketMQConsumer::start()
}
else{
std::cout << "RocketMQ Consumer started." << std::endl;
}
}*/
consumer_.registerMessageListener(listener_);
consumer_.start();
}
void RocketMQConsumer::subscribe(const std::string& topic, const std::string& tag, MessageCallBack callback)
{
if (Subscribe(consumer_, topic.c_str(), tag.c_str()) != 0) {
/*if (Subscribe(consumer_, topic.c_str(), tag.c_str()) != 0) {
throw std::runtime_error("Failed to subscribe to topic/tag.");
}
}*/
consumer_.subscribe(topic, tag);
//调试用
std::cout << "Subscribed to topic: " << topic << ", tag: " << tag << std::endl;
// 使用 std::pair 作为键
std::pair<std::string, std::string> key(topic, tag);
callbacks_[key] = callback;
std::pair<std::string, std::string> mapKey(topic, tag);
callbacks_[mapKey] = callback;
}
/*
// 静态消息处理回调实现
int RocketMQConsumer::messageHandler(CPushConsumer* consumer, CMessageExt* msg)
{
@@ -206,68 +282,66 @@ int RocketMQConsumer::messageHandler(CPushConsumer* consumer, CMessageExt* msg)
return instance->handleMessage(msg);
} else {
std::cerr << "Consumer instance not found for callback." << std::endl;
return E_RECONSUME_LATER; // 默认返回重试状态
//return E_RECONSUME_LATER; // 默认返回重试状态
return rocketmq::RECONSUME_LATER;
}
}
int RocketMQConsumer::handleMessage(CMessageExt* msg)
*/
/*int RocketMQConsumer::handleMessage(CMessageExt* msg)
{
// 检查 msg 和 consumer_ 是否为 NULL
if (!msg || !consumer_) {
std::cerr << "Received null message or consumer." << std::endl;
return E_RECONSUME_LATER;
}
//return E_RECONSUME_LATER;
return rocketmq::RECONSUME_LATER;
}*/
// 获取消息的主题和标签
std::string topic = GetMessageTopic(msg); // 假设存在此函数
std::string tag = GetMessageTags(msg); // 假设存在此函数
//std::string topic = GetMessageTopic(msg); // 假设存在此函数
//std::string tag = GetMessageTags(msg); // 假设存在此函数
// 打印调试信息
std::cout << "Handling message for topic: " << topic << ", tag: " << tag << std::endl;
// 使用 std::pair 作为键
std::pair<std::string, std::string> key(topic, tag);
// 查找对应的回调函数
std::map<std::pair<std::string, std::string>, MessageCallBack>::iterator it = callbacks_.find(key);
if (it != callbacks_.end()) {
// 调用对应的回调函数
//调试
std::cout << "callback Handling message " <<std::endl;
return it->second(consumer_, msg);
} else {
//调试
std::cout << "there is no callback " <<std::endl;
// 如果没有找到对应的回调,执行默认处理
const char* body = GetMessageBody(msg);
const char* msgKey = GetMessageKeys(msg);
if (body) {
std::cout << "Received message body: " << body << std::endl;
} else {
std::cout << "Received message with empty body." << std::endl;
}
if (msgKey) {
std::cout << "Message Key: " << msgKey << std::endl;
} else {
std::cout << "Message Key: N/A" << std::endl;
}
return E_CONSUME_SUCCESS;
}
rocketmq::ConsumeStatus RocketMQConsumer::handleMessage( const rocketmq::MQMessageExt& msg) {
std::string tag = msg.getTags();
std::string topic = msg.getTopic();
// 打印调试信息
std::cout << "Handling message for topic: " << topic << ", tag: " << tag << std::endl;
// 使用 std::pair 作为键
std::pair<std::string, std::string> key(topic, tag);
// 查找对应的回调函数
std::map<std::pair<std::string, std::string>, MessageCallBack>::iterator it = callbacks_.find(key);
if (it != callbacks_.end())
{ // 调用对应的回调函数
//调试
std::cout << "callback Handling message " <<std::endl;
//return it->second(consumer_, msg);
return it->second(msg);
}
else {
//调试
std::cout << "there is no callback " <<std::endl;
// 如果没有找到对应的回调,执行默认处理
//const char* body = GetMessageBody(msg);
//const char* msgKey = GetMessageKeys(msg);
std::string body = msg.getBody();
std::string msgKey = msg.getKeys();
if (!body.empty()) {
std::cout << "Received message body: " << body << std::endl;
} else {
std::cout << "Received message with empty body." << std::endl;
} if (!msgKey.empty()) {
std::cout << "Message Key: " << msgKey << std::endl;
} else {
std::cout << "Message Key: N/A" << std::endl;
} //return E_CONSUME_SUCCESS;
return rocketmq::CONSUME_SUCCESS;
}
}
// 析构函数实现
RocketMQConsumer::~RocketMQConsumer()
{
if (consumer_) {
/*if (consumer_) {
// 关闭消费者
ShutdownPushConsumer(consumer_);
@@ -281,7 +355,16 @@ RocketMQConsumer::~RocketMQConsumer()
consumer_ = NULL;
std::cout << "RocketMQ Consumer shutdown and destroyed." << std::endl;
}*/
try {
consumer_.shutdown();
} catch (...) {
}
delete listener_;
listener_ = NULL;
std::cout << "RocketMQ Consumer shutdown and destroyed." << std::endl;
}
// 在 RocketMQConsumer 类中新增函数用来设置消费模式
@@ -296,11 +379,13 @@ void RocketMQConsumer::setConsumerMessageModel(const std::string& topic)
}
} else*/ {
// 默认设置为广播消费模式
if (SetPushConsumerMessageModel(consumer_, BROADCASTING) != 0) {
/*if (SetPushConsumerMessageModel(consumer_, BROADCASTING) != 0) {
std::cout << "Error setting message model to BROADCASTING for topic: " << topic << std::endl;
} else {
std::cout << "Set consumer to BROADCASTING for topic: " << topic << std::endl;
}
}*/
consumer_.setMessageModel(rocketmq::BROADCASTING);
std::cout << "Set consumer to BROADCASTING for topic: " << topic << std::endl;
}
}
@@ -316,11 +401,12 @@ void InitializeConsumer(
if (g_consumer == NULL) {
std::cout << "create new consumer!" << std::endl;
try {
g_consumer = new RocketMQConsumer(consumerName, nameServer,consumerName);//用消费名作为消费组不同进程不同的消费者同时消费topic的同一条消息
//g_consumer = new RocketMQConsumer(consumerName, nameServer,consumerName);//用消费名作为消费组不同进程不同的消费者同时消费topic的同一条消息
g_consumer = new RocketMQConsumer(consumerName, nameServer);
for (size_t i = 0; i < subscriptions.size(); ++i) {
g_consumer->setConsumerMessageModel(subscriptions[i].topic);//初始化时根据topic设置消费模式
g_consumer->subscribe(subscriptions[i].topic, subscriptions[i].tag, subscriptions[i].callback);
g_consumer->subscribe(subscriptions[i].topic, subscriptions[i].tag,subscriptions[i].callback);
}
g_consumer->start();
@@ -367,7 +453,7 @@ void rocketmq_consumer_receive(
static int currentQueueId = 0;
// 队列选择器回调函数:轮询选择队列 ID
int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) {
/*int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) {
if (queueNum == 0) {
throw std::runtime_error("No available queues");
}
@@ -377,27 +463,60 @@ int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) {
currentQueueId = 0;
}
return queueId;
}*/
int RoundRobinSelector(int queueNum, CMessage* msg, void* arg) {
static std::atomic<int> currentQueueId(0);
if (queueNum <= 0) {
std::cout << "[MQ][SELECTOR_FAIL] queueNum=" << queueNum << std::endl;
return -1;
}
int id = currentQueueId.fetch_add(1, std::memory_order_relaxed);
int queueId = id % queueNum;
std::cout << "[MQ][SELECTOR] queueNum=" << queueNum
<< ", current=" << id
<< ", selected=" << queueId
<< std::endl;
return queueId;
}
// 封装生产者的类
class RocketMQProducer {
public:
RocketMQProducer(const std::string& producerName, const std::string& nameServer)
: producer_(NULL)
: producer_(producerName)
{
// 创建生产者
producer_ = CreateProducer(producerName.c_str());
/*producer_ = CreateProducer(producerName.c_str());
if (producer_ == NULL) {
throw std::runtime_error("Failed to create producer.");
}
}*/
// 设置日志
producer_.setLogLevel(rocketmq::eLOG_LEVEL_ERROR);
producer_.setLogFileSizeAndNum(5, 50);
// 设置 nameserver 地址
SetProducerNameServerAddress(producer_, nameServer.c_str());
//SetProducerNameServerAddress(producer_, nameServer.c_str());
producer_.setNamesrvAddr(nameServer);
SetProducerSessionCredentials(producer_, G_MQCONSUMER_ACCESSKEY.c_str(),G_MQCONSUMER_SECRETKEY.c_str(), "");
//lnk20260417设置数据上送消息体最大值默认4M调整为1M避免过大消息导致发送失败
//SetProducerMaxMessageSize(producer_, 1024 * 1024); // 1MB
producer_.setMaxMessageSize(1024 * 1024);
//SetProducerSessionCredentials(producer_, G_MQCONSUMER_ACCESSKEY.c_str(),G_MQCONSUMER_SECRETKEY.c_str(), "");
producer_.setSessionCredentials(
G_MQCONSUMER_ACCESSKEY,
G_MQCONSUMER_SECRETKEY,
""
);
// 启动生产者
StartProducer(producer_);
//StartProducer(producer_);
producer_.start();
std::cout << "rocketmq_Producer initialized and started." << std::endl;
}
@@ -406,7 +525,7 @@ public:
RocketMQProducer(const RocketMQProducer&) = delete;
RocketMQProducer& operator=(const RocketMQProducer&) = delete;
void printSendResult(const CSendResult& result) {
/*void printSendResult(const CSendResult& result) {
std::cout << "SendResult:" << std::endl;
std::cout << " Status: ";
switch (result.sendStatus) {
@@ -430,10 +549,68 @@ public:
std::cout << " MsgID : " << result.msgId << std::endl;
std::cout << " Offset: " << result.offset << std::endl;
}
}*/
// 发送消息
void sendMessage(const char* strbody, const char* topic, const std::string& tags, const std::string& keys) {
/* void sendMessage(const char* strbody, const char* topic, const std::string& tags, const std::string& keys) {
if (DEBUGOPEN) {
std::cout << "sendMessage called with topic: " << (topic ? topic : "NULL")
<< ", tags: " << tags
<< ", keys: " << keys
<< std::endl;
if (strbody) {
// ===== 1⃣ 真实长度 vs strlen =====
std::string body_str(strbody);
std::cout << "[MQ][LEN_CHECK]"
<< " strlen=" << strlen(strbody)
<< ", std::string.size=" << body_str.size()
<< std::endl;
// ===== 2⃣ 检测是否包含 \0 =====
bool has_null = false;
for (size_t i = 0; i < body_str.size(); i++) {
if (body_str[i] == '\0') {
has_null = true;
std::cout << "[MQ][FOUND_NULL] index=" << i << std::endl;
break;
}
}
std::cout << "[MQ][HAS_NULL] " << (has_null ? "YES" : "NO") << std::endl;
// ===== 3⃣ 打印头部(可读)=====
size_t len = strlen(strbody);
size_t n = std::min((size_t)200, len);
std::cout << "[MQ][BODY_HEAD] "
<< std::string(strbody, n)
<< std::endl;
std::cout << "[MQ][BODY_TAIL] "
<< std::string(strbody + (len - n), n)
<< std::endl;
// ===== 4⃣ 十六进制打印前100字节 =====
std::cout << "[MQ][HEX_HEAD] ";
for (size_t i = 0; i < std::min((size_t)100, body_str.size()); i++) {
printf("%02X ", (unsigned char)body_str[i]);
}
printf("\n");
// ===== 5⃣ 十六进制打印尾部100字节 =====
std::cout << "[MQ][HEX_TAIL] ";
size_t start = (body_str.size() > 100) ? body_str.size() - 100 : 0;
for (size_t i = start; i < body_str.size(); i++) {
printf("%02X ", (unsigned char)body_str[i]);
}
printf("\n");
} else {
std::cout << "[MQ][ERROR] strbody is NULL" << std::endl;
}
}
CSendResult result;
CMessage* msg = NULL;
@@ -458,11 +635,67 @@ public:
RoundRobinSelector, // 队列选择器回调函数
&queueNum // 传递给选择器的额外参数(队列数量)
);
/////////////////////////////////替换接口,性能较低但不影响
/*CSendResult result;
memset(&result, 0, sizeof(result));
int sendResult = SendMessageOrderly(
producer_,
msg,
RoundRobinSelector,
&queueNum,
0, // autoRetryTimes
&result
);
std::cout << "[MQ][ORDERLY_RESULT]"
<< " ret=" << sendResult
<< ", sendStatus=" << (int)result.sendStatus
<< ", msgId=" << result.msgId
<< ", offset=" << result.offset
<< ", topic=" << (topic ? topic : "")
<< ", body_len=" << (strbody ? strlen(strbody) : 0)
<< std::endl;*/
/////////////////////////////////替换接口,性能较低但不影响
// 发送消息:临时改成同步发送,绕过 orderly / selector便于定位问题
/*CSendResult result;
memset(&result, 0, sizeof(result));
int sendResult = SendMessageSync(
producer_,
msg,
&result
);
std::cout << "[MQ][SYNC_RESULT]"
<< " ret=" << sendResult
<< ", sendStatus=" << (int)result.sendStatus
<< ", msgId=" << result.msgId
<< ", offset=" << result.offset
<< ", topic=" << (topic ? topic : "")
<< ", body_len=" << (strbody ? strlen(strbody) : 0)
<< std::endl;*/
// 发送消息:临时改成同步发送,绕过 orderly / selector便于定位问题
if (sendResult == 0) { // 假设返回 0 表示成功
std::cout << "Message sent successfully.topic:" << topic <<std::endl;
/*if (sendResult == 0) { // 假设返回 0 表示成功
std::cout << "[MQ][SEND_OK]"
<< " topic=" << (topic ? topic : "")
<< ", tags=" << tags
<< ", keys=" << keys
<< ", body_len=" << (strbody ? strlen(strbody) : 0)
<< std::endl;
} else {
std::cout << "Failed to send message." << std::endl;
std::cout << "[MQ][SEND_FAIL]"
<< " ret=" << sendResult
<< ", topic=" << (topic ? topic : "")
<< ", tags=" << tags
<< ", keys=" << keys
<< ", body_len=" << (strbody ? strlen(strbody) : 0)
<< std::endl;
std::cout << "[MQ][BODY_HEAD] " << std::string(strbody, std::min((size_t)200, strlen(strbody))) << std::endl;
std::cout << "[MQ][BODY_TAIL] " << std::string(strbody + std::max((size_t)0, strlen(strbody) - std::min((size_t)200, strlen(strbody)))) << std::endl;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_MQ,"【ERROR】前置的%s%d号进程 mq发送失败,请检查mq配置", get_front_msg_from_subdir(), g_front_seg_index);
}
// 销毁消息
@@ -489,20 +722,97 @@ public:
DestroyMessage(msg);
}
}
}*/
void sendMessage(const std::string& body,
const std::string& topic,
const std::string& tags,
const std::string& keys)
{
try {
if (DEBUGOPEN) {
std::cout << "sendMessage called with topic: " << topic
<< ", tags: " << tags
<< ", keys: " << keys
<< ", body_len=" << body.size()
<< std::endl;
size_t n = std::min((size_t)200, body.size());
std::cout << "[MQ][BODY_HEAD] "
<< body.substr(0, n)
<< std::endl;
if (body.size() > n) {
std::cout << "[MQ][BODY_TAIL] "
<< body.substr(body.size() - n, n)
<< std::endl;
}
std::cout << "[MQ][HEX_HEAD] ";
for (size_t i = 0; i < std::min((size_t)100, body.size()); ++i) {
printf("%02X ", (unsigned char)body[i]);
}
printf("\n");
}
rocketmq::MQMessage msg(topic, tags, keys, body);
rocketmq::SendResult result = producer_.send(msg);
std::cout << "[MQ][SEND_OK]"
<< " topic=" << topic
<< ", tags=" << tags
<< ", keys=" << keys
<< ", msgId=" << result.getMsgId()
<< ", status=" << result.getSendStatus()
<< ", body_len=" << body.size()
<< std::endl;
}
catch (const rocketmq::MQClientException& e) {
std::cerr << "[MQ][SEND_FAIL] MQClientException: "
<< e.what() << std::endl;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_MQ,
"【ERROR】前置的%s%d号进程 mq发送失败,mq客户端错误,请检查mq配置",
get_front_msg_from_subdir(), g_front_seg_index);
}
catch (const std::exception& e) {
std::cerr << "[MQ][SEND_FAIL] exception: "
<< e.what() << std::endl;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_MQ,
"【ERROR】前置的%s%d号进程 mq发送失败,mq发送错误,发送请检查mq配置",
get_front_msg_from_subdir(), g_front_seg_index);
}
catch (...) {
std::cerr << "[MQ][SEND_FAIL] unknown exception" << std::endl;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_MQ,
"【ERROR】前置的%s%d号进程 mq发送失败,未知错误,请检查mq配置",
get_front_msg_from_subdir(), g_front_seg_index);
}
}
// 析构函数中关闭并销毁生产者
~RocketMQProducer() {
if (producer_) {
/*if (producer_) {
ShutdownProducer(producer_);
DestroyProducer(producer_);
std::cout << "rocketmq_Producer shutdown and destroyed." << std::endl;
}*/
try {
producer_.shutdown();
}
catch (...) {
}
std::cout << "rocketmq_Producer shutdown and destroyed." << std::endl;
}
private:
CProducer* producer_;
//CProducer* producer_;
rocketmq::DefaultMQProducer producer_;
};
// 全局生产者实例
@@ -513,7 +823,7 @@ void InitializeProducer()
{
if (g_producer == NULL) {
try {
g_producer = new RocketMQProducer(G_ROCKETMQ_PRODUCER, G_ROCKETMQ_IPPORT);
g_producer = new RocketMQProducer(G_ROCKETMQ_PRODUCER, G_ROCKETMQ_IPPORT);//生产者名称和NameServer地址
}
catch (const std::exception& e) {
std::cerr << "Failed to initialize producer: " << e.what() << std::endl;
@@ -533,34 +843,33 @@ void ShutdownAndDestroyProducer()
}
// 发送消息的接口函数
void rocketmq_producer_send(const char* strbody, const char* topic)
void rocketmq_producer_send(const std::string& body,
const std::string& topic,
const std::string& tags,
const std::string& keys)
{
if (g_producer == NULL) {
try {
InitializeProducer();
}
catch (...) {
} catch (...) {
std::cerr << "Cannot send message because producer initialization failed." << std::endl;
return;
}
}
// 假设 tags 和 keys 是固定的,可以根据需要修改
std::string tags = G_ROCKETMQ_TAG;
std::string keys = G_ROCKETMQ_KEY;
try {
g_producer->sendMessage(strbody, topic, tags, keys);
}
catch (const std::exception& e) {
g_producer->sendMessage(body, topic, tags, keys);
} catch (const std::exception& e) {
std::cerr << "Failed to send message: " << e.what() << std::endl;
// 处理发送失败的情况,例如记录日志或重试
DIY_ERRORLOG_CODE("process",LOG_CODE_MQ,"【ERROR】前置的%s%d号进程 mq发送失败,请检查mq配置", get_front_msg_from_subdir(), g_front_seg_index);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_MQ,
"【ERROR】前置的%s%d号进程 mq发送失败,请检查mq配置",
get_front_msg_from_subdir(), g_front_seg_index);
}
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
// producer_send0测试用
void StartSendMessage(CProducer* producer)
{
@@ -645,11 +954,11 @@ void producer_send(const char* strbody)
DestroyProducer(producer);
cout << "Producer Shutdown!" << endl;
}
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////
extern "C" {
extern std::string G_MQCONSUMER_TOPIC_RT;
//extern std::string G_MQCONSUMER_TOPIC_RT;
void rocketmq_test_rt()
{
Ckafka_data_t data;
@@ -663,7 +972,7 @@ void rocketmq_test_rt()
data.mp_id = 123123;
my_rocketmq_send(data);
}
extern std::string G_MQCONSUMER_TOPIC_UD;
//extern std::string G_MQCONSUMER_TOPIC_UD;
void rocketmq_test_ud()//用来测试台账更新
{
Ckafka_data_t data;
@@ -706,7 +1015,7 @@ void rocketmq_test_only()//用来测试进程控制脚本
my_rocketmq_send(data);
}
extern std::string G_MQCONSUMER_TOPIC_RC;
//extern std::string G_MQCONSUMER_TOPIC_RC;
void rocketmq_test_rc()
{
Ckafka_data_t data;
@@ -721,7 +1030,7 @@ void rocketmq_test_rc()
my_rocketmq_send(data);
}
extern std::string G_MQCONSUMER_TOPIC_LOG;
//extern std::string G_MQCONSUMER_TOPIC_LOG;
void rocketmq_test_log()
{
Ckafka_data_t data;

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
#include "../log4cplus/fileappender.h"
#include "../log4cplus/layout.h"
#include "../log4cplus/ndc.h"
#include "../log4cplus/log4.h"
//#include "../log4cplus/log4.h"
#include "../log4cplus/spi/loggingevent.h"
#include <iostream>
#include <map>
@@ -18,21 +18,47 @@
//目录创建
#include <sys/stat.h>
#include <sys/types.h>
//kafka结构定义
#include "../json/mms_json_inter.h"
#include "../mms/rdb_client.h"
#include "../include/node.h"//lnk20241223
#include "../log4cplus/log4.h"//后移防止min/max定义冲突
///////////////////////////////////////////////lnk20260303添加日志上送控制
#include <unordered_map>
#include <chrono>
#include <mutex>
#include <atomic>
#include <memory>
struct LogLevelCache { //记录日志等级的缓存减少频繁访问全局map的开销
std::unordered_map<std::string, int> term_min; // terminal_id -> min level
std::unordered_map<std::string, int> mp_min; // mp_id -> min level
};
// append线程只读不加锁
static std::shared_ptr<LogLevelCache> g_level_cache_sp;
///////////////////////////////////////////////
//用来控制日志上送的结构
struct LOGEntry {
std::string id;
std::string level; // terminal / measurepoint
int code; //code
int min_grade; //允许上送的最低日志等级
int countdown; //自动关闭的倒计时,单位秒
};
//日志上送map管理
std::map<std::string, LOGEntry> g_log_entries;
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
/////////////////////////////////////////////外部定义
extern unsigned int g_node_id;
extern int g_front_seg_index;
extern std::string FRONT_INST;
extern char subdir[128];
extern node_t* g_node;
//mq
extern QMutex kafka_data_list_mutex; //Kafka发送数据锁
extern QList<Ckafka_data_t> kafka_data_list; //kafka发送数据链表
@@ -43,11 +69,161 @@ extern std::string intToString(int number);
//日志主题
extern std::string G_LOG_TOPIC;
// 日志限流配置
extern int G_LOG_RATE_RESET_SEC;
extern int G_LOG_RATE_LIMIT_SEC;
extern int G_LOG_RATE_KEEP_ALL_MS;
extern int G_LOG_RATE_KEEP_BURST_MS;
extern int G_LOG_RATE_KEEP_BURST_COUNT;
extern int G_LOG_RATE_KEEP_HIGHFREQ_COUNT;
/////////////////////////////////////////////////////////
//log4命名空间
using namespace log4cplus;
using namespace log4cplus::helpers;
///////////////////////////////////////////////////////////////
static std::string extract_logger_id(const std::string& logger_name);
////////////////////////////////////////////////////////辅助函数
///////////////////////////////////////////////////////lnk20260303添加日志上送控制
//用于在台账中查询日志上送控制项的日志等级字符串转换为整数
static int int_to_loglevel(int v, int default_level = WARN_LOG_LEVEL)
{
switch (v) {
case 0: return ERROR_LOG_LEVEL;
case 1: return WARN_LOG_LEVEL;
case 2: return INFO_LOG_LEVEL;
case 3: return DEBUG_LOG_LEVEL;
default: return default_level;
}
}
// 构建日志等级缓存,减少 append 线程访问全局 map 的开销
static LogLevelCache* build_cache_unlocked()
{
LogLevelCache* nc = new LogLevelCache;
// 没 node / 没 clients返回空 cache查不到会兜底 WARN
if (!g_node || g_node->n_clients <= 0 || !g_node->clients) {
return nc;
}
// 你 LD_info 是固定 10 个就用 10如果不是改成实际长度
const int MAX_LD = 10;
for (int iedno = 0; iedno < g_node->n_clients; ++iedno) {
ied_t* ied = g_node->clients[iedno];
if (!ied || !ied->usr_ext) continue;
ied_usr_t* ied_usr = (ied_usr_t*)ied->usr_ext;
// terminal_id 必须有效
const char* tid = ied_usr->terminal_id;
if (!tid || tid[0] == '\0') continue;
const std::string terminal_id(tid);
// 装置级阈值0~3 -> log4cplus level默认 WARN
const int term_lv = int_to_loglevel(ied_usr->log_level, WARN_LOG_LEVEL);
nc->term_min[terminal_id] = term_lv;
// 监测点阈值:若非法/缺失,兜底用装置级 term_lv
for (int i = 0; i < MAX_LD; ++i) {
const char* mp = ied_usr->LD_info[i].mp_id;
if (!mp || mp[0] == '\0') continue;
const std::string mp_id(mp);
// mp 的 log_level 优先;非法则用 term_lv
const int mp_lv = int_to_loglevel(ied_usr->LD_info[i].log_level, term_lv);
nc->mp_min[mp_id] = mp_lv;
}
}
return nc;
}
//用于更新日志等级缓存的函数,获取最新的日志上送控制项并更新到缓存中,调用时需持锁
void refresh_log_level_cache_locked()
{
std::shared_ptr<LogLevelCache> nc(build_cache_unlocked());
std::atomic_store(&g_level_cache_sp, nc);
}
const int LOGTYPE_DEFAULT = LOG_CODE_OTHER; // 默认日志类型,表示不区分具体类型的日志上送控制
static const int LOGTYPE_WILDCARD = 999; // 用于匹配任意日志类型的特殊值
static const char* ID_WILDCARD = "all"; // 用于匹配任意 ID 的特殊值
static std::string build_debug_key(const std::string& id,
const std::string& level, // terminal/measurepoint/process
int code) // 日志类型
{
std::ostringstream oss;
oss << id << "|" << level << "|" << code;
return oss.str();
}
static bool find_entry_allow(const std::string& key, int level_val)
{
std::map<std::string, LOGEntry>::iterator it = g_log_entries.find(key);
if (it == g_log_entries.end() || it->second.countdown <= 0) return false;
return level_val >= it->second.min_grade;
}
static bool allow_low_level_send(const std::string& id,
const std::string& level_str,
int code,
int level_val)
{
pthread_mutex_lock(&g_log_mutex);
// 1) 精确
if (find_entry_allow(build_debug_key(id, level_str, code), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
// 2) logtype 通配
if (find_entry_allow(build_debug_key(id, level_str, LOGTYPE_WILDCARD), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
// 3) id 通配
if (find_entry_allow(build_debug_key(ID_WILDCARD, level_str, code), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
// 4) 双通配
if (find_entry_allow(build_debug_key(ID_WILDCARD, level_str, LOGTYPE_WILDCARD), level_val)) {
pthread_mutex_unlock(&g_log_mutex);
return true;
}
pthread_mutex_unlock(&g_log_mutex);
return false;
}
static int get_min_send_level_cached(const std::string& level_str, const std::string& logger_name)
{
const int DEFAULT_LEVEL = WARN_LOG_LEVEL;
if (level_str == "process") return DEFAULT_LEVEL;
const std::string id = extract_logger_id(logger_name); //terminal.<id> / monitor.<mp>
if (id.empty()) return DEFAULT_LEVEL;
std::shared_ptr<LogLevelCache> c = std::atomic_load(&g_level_cache_sp);
if (!c) return DEFAULT_LEVEL;
if (level_str == "terminal") {
auto it = c->term_min.find(id);
return (it != c->term_min.end()) ? it->second : DEFAULT_LEVEL;
}
if (level_str == "measurepoint") {
auto it = c->mp_min.find(id);
return (it != c->mp_min.end()) ? it->second : DEFAULT_LEVEL;
}
return DEFAULT_LEVEL;
}
///////////////////////////////////////////////////////lnk20260303添加日志上送控制
std::string get_front_type_from_subdir() {
if (std::strstr(subdir, "cfg_3s_data") != NULL)
return "realTime";
@@ -79,12 +255,11 @@ bool create_directory_recursive(const std::string& path) {
}
//////////////////////////////////////////////////////////////////////
std::string extract_logger_id(const std::string& logger_name) {
size_t first = logger_name.find('.');
size_t last = logger_name.rfind('.');
if (first != std::string::npos && last != std::string::npos && first + 1 < last) {
return logger_name.substr(first + 1, last - first - 1); // 去掉开头"terminal."和结尾".COM"
}
return "";
if (logger_name == "process") return "process";
size_t pos = logger_name.find('.');
if (pos == std::string::npos) return "";
// 取第一个 '.' 后面的全部terminal.<id> / monitor.<mp>
return logger_name.substr(pos + 1);
}
std::string get_level_str(int level) {
@@ -98,7 +273,7 @@ std::string get_level_str(int level) {
}
//////////////////////////////////////////////////////////////////////
TypedLogger::TypedLogger() {}
TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), logtype(t) {}
TypedLogger::TypedLogger(const Logger& l, int t) : logger(l), code(t) {}
DebugSwitch::DebugSwitch() : debug_open(false), min_level(WARN_LOG_LEVEL) {}
void DebugSwitch::open() { debug_open = true; }
@@ -132,46 +307,81 @@ LOG_TLS int g_log_code_tls = 0;
class SendAppender : public Appender {
protected:
void append(const spi::InternalLoggingEvent& event) {
void append(const spi::InternalLoggingEvent& event) override {
std::string logger_name = event.getLoggerName();
int level = event.getLogLevel();
std::string msg = event.getMessage();
int logtype = (logger_name.find(".COM") != std::string::npos) ? LOGTYPE_COM : LOGTYPE_DATA;
std::string level_str;
if (logger_name.find("process") == 0)
level_str = "process";
else if (logger_name.find("monitor") != std::string::npos)
level_str = "measurepoint";
else
else if (logger_name.find("terminal") != std::string::npos)
level_str = "terminal";
else
level_str = "process";
// ★读取 TLS 中的 code(在打日志的线程里由宏设定)
int code = g_log_code_tls; // 若未显式传入,则为 0
int code = g_log_code_tls; // TLS code
int safe_logtype = code; // ★关键:用 code 当 logtype 维度
if (level == ERROR_LOG_LEVEL || level == WARN_LOG_LEVEL || g_debug_switch.match(logger_name, level, logtype)) {
std::ostringstream oss;
oss << "{\"processNo\":\"" << intToString(g_front_seg_index)
<< "\",\"nodeId\":\"" << FRONT_INST
<< "\",\"businessId\":\"" << extract_logger_id(logger_name)
<< "\",\"level\":\"" << level_str
<< "\",\"grade\":\"" << get_level_str(level)
<< "\",\"logtype\":\"" << (logtype == LOGTYPE_COM ? "com" : "data")
<< "\",\"frontType\":\"" << get_front_type_from_subdir()
// ★新增:输出 code 字段(整型)
<< "\",\"code\":\"" << code
<< "\",\"log\":\"" << escape_json(msg) << "\"}";
bool allow_send = false;
int min_send_level = get_min_send_level_cached(level_str, logger_name);
std::string jsonString = oss.str();
// ① 高于台账阈值:直接上送
if (level >= min_send_level) {
allow_send = true;
} else {
// ② 低等级:默认不上送,除非命令打开
std::string ctrl_id;
if (level_str == "process") ctrl_id = "process";
else ctrl_id = extract_logger_id(logger_name);
Ckafka_data_t connect_info;
connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC);
connect_info.strText = QString::fromStdString(jsonString);
kafka_data_list_mutex.lock();
kafka_data_list.append(connect_info);
kafka_data_list_mutex.unlock();
if (!ctrl_id.empty()) {
allow_send = allow_low_level_send(ctrl_id, level_str, safe_logtype, level);
}
}
if (!allow_send) return;
// ③ 限频:同一条日志
const std::string rkey = make_key(logger_name, level, code, msg);
uint64_t suppressed_before_emit = 0;
if (!should_emit(rkey, suppressed_before_emit)) return;
// 如果本次输出前压掉过日志,则在 log 文本后追加统计
std::string final_msg = msg;
if (suppressed_before_emit > 0) {
std::ostringstream suppressed_oss;
suppressed_oss << msg << " 【已过滤重复同类日志 "
<< suppressed_before_emit
<< " 条】";
final_msg = suppressed_oss.str();
}
std::string business_id = extract_logger_id(logger_name);
std::string front_type = get_front_type_from_subdir();
std::ostringstream oss;
oss << "{\"processNo\":\"" << intToString(g_front_seg_index)
<< "\",\"nodeId\":\"" << escape_json(FRONT_INST)
<< "\",\"businessId\":\"" << escape_json(business_id)
<< "\",\"level\":\"" << escape_json(level_str)
<< "\",\"grade\":\"" << escape_json(get_level_str(level))
<< "\",\"logtype\":\"" << safe_logtype
<< "\",\"frontType\":\"" << escape_json(front_type)
<< "\",\"code\":" << code
<< ",\"log\":\"" << escape_json(final_msg) << "\"}";
Ckafka_data_t connect_info;
connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC);
connect_info.mp_id = QString::fromStdString(business_id);
connect_info.strText = QString::fromStdString(oss.str());
kafka_data_list_mutex.lock();
kafka_data_list.append(connect_info);
kafka_data_list_mutex.unlock();
}
std::string escape_json(const std::string& input) {
@@ -198,25 +408,128 @@ public:
virtual ~SendAppender() {
destructorImpl(); // 重要!释放 log4cplus 基类资源
}
//////////////////////////////////////////////////////////////////20260303添加日志上送控制 - 频率限制实现
private:
struct RateState {
uint64_t pass_count; // 当前周期内已放行条数
uint64_t suppressed_count; // 当前被抑制条数
std::chrono::steady_clock::time_point last_emit;
std::chrono::steady_clock::time_point last_seen;
std::chrono::steady_clock::time_point last_reset;
bool has_emit;
RateState()
: pass_count(0),
suppressed_count(0),
last_emit(),
last_seen(),
last_reset(),
has_emit(false) {}
};
static std::unordered_map<std::string, RateState> s_rate_map;
static std::mutex s_rate_mutex;
static std::string make_key(const std::string& logger_name, int level, int code, const std::string& msg) {
std::ostringstream oss;
oss << logger_name << "|" << level << "|" << code ; //<< "|" << msg;
return oss.str();
}
static bool should_emit(const std::string& key, uint64_t& suppressed_before_emit) {
using namespace std::chrono;
const auto now = steady_clock::now();
suppressed_before_emit = 0;
std::lock_guard<std::mutex> lk(s_rate_mutex);
RateState& st = s_rate_map[key];
const int RESET_SEC = G_LOG_RATE_RESET_SEC ; // 1小时重置
const int LIMIT_SEC = G_LOG_RATE_LIMIT_SEC ; // 进入限流后多久发1条 主要控制中频和高频那些,低频的都直接放行了
// 初始化 / 强制每小时重置
if (st.last_reset.time_since_epoch().count() == 0) {
st.last_reset = now;
} else {
auto since_reset = duration_cast<seconds>(now - st.last_reset).count();
if (since_reset >= RESET_SEC) { //重置周期
st = RateState();
st.last_reset = now;
}
}
// 计算当前频率档位按“本次与上次看到该key的间隔”判断
// >=60秒/条:全部保留
// [1秒, 60秒)保留前60条然后1分钟1条
// <1秒保留前10条然后1分钟1条
int allow_burst = 0;
if (st.last_seen.time_since_epoch().count() == 0) {
// 第一次看到,先按“全部保留”处理
allow_burst = -1;
} else {
auto gap_ms = duration_cast<milliseconds>(now - st.last_seen).count();
if (gap_ms >= G_LOG_RATE_KEEP_ALL_MS) { //什么时候不需要限流 //低频 //如果这里设置的很低,就不会限流
allow_burst = -1; // 全部保留
} else if (gap_ms >= G_LOG_RATE_KEEP_BURST_MS) {
allow_burst = G_LOG_RATE_KEEP_BURST_COUNT; // 前60条 //中频 //如果这里设置的比低频低,也不会生效
} else {
allow_burst = G_LOG_RATE_KEEP_HIGHFREQ_COUNT; // 前10条 //高频
}
}
st.last_seen = now;
// 档位1全部保留
if (allow_burst == -1) {
suppressed_before_emit = st.suppressed_count;
st.suppressed_count = 0;
st.pass_count++;
st.last_emit = now;
st.has_emit = true;
return true;
}
// 档位2/3先放前N条
if (st.pass_count < (uint64_t)allow_burst) {
suppressed_before_emit = st.suppressed_count;
st.suppressed_count = 0;
st.pass_count++;
st.last_emit = now;
st.has_emit = true;
return true;
}
// 超过前N条后进入 1分钟1条
if (!st.has_emit) {
suppressed_before_emit = st.suppressed_count;
st.suppressed_count = 0;
st.pass_count++;
st.last_emit = now;
st.has_emit = true;
return true;
}
auto elapsed = duration_cast<seconds>(now - st.last_emit).count();
if (elapsed >= LIMIT_SEC) {
suppressed_before_emit = st.suppressed_count;
st.suppressed_count = 0;
st.pass_count++;
st.last_emit = now;
st.has_emit = true;
return true;
}
// 本条被抑制
st.suppressed_count++;
return false;
}
};
//用来控制日志上送的结构
struct LOGEntry {
std::string id;
std::string level; // terminal / measurepoint
int logtype; // com / data
int min_grade;
int countdown;
};
//日志上送map管理
std::map<std::string, LOGEntry> g_log_entries;
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
// 生成唯一 key
std::string build_debug_key(const std::string& id, const std::string& level, int logtype) {
return id + "|" + level + "|" + (logtype == 1 ? "COM" : "DATA");
}
//////////////////////////////////////////////////////////////////20260303添加日志上送控制 - 频率限制实现
std::unordered_map<std::string, SendAppender::RateState> SendAppender::s_rate_map;
std::mutex SendAppender::s_rate_mutex;
// 外部线程中调用每秒更新所有倒计时0 则删除
void update_log_entries_countdown() {
@@ -236,25 +549,25 @@ void update_log_entries_countdown() {
pthread_mutex_unlock(&g_log_mutex);
}
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str) {
if (level != "terminal" && level != "measurepoint") return;
void process_log_command(const std::string& id,
const std::string& level,
const std::string& grade,
int code)
{
if (level != "terminal" && level != "measurepoint" && level != "process") return;
int type = (logtype_str == "com") ? LOGTYPE_COM : LOGTYPE_DATA;
int grade_level = (grade == "DEBUG") ? DEBUG_LOG_LEVEL : INFO_LOG_LEVEL;
std::string key = build_debug_key(id, level, type);
std::string key = build_debug_key(id, level, code);
pthread_mutex_lock(&g_log_mutex);
LOGEntry& entry = g_log_entries[key]; // 会自动 insert 或取已有
LOGEntry& entry = g_log_entries[key];
entry.id = id;
entry.level = level;
entry.logtype = type;
entry.code = code;
entry.min_grade = grade_level;
entry.countdown = 60; // 重置倒计时
entry.countdown = 60;
pthread_mutex_unlock(&g_log_mutex);
}
Logger init_logger(const std::string& full_name, const std::string& file_dir, const std::string& base_file, SharedAppenderPtr fileAppender) {
@@ -286,7 +599,7 @@ log4cplus::Logger init_logger(const std::string& full_name,
//进程的日志
void init_logger_process() {
std::string base_dir = std::string("/FeProject/") + subdir + "/processNo" + intToString(g_front_seg_index) + "/log";
logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DATA);
logger_map["process"] = TypedLogger(init_logger(std::string("process"), base_dir, std::string("process")), LOGTYPE_DEFAULT);
std::cout << "process log init ok" << std::endl;
}
@@ -321,12 +634,10 @@ void init_loggers_bydevid(const char* dev_id)
std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + dev_id + ".COM";
std::string device_key_d = std::string("terminal.") + dev_id + ".DATA";
std::string device_key = std::string("terminal.") + dev_id;
// 添加判断:终端日志 logger 是否已存在
if (logger_map.find(device_key_c) == logger_map.end() &&
logger_map.find(device_key_d) == logger_map.end()) {
if (logger_map.find(device_key) == logger_map.end()) {
// 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + dev_id + ".log";
@@ -335,27 +646,23 @@ void init_loggers_bydevid(const char* dev_id)
SharedAppenderPtr device_appender = SharedAppenderPtr(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, dev_id, device_appender); //用终端id作为日志文件名
Logger device_logger_d = init_logger(device_key_d, device_dir, dev_id, device_appender); //用终端id作为日志文件名
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
Logger device_logger = init_logger(device_key, device_dir, dev_id, device_appender); //用终端id作为日志文件名
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT);
DIY_INFOLOG(device_key_d.c_str(),"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
DIY_INFOLOG_CODE(device_key.c_str(),1,LOG_CODE_OTHER,"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
}
// 初始化监测点
// 监测点 logger 名称格式monitor.<mp_id>.COM / .DATA
// 监测点 logger 名称格式monitor.<mp_id>
for (int i = 0; i < 10; ++i) {
if (strlen(ied_usr->LD_info[i].mp_id) > 0){
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
mon_key_c << "monitor." << ied_usr->LD_info[i].mp_id << ".COM";
mon_key_d << "monitor." << ied_usr->LD_info[i].mp_id << ".DATA";
std::ostringstream mon_key, mon_path, mon_name;
mon_key << "monitor." << ied_usr->LD_info[i].mp_id;
mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录
mon_name << ied_usr->LD_info[i].mp_id;
// 添加判断:监测点 logger 是否已存在
if (logger_map.find(mon_key_c.str()) == logger_map.end() &&
logger_map.find(mon_key_d.str()) == logger_map.end()) {
if (logger_map.find(mon_key.str()) == logger_map.end()) {
// 所有监测点日志com 和 data写到同一个 monitor 日志文件中
std::string file_path_m = mon_path.str() + "/" + mon_name.str() + ".log";
@@ -364,12 +671,10 @@ void init_loggers_bydevid(const char* dev_id)
SharedAppenderPtr monitor_appender = SharedAppenderPtr(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(),monitor_appender);//用监测点号作为日志文件名
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(),monitor_appender);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(),monitor_appender);//用监测点号作为日志文件名
logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT);
DIY_INFOLOG(mon_key_d.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
DIY_INFOLOG_CODE(mon_key.str().c_str(),2,LOG_CODE_OTHER,"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
}
}
@@ -377,6 +682,9 @@ void init_loggers_bydevid(const char* dev_id)
break; // 只匹配一个 terminal_id
}
//lnk20260303添加日志上送控制 - 初始化时构建日志等级缓存
refresh_log_level_cache_locked();
}
void init_loggers() {
@@ -402,8 +710,7 @@ void init_loggers() {
std::string device_dir = base_dir + "/" + ip_str;
std::string device_key_c = std::string("terminal.") + ied_usr->terminal_id + ".COM";
std::string device_key_d = std::string("terminal.") + ied_usr->terminal_id + ".DATA";
std::string device_key = std::string("terminal.") + ied_usr->terminal_id;
// 所有终端日志com 和 data写到同一个 device 日志文件中
std::string file_path_t = device_dir + "/" + ied_usr->terminal_id + ".log";
@@ -412,21 +719,18 @@ void init_loggers() {
SharedAppenderPtr device_appender = SharedAppenderPtr(new RollingFileAppender(file_path_t, 1 * 1024 * 1024, 2));
device_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger device_logger_c = init_logger(device_key_c, device_dir, ied_usr->terminal_id, device_appender); //用终端id作为日志文件名
Logger device_logger_d = init_logger(device_key_d, device_dir, ied_usr->terminal_id, device_appender); //用终端id作为日志文件名
Logger device_logger = init_logger(device_key, device_dir, ied_usr->terminal_id, device_appender); //用终端id作为日志文件名
logger_map[device_key_c] = TypedLogger(device_logger_c, LOGTYPE_COM);
logger_map[device_key_d] = TypedLogger(device_logger_d, LOGTYPE_DATA);
logger_map[device_key] = TypedLogger(device_logger, LOGTYPE_DEFAULT);
DIY_INFOLOG(device_key_d.c_str(),"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
DIY_INFOLOG_CODE(device_key.c_str(),1,LOG_CODE_OTHER,"【NORMAL】终端id:%s终端级日志初始化完毕", ied_usr->terminal_id);
// 初始化监测点
// 监测点 logger 名称格式monitor.<mp_id>.COM / .DATA
// 监测点 logger 名称格式monitor.<mp_id>
for (int i = 0; i < 10; ++i) {
if (strlen(ied_usr->LD_info[i].mp_id) > 0){
std::ostringstream mon_key_c, mon_key_d, mon_path, mon_name;
mon_key_c << "monitor." << ied_usr->LD_info[i].mp_id << ".COM";
mon_key_d << "monitor." << ied_usr->LD_info[i].mp_id << ".DATA";
std::ostringstream mon_key, mon_path, mon_name;
mon_key << "monitor." << ied_usr->LD_info[i].mp_id;
mon_path << device_dir << "/monitor" << i;//终端路径下用monitor+序号作为目录
mon_name << ied_usr->LD_info[i].mp_id;
@@ -437,19 +741,19 @@ void init_loggers() {
SharedAppenderPtr monitor_appender = SharedAppenderPtr(new RollingFileAppender(file_path_m, 1 * 1024 * 1024, 2));
monitor_appender->setLayout(std::auto_ptr<Layout>(new PatternLayout("%D{%Y-%m-%d %H:%M:%S} [%p] [%c] %m%n")));
Logger mon_logger_c = init_logger(mon_key_c.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger_d = init_logger(mon_key_d.str(), mon_path.str(), mon_name.str(), monitor_appender);
Logger mon_logger = init_logger(mon_key.str(), mon_path.str(), mon_name.str(), monitor_appender);
logger_map[mon_key_c.str()] = TypedLogger(mon_logger_c, LOGTYPE_COM);
logger_map[mon_key_d.str()] = TypedLogger(mon_logger_d, LOGTYPE_DATA);
logger_map[mon_key.str()] = TypedLogger(mon_logger, LOGTYPE_DEFAULT);
DIY_INFOLOG(mon_key_d.str().c_str(),"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
DIY_INFOLOG_CODE(mon_key.str().c_str(),2,LOG_CODE_OTHER,"【NORMAL】监测点:%s - id:%s监测点级日志初始化完毕", ied_usr->LD_info[i].name,ied_usr->LD_info[i].mp_id);
}
}
}
//lnk20260303添加日志上送控制 - 初始化时构建日志等级缓存
refresh_log_level_cache_locked();
}
void remove_loggers_by_terminal_id(const char* terminal_id_cstr) {
@@ -465,37 +769,24 @@ void remove_loggers_by_terminal_id(const char* terminal_id_cstr) {
if (strcmp(ied_usr->terminal_id, terminal_id.c_str()) != 0) continue;
// 删除终端日志 logger
std::string com_key = "terminal." + terminal_id + ".COM";
std::string data_key = "terminal." + terminal_id + ".DATA";
std::string terminal_key = "terminal." + terminal_id;;
if (logger_map.count(com_key)) {
logger_map[com_key].logger.removeAllAppenders();
logger_map.erase(com_key);
}
if (logger_map.count(data_key)) {
logger_map[data_key].logger.removeAllAppenders();
logger_map.erase(data_key);
if (logger_map.count(terminal_key)) {
logger_map[terminal_key].logger.removeAllAppenders();
logger_map.erase(terminal_key);
}
// 删除监测点日志 logger
for (int i = 0; i < 10; ++i) {
const char* mp_id = ied_usr->LD_info[i].mp_id;
if (strlen(mp_id) > 0) {
std::string mon_prefix = std::string("monitor.") + mp_id;
std::string mon_key = std::string("monitor.") + mp_id;
std::string mon_com_key = mon_prefix + ".COM";
std::string mon_data_key = mon_prefix + ".DATA";
if (logger_map.count(mon_com_key)) {
logger_map[mon_com_key].logger.removeAllAppenders();
logger_map.erase(mon_com_key);
if (logger_map.count(mon_key)) {
logger_map[mon_key].logger.removeAllAppenders();
logger_map.erase(mon_key);
}
if (logger_map.count(mon_data_key)) {
logger_map[mon_data_key].logger.removeAllAppenders();
logger_map.erase(mon_data_key);
}
}
}

View File

@@ -1,6 +1,6 @@
/**
* @file: $RCSfile: ied.h,v $
* @brief: $<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽṹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @brief: $设备数据结构定义
*
* @version: $Revision: 1.1 $
* @date: $Date: 2018/11/24 06:54:49 $
@@ -24,35 +24,35 @@ typedef byte_t channel_size_type;
#endif
#define PRV_ANA_EXTENSION (1) //ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
#define PRV_DIGIT_EXTENSION (3) //ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
#define PRV_EVENT_EXTENSION (3) //<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
#define PRV_PULSE_EXTENSION (2) //ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
//-----ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ---------------//
#define ANA_EXTENSION_ALARM (0) //<EFBFBD>澯:<3A><EFBFBD>ȼ<EFBFBD>;<3B><EFBFBD><E6BEAF><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
#define PRV_ANA_EXTENSION (1) //模拟量用户扩展属性 总数
#define PRV_DIGIT_EXTENSION (3) //遥信量用户扩展属性 总数
#define PRV_EVENT_EXTENSION (3) //事件量用户扩展属性 总数
#define PRV_PULSE_EXTENSION (2) //遥测量用户扩展属性 总数
//-----模拟量用户扩展---------------//
#define ANA_EXTENSION_ALARM (0) //告警:告警等级;告警声音文件名
typedef struct analog_t analog_t;
struct analog_t {
byte_t type; /**< <EFBFBD><EFBFBD>ѹ/<2F><><EFBFBD><EFBFBD>/<2F>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD>/<2F>޹<EFBFBD><DEB9><EFBFBD><EFBFBD><EFBFBD><><C6B5>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD> */
float initval; /**< ȱʡֵ */
float minimum; /**< ȡֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
float maximum; /**< ȡֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
float step; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
byte_t type; /**< 电压/电流/有功功率/无功功率/频率/功率因素/其它 */
float initval; /**< 缺省值 */
float minimum; /**< 取值下限 */
float maximum; /**< 取值上限 */
float step; /**< 步长 */
byte_t integral; /**< precision ( n , m ) - n */
byte_t decimal; /**< precision ( n , m ) - m */
float offset; /**< ʵ<EFBFBD><EFBFBD>ֵת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
float factor; /**< ʵ<EFBFBD><EFBFBD>ֵת<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
float threshold; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ */
float smooth; /**< ƽ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
float lower; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ */
float higher; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ */
float lowest; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸澯ֵ */
float highest; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸澯ֵ */
float blur; /**< <EFBFBD><EFBFBD>ֵģ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
char dimension[SHORTNAME]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ASCII<EFBFBD><EFBFBD>ʽ(A/V/kV/kvar/kW/MW etc.) */
void *ext[PRV_ANA_EXTENSION]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ */
float offset; /**< 实际值转换基数 */
float factor; /**< 实际值转换系数 */
float threshold; /**< 门限值 */
float smooth; /**< 平滑系数 */
float lower; /**< 告警下限值 */
float higher; /**< 告警上限值 */
float lowest; /**< 下下限告警值 */
float highest; /**< 上上限告警值 */
float blur; /**< 阀值模糊系数 */
char dimension[SHORTNAME]; /**< 量纲ASCII格式(A/V/kV/kvar/kW/MW etc.) */
void *ext[PRV_ANA_EXTENSION]; /**< 保护管理机扩展 */
}ALIGNPACKED;
@@ -66,27 +66,27 @@ struct ana_extention_t{
};
typedef struct digit_t digit_t;
#define DGT_TYP_UNDEF 0x00 /**< δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define DGT_TYP_SAMPLING 0x01 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define DGT_TYP_EVENT 0x02 /**< <EFBFBD>¼<EFBFBD> */
#define DGT_TYP_ALARM 0x03 /**< <EFBFBD> */
#define DGT_TYP_OPERATE 0x04 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define DGT_TYP_SYSTEM 0x05 /**< ϵͳ */
/** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define DGT_TYP_UNDEF 0x00 /**< 未定义 */
#define DGT_TYP_SAMPLING 0x01 /**< 采样 */
#define DGT_TYP_EVENT 0x02 /**< 事件 */
#define DGT_TYP_ALARM 0x03 /**< 告警 */
#define DGT_TYP_OPERATE 0x04 /**< 操作 */
#define DGT_TYP_SYSTEM 0x05 /**< 系统 */
/** 数字量私有属性 */
struct digit_t {
byte_t type; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F>¼<EFBFBD>/<2F>澯/<2F><><EFBFBD><EFBFBD>/ϵͳ */
byte_t type; /**< 采样/事件/告警/操作/系统 */
byte_t initval; /**< default zero value(0 or 1) */
byte_t level; /**< level */
byte_t snd_timer; /**< sound play timer (s) */
byte_t rst_timer; /**< auto restore timer (s) */
uint16_t act_lim; /**< (0 ==> 1)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t rst_lim; /**< (1 ==> 0)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t act_num; /**< (0 ==> 1)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>) */
uint16_t rst_num; /**< (1 ==> 0)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>) */
//<EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD>
//char on[SHORTNAME]; /**< 0==>1<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(ASCII<EFBFBD><EFBFBD>ʽ) */
//char off[SHORTNAME]; /**< 1==>0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(ASCII<EFBFBD><EFBFBD>ʽ) */
void *ext[PRV_DIGIT_EXTENSION]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ */
uint16_t act_lim; /**< (0 ==> 1)动作告警上限 */
uint16_t rst_lim; /**< (1 ==> 0)动作告警上限 */
uint16_t act_num; /**< (0 ==> 1)动作上限(不需界面录入) */
uint16_t rst_num; /**< (1 ==> 0)动作上限(不需界面录入) */
//第二版去掉
//char on[SHORTNAME]; /**< 0==>1动作名称(ASCII格式) */
//char off[SHORTNAME]; /**< 1==>0动作名称(ASCII格式) */
void *ext[PRV_DIGIT_EXTENSION]; /**< 保护管理机扩展 */
}ALIGNPACKED;
@@ -102,12 +102,12 @@ struct digit_t {
typedef struct state_describe_extention_t state_describe_extention_t;
struct state_describe_extention_t{
char *state_describe[4]; /**< ״̬0<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>3<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
char *state_describe[4]; /**< 状态0123的描述 */
};
typedef struct sound_file_name_extention_t sound_file_name_extention_t;
struct sound_file_name_extention_t{
char *sound_file_name[3]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
char *sound_file_name[3]; /**< 开报警声、合报警声、事故报警声 */
};
typedef struct epfi_addt_extension_t epfi_addt_extension_t;
@@ -120,48 +120,48 @@ struct epfi_addt_extension_t {
typedef struct pulse_t pulse_t;
/** Integrated totals private attr */
#define PLS_TYP_UNDEF 0x00 /**< δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define PLS_TYP_PLUS_POWER_HV 0x01 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD> */
#define PLS_TYP_PLUS_POWER_NO 0x02 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޹<EFBFBD> */
#define PLS_TYP_NEGATIVE_POWER_HV 0x03 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD> */
#define PLS_TYP_NEGATIVE_POWER_NO 0x04 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޹<EFBFBD> */
#define PLS_TYP_UNDEF 0x00 /**< 未定义 */
#define PLS_TYP_PLUS_POWER_HV 0x01 /**< 正向有功 */
#define PLS_TYP_PLUS_POWER_NO 0x02 /**< 正向无功 */
#define PLS_TYP_NEGATIVE_POWER_HV 0x03 /**< 反向有功 */
#define PLS_TYP_NEGATIVE_POWER_NO 0x04 /**< 反向无功 */
struct pulse_t {
byte_t type; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>޹<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>޹<EFBFBD> */
uint32_t save_flag; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
byte_t type; /**< 正向有功/正向无功/反向有功/反向无功 */
uint32_t save_flag; /**< 存储标记 */
uint32_t initval; /**< default value */
uint32_t minimum; /**< minimum value */
uint32_t maximum; /**< maximum value */
uint32_t step; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
//changed by zhancg 2017-04-05 <EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
// uint32_t offset; /**< ʵ<EFBFBD><EFBFBD>ֵת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
// uint32_t factor; /**< ʵ<EFBFBD><EFBFBD>ֵת<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
// uint32_t threshold; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ */
// uint32_t smooth; /**< ƽ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
float offset; /**< ʵ<EFBFBD><EFBFBD>ֵת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
float factor; /**< ʵ<EFBFBD><EFBFBD>ֵת<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
float threshold; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ */
float smooth; /**< ƽ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD> */
char dimension[SHORTNAME]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ASCII<EFBFBD><EFBFBD>ʽ(kvar/kW/MW etc.) */
uint32_t step; /**< 步长 */
//changed by zhancg 2017-04-05 配系数
// uint32_t offset; /**< 实际值转换基数 */
// uint32_t factor; /**< 实际值转换系数 */
// uint32_t threshold; /**< 门限值 */
// uint32_t smooth; /**< 平滑系数 */
float offset; /**< 实际值转换基数 */
float factor; /**< 实际值转换系数 */
float threshold; /**< 门限值 */
float smooth; /**< 平滑系数 */
char dimension[SHORTNAME]; /**< 量纲ASCII格式(kvar/kW/MW etc.) */
void *ext[PRV_PULSE_EXTENSION];
}ALIGNPACKED;
typedef struct pluse_stage_limits_extention_t pluse_stage_limits_extention_t;
struct pluse_stage_limits_extention_t{
uint32_t limits[3]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ,<2C>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>ֵ,<2C>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD>ֵ */
uint32_t limits[3]; /**< 峰电度限值,日电度限值,月电度限值 */
};
typedef struct pluse_stage_const_extention_t pluse_stage_const_extention_t;
struct pluse_stage_const_extention_t{
char* stage[8]; /**< <EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>1,<2C><>ʱ<EFBFBD><CAB1>2,<2C><>ʱ<EFBFBD><CAB1>3,<2C><>ʱ<EFBFBD><CAB1>4,<2C><>ʱ<EFBFBD><CAB1>1,<2C><>ʱ<EFBFBD><CAB1>2,<2C><>ʱ<EFBFBD><CAB1>3,<2C><>ʱ<EFBFBD><CAB1>4 */
char* stage[8]; /**< 峰时段1,峰时段2,峰时段3,峰时段4,谷时段1,谷时段2,谷时段3,谷时段4 */
};
//
typedef struct command_t command_t;
/** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD> */
/** 命令消息结构 */
struct command_t {
ticks_t ticks; /**< Ticks when command generated */
apr_time_t tmlimit; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> */
byte_t state; /**< ACTIVE<EFBFBD><EFBFBD>FINISH or TIMEOUT */
apr_time_t tmlimit; /**< 命令执行完成的限制时间 */
byte_t state; /**< ACTIVEFINISH or TIMEOUT */
byte_t channel; /**< command channel no */
byte_t flag; /**< General<EFBFBD><EFBFBD>System or Special */
byte_t flag; /**< GeneralSystem or Special */
byte_t typ; /**< Command TYPE(IEC60870-5-101) */
uint32_t ied; /**< Controlled IED id */
uint32_t group; /**< Controlled group id */
@@ -173,65 +173,65 @@ struct command_t {
/** status_t code definiens */
#define STATUS_NORMAL 0 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define STATUS_NOINIT 1 /**< δ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD> */
#define STATUS_OVERTIME 2 /**< ͨ<EFBFBD>ų<EFBFBD>ʱ */
#define STATUS_BREAKOFF 3 /**< ͨ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> */
#define STATUS_BLOCKED 4 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define STATUS_TESTING 5 /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define STATUS_NOTDEF 6 /**< δ<EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) */
#define STATUS_NORMAL 0 /**< 正常 */
#define STATUS_NOINIT 1 /**< 未初始化 */
#define STATUS_OVERTIME 2 /**< 通信超时 */
#define STATUS_BREAKOFF 3 /**< 通信中断 */
#define STATUS_BLOCKED 4 /**< 封锁 */
#define STATUS_TESTING 5 /**< 测试 */
#define STATUS_NOTDEF 6 /**< 未配置(本运行状态没有配置) */
typedef uint16_t status_t; /**< <EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Žڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ */
typedef uint16_t status_t; /**< 设备或通信节点的运行状态 */
typedef struct alias_t alias_t;
/** <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صı<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
struct alias_t { /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صı<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t id; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>ַ */
uint32_t parent; /**< <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IED */
uint32_t group; /**< <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IED<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t dot; /**< <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IED<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
value_t* value; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/** 数据元素的别名结构 */
struct alias_t { /**< 数据元素的别名结构 */
uint32_t id; /**< 别名信息地址 */
uint32_t parent; /**< 所指代的IED */
uint32_t group; /**< 所指代的IED内的组号 */
uint32_t dot; /**< 所指代的IED内的序号 */
value_t* value; /**< 运行时刻实时数据 */
};
typedef struct ied_t ied_t;
typedef struct group_t group_t;
typedef struct element_t element_t;
/** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϢԪ<EFBFBD>صĽṹ */
/** 数据信息元素的结构 */
struct element_t {
uint32_t id; /**< Identification, Information Address */
uint32_t flags; /**< flags define */
byte_t type; /**< IEC60870-5-101 TYP.(IEC60870DEF.h) */
byte_t code; /**< Data code type.(BIN/ASCII/BCD/etc.) */
uint32_t parent; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t group; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t dot; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t size; /**< <EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD>ֽ<EFBFBD>Ϊ<EFBFBD><CEAA>λ) */
char name[LONGNAME]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t parent; /**< 隶属设备 */
uint32_t group; /**< 数据组号 */
uint32_t dot; /**< 数据序号 */
uint16_t size; /**< 数据宽度(以字节为单位) */
char name[LONGNAME]; /**< 数据名称 */
char *aliasname; /**< <EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>Ӧ<EFBFBD><EFBFBD>Ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ++EPFI++ */
char *aliasname; /**< 数据点别名,如用于中文名称对应的英文名称 ++EPFI++ */
void *owner; /**< ˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խṹ(analog_t/digit_t/..../etc.) */
void *script; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ */
void *owner; /**< 私有属性结构(analog_t/digit_t/..../etc.) */
void *script; /**< 关联的计算表达式 */
/** Runtime generate */
value_t value; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ʵʱ<EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
ticks_t last; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仯ʱ<EFBFBD><EFBFBD> */
uint32_t state; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ */
byte_t funtype; /**< <EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ݹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t index; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t n_alias_add_1; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD> */
uint16_t n_alias; /**< <EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> */
alias_t* alias; /**< <EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t alias_pos; /**< <EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰλ<EFBFBD><EFBFBD> */
uint32_t offset; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ƫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
group_t *grp; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
ied_t *ied; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
value_t value; /**< 运行时刻实时数据缓冲区 */
ticks_t last; /**< 最后变化时间 */
uint32_t state; /**< 数据状态 */
byte_t funtype; /**< 继承自所属组的类型,表示数据功能类型 */
uint16_t index; /**< 数据元素索引 */
uint16_t n_alias_add_1; /**< 分配的数据别名缓冲区的大小预留1动态定订购用 */
uint16_t n_alias; /**< 数据别名数组元素个数 */
alias_t* alias; /**< 数据别名索引数组 */
uint16_t alias_pos; /**< 数据别名当前位置 */
uint32_t offset; /**< 数据在设备数据缓冲区内的偏移索引 */
group_t *grp; /**< 所属数据组句柄 */
ied_t *ied; /**< 所属设备句柄 */
/* Extend property */
void *sys_ext; /**< <EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C>ɻ<EFBFBD><C9BB><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5> */
void *app_ext; /**< <EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>Ӧ<EFBFBD>ÿ<EFBFBD>ʵ<EFBFBD><CAB5> */
void *usr_ext; /**< <EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD>ʵ<EFBFBD><CAB5> */
void *sys_ext; /**< 数据点的系统扩展属性,由基本库实现 */
void *app_ext; /**< 数据点的应用扩展属性,由应用库实现 */
void *usr_ext; /**< 数据点的用户扩展属性,由应用程序实现 */
};
/** group_t->type definiens */
@@ -245,36 +245,36 @@ struct element_t {
#define GRP_ALARM 7 /**< Alarm type */
#define GRP_SETTING 8 /**< Fixed value type */
#define GRP_STATUS 9 /**< State of device */
#define GRP_VDI 10 /**< <EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD> type */
#define GRP_VDI 10 /**< 软压板 type */
#define GRP_STEPPOS 11 /**< Step position type */
#define GRP_COMBO 12 /**< combo/compute type */
#define GRP_SIMANA 13 /**< ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define GRP_SETAREA 14 /**< <EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD> */
#define GRP_ACCANA 15 /**< ¼<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define GRP_ACCDGT 16 /**< ¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define GRP_SIMANA 13 /**< 模拟量 */
#define GRP_SETAREA 14 /**< 定值区 */
#define GRP_ACCANA 15 /**< 录波模拟量 */
#define GRP_ACCDGT 16 /**< 录波开关量 */
#define GRP_SETPOINT 18 /**< Set point type for 101,104 protocol used only */
#define GRP_STEPCONTROL 19 /**< <EFBFBD><EFBFBD>λ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define GRP_STEPCONTROL 19 /**< 步位置调节组 */
/** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/** 数据组结构 */
struct group_t {
uint32_t id; /**< Identification, Commond Address of Set */
uint32_t flags; /**< Flags definiens */
byte_t type; /**< Analogue/Digit/Control/Event/etc. */
char name[LONGNAME]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint16_t maxelems; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>elements<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ */
element_t *elements; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
char name[LONGNAME]; /**< 数据组的名称 */
uint16_t maxelems; /**< 允许包含elements的最大数目 */
element_t *elements; /**< 数据元素定义数组 */
// runtime generate
uint16_t count; /**< ʵ<EFBFBD>ʰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ */
uint16_t index; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IED->groups<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD> */
value_t value; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>elements<EFBFBD><EFBFBD>ʵʱֵ */
ied_t *ied; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
apr_hash_t *htdots; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD> */
uint16_t count; /**< 实际包含的数据元素数目 */
uint16_t index; /**< 数据组索引IED->groups的数组下标 */
value_t value; /**< 数据组缓冲区,顺序存放elements的实时值 */
ied_t *ied; /**< 所属设备句柄 */
apr_hash_t *htdots; /**< 数据元素定义哈希表 */
/* Extend property */
void *sys_ext; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C>ɻ<EFBFBD><C9BB><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5> */
void *app_ext; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>Ӧ<EFBFBD>ÿ<EFBFBD>ʵ<EFBFBD><CAB5> */
void *usr_ext; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD>ʵ<EFBFBD><CAB5> */
void *sys_ext; /**< 数据组的系统扩展属性,由基本库实现 */
void *app_ext; /**< 数据组的应用扩展属性,由应用库实现 */
void *usr_ext; /**< 数据组的用户扩展属性,由应用程序实现 */
};
//<!-- IEDConfig id,name,flags,type,chncount,cpucount,addrsinfo,cpusinfo,station,frequency,delay,count
@@ -284,83 +284,83 @@ struct group_t {
#define IED_TYPE_REMOTE (1)
#define IED_TYPE_SYSTEM (2)
#define IED_TYPE_VIRTUAL (3)
#define IED_TYPE_EPFI (4) /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define IED_TYPE_EPFI (4) /**< 保护管理机 */
#define IED_FLAG_BLOCKED 0x00000004 /**< <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱʡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define IED_FLAG_BLOCKED 0x00000004 /**< 是否封锁,缺省不封锁 */
#define CHANBEL_TYPE_UNKNOWN (0)
#define CHANNEL_TYPE_IPV4 (1)
#define CHANNEL_TYPE_IPV6 (2) /**< δ<EFBFBD><EFBFBD> */
#define CHANNEL_TYPE_SERIAL (3) /**< <EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD> */
#define CHANNEL_TYPE_IPV6 (2) /**< 未用 */
#define CHANNEL_TYPE_SERIAL (3) /**< 串口号 */
#define CHANNEL_TYPE_USER_DEFINED (254) /**< <EFBFBD>û<EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define CHANNEL_TYPE_USER_DEFINED (254) /**< 用户自定义类型 */
typedef struct channel_t channel_t;
struct channel_t {
uint32_t master; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>(Node ID) */
uint32_t master; /**< 所属通信通道(Node ID) */
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ2008-08-16<EFBFBD><EFBFBD><EFBFBD><EFBFBD><><D6A7>
int channel_type; /**< ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
char addr_str[LONGNAME]; /**< ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ */
//以下两个属性域为2008-08-16增加,支持
int channel_type; /**< 通道地址类型 */
char addr_str[LONGNAME]; /**< 通道地址的字符串表示 */
uint32_t addr; /**< ͨ<EFBFBD>Ŷ˿ڵ<EFBFBD>ַ */
uint16_t port; /**< ip<EFBFBD><EFBFBD>ַ<EFBFBD>Ķ˿<EFBFBD> */
uint32_t addr; /**< 通信端口地址 */
uint16_t port; /**< ip地址的端口 */
uint32_t status; /**< ͨ<EFBFBD>Ŷ˿<EFBFBD>״̬ */
ticks_t last_ticks; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> */
ticks_t last_send_ticks; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯʱ<EFBFBD><EFBFBD> */
void *connect; /**< ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӿ<EFBFBD><EFBFBD><EFBFBD> */
ied_t *ied; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
int ied_id; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>id */
uint32_t status; /**< 通信端口状态 */
ticks_t last_ticks; /**< 最近访问时间 */
ticks_t last_send_ticks; /**< 最近查询时间 */
void *connect; /**< 通道连接句柄 */
ied_t *ied; /**< 所属设备句柄 */
int ied_id; /**< 所属设备id */
};
typedef struct cpuinfo_t cpuinfo_t;
struct cpuinfo_t {
byte_t addr; /**< CPU<EFBFBD><EFBFBD>ַ */
byte_t status; /**< CPU״̬ */
byte_t templ; /**< CPUģ<EFBFBD><EFBFBD> */
char name[LONGNAME]; /**< CPU<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
ticks_t last_gi; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD>ѯʱ<EFBFBD><EFBFBD> */
ticks_t last_gi_send; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> */
ticks_t next_gi_send; /**< <EFBFBD>´<EFBFBD><EFBFBD>ܲ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> */
ticks_t last_ticks; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> */
ticks_t last_send_ticks; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯʱ<EFBFBD><EFBFBD> */
byte_t addr; /**< CPU地址 */
byte_t status; /**< CPU状态 */
byte_t templ; /**< CPU模板 */
char name[LONGNAME]; /**< CPU名称 */
ticks_t last_gi; /**< 最近总查询时间 */
ticks_t last_gi_send; /**< 最近总查询发送时间 */
ticks_t next_gi_send; /**< 下次总查询发送时间 */
ticks_t last_ticks; /**< 最近访问时间 */
ticks_t last_send_ticks; /**< 最近查询时间 */
};
/** IED struct definiens */
struct ied_t {
uint32_t id; /**< Primy key ( = 0 ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IED ) */
uint32_t id; /**< Primy key ( = 0 系统保留IED ) */
uint32_t flags; /**< Flags define */
byte_t type; /**< Type define */
byte_t chncount; /**< <EFBFBD>豸ͨ<EFBFBD>Ŷ˿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱʡ=1<><31> */
channel_t *channel; /**< <EFBFBD>豸ͨ<EFBFBD>Ŷ˿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
byte_t cpucount; /**< CPU<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱʡ=1<><31> */
cpuinfo_t *cpuinfo; /**< CPU<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
char name[LONGNAME]; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t station; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>վ<EFBFBD><EFBFBD><><D6B1>Ŀ¼ID> */
uint32_t node; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Žڵ<EFBFBD><EFBFBD><EFBFBD> */
uint16_t frequency; /**< ͨ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD> */
uint32_t delay; /**< ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ʱ(ms) */
uint16_t count; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ */
group_t *groups; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
apr_hash_t *htgroups; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
uint32_t systoken_st; /**< ϵͳ<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>״̬ */
byte_t chncount; /**< 设备通信端口总数(缺省=1 */
channel_t *channel; /**< 设备通信端口数组 */
byte_t cpucount; /**< CPU总数(缺省=1 */
cpuinfo_t *cpuinfo; /**< CPU地址数组 */
char name[LONGNAME]; /**< 设备名称 */
uint32_t station; /**< 所属站号<直属目录ID> */
uint32_t node; /**< 所属通信节点号 */
uint16_t frequency; /**< 通信扫描频率 */
uint32_t delay; /**< 通信响应延时(ms) */
uint16_t count; /**< 包含的数据组数目 */
group_t *groups; /**< 数据组定义数组 */
apr_hash_t *htgroups; /**< 数据组定义哈希表句柄 */
uint32_t systoken_st; /**< 系统令牌的状态 */
/* Runtime generate */
uint16_t index; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD> */
status_t status; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ */
ticks_t last_ticks; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> */
ticks_t last_gi; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD>ѯʱ<EFBFBD><EFBFBD> */
uint16_t index; /**< 设备数组下标 */
status_t status; /**< 设备运行状态 */
ticks_t last_ticks; /**< 最近访问时间 */
ticks_t last_gi; /**< 最近总查询时间 */
/* Extend property */
void *sys_ext; /**< <EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E2B6A8> */
void *app_ext; /**< <EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><>ÿⶨ<C3BF><E2B6A8> */
void *usr_ext; /**< <EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
void *sys_ext; /**< 设备的系统扩展属性,基本库定义 */
void *app_ext; /**< 设备的应用扩展属性,应用库定义 */
void *usr_ext; /**< 设备的用户扩展属性,应用程序定义 */
};
#ifdef _OS_WIN32_

View File

@@ -224,8 +224,19 @@ extern "C" {
#include <sys/time.h>
#include <sys/resource.h>
#endif
/*
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
*/
#ifndef __cplusplus
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>

View File

@@ -1,21 +1,34 @@
#ifdef __cplusplus
#include "../json/mms_json_inter.h"
#include "../rocketmq/CProducer.h"
#include "../rocketmq/CMessage.h"
#include "../rocketmq/CSendResult.h"
#include "../rocketmq/CPushConsumer.h"
//#include "../rocketmq/CProducer.h"
//#include "../rocketmq/CMessage.h"
//#include "../rocketmq/CSendResult.h"
//#include "../rocketmq/CPushConsumer.h"
#include "../rocketmq/DefaultMQProducer.h"
#include "../rocketmq/MQMessage.h"
#include "../rocketmq/SendResult.h"
#include "../rocketmq/SessionCredentials.h"
#include "../rocketmq/MQMessageExt.h"
#include "../rocketmq/ConsumeType.h"
#include "../rocketmq/MQMessageListener.h"
#include <vector>
#include <iostream>
#include <string>
using namespace rocketmq;
/*添加测试函数lnk10-10*/
void producer_send0();
void StartSendMessage(CProducer* producer,const char* strbody);
void producer_send(const char* strbody);
void rocketmq_producer_send(const char* strbody,const char* topic);
void rocketmq_StartSendMessage(CProducer* producer,const char* strbody,const char* topic);
//void producer_send0();
//void StartSendMessage(CProducer* producer,const char* strbody);
//void producer_send(const char* strbody);
//void rocketmq_producer_send(const char* strbody,const char* topic);
//void rocketmq_StartSendMessage(CProducer* producer,const char* strbody,const char* topic);
void rocketmq_producer_send(const std::string& body,
const std::string& topic,
const std::string& tags,
const std::string& keys);
extern "C" {
void rocketmq_test_rt();
void rocketmq_test_ud();
@@ -32,24 +45,29 @@ extern void my_rocketmq_send(Ckafka_data_t& data);
void InitializeProducer();
void ShutdownAndDestroyProducer();
//////////////////////////////////////////////////////消费者
void InitializeConsumer(const std::string& consumerName, const std::string& nameServer, const char* topic, const char* tag, const std::string& key);
void ShutdownAndDestroyConsumer();
typedef ConsumeStatus (*MessageCallBack)(
const MQMessageExt& msg
);
struct Subscription {
std::string topic;
std::string tag;
MessageCallBack callback;
Subscription(const std::string& t, const std::string& tg, MessageCallBack cb)
Subscription(const std::string& t,
const std::string& tg,
MessageCallBack cb)
: topic(t), tag(tg), callback(cb) {}
};
//void InitializeConsumer(const std::string& consumerName, const std::string& nameServer, const char* topic, const char* tag, const std::string& key);
void InitializeConsumer(const std::string& consumerName,
const std::string& nameServer,
const std::vector<Subscription>& subscriptions);
void ShutdownAndDestroyConsumer();
void rocketmq_consumer_receive(
const std::string& consumerName,
const std::string& nameServer,
//const std::string& topic,
//const std::string& tag,
//MessageCallBack callback);
const std::vector<Subscription>& subscriptions);
//////////////////////////////////////////////////////

View File

@@ -49,7 +49,7 @@
#ifndef HIBYTE
#define HIBYTE(w) ((byte_t)((uint16_t)(w) >> 8))
#endif
/*
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
@@ -57,7 +57,18 @@
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
*/
#ifndef __cplusplus
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -25,6 +25,18 @@
#include "../json/cjson.h"
#include "../log4cplus/log4.h"//lnk添加log4
///////////////////////////////////////////////////////////////////////lnk20260305数据追踪相关
#include <QHash>
#include <QMutex>
#include <QMutexLocker>
#include <QMapIterator>
#include <QStringList>
// ★MOD: 全局追踪表mp_id -> remaining times
static QMutex g_trace_mutex;
static QHash<QString, int> g_trace_map;
///////////////////////////////////////////////////lnk2024-10-21////////////////////////////////////////////////////////
extern void SendJsonAPI_web(const std::string& strUrl, const char* code, const std::string& json, char** ptr);
extern std::string WEB_INTEGRITY;
@@ -33,6 +45,8 @@ extern std::string WEB_EVENT;
extern std::string WEB_FILEDOWNLOAD;
extern std::string G_CONNECT_TOPIC;
extern int RECALL_ONLY_FLAG;
//lnk20250115添加台账锁
extern pthread_mutex_t mtx;
@@ -230,7 +244,106 @@ extern int isdelta_flag;//lnk2024-8-16 角型接线标志
void connectlog_pgsql(char* id,char* datetime,int status);
///////////////////////////////////////////////lnk20241021替换web接口//////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////lnk20260305数据追踪
static QString escape_json_string(const QString& s)
{
QString out = s;
out.replace("\\", "\\\\");
out.replace("\"", "\\\"");
out.replace("\r", "\\r");
out.replace("\n", "\\n");
out.replace("\t", "\\t");
return out;
}
// 打开追踪:次数 times比如 5
void process_trace_command(const std::string& id, int times)
{
if (times <= 0) return;
QString qid = QString::fromStdString(id).trimmed();
if (qid.isEmpty()) return;
QMutexLocker lk(&g_trace_mutex);
g_trace_map[qid] = times; // 重新打开就覆盖/重置次数
}
// 查询是否要追踪
static bool trace_is_enabled(const QString& mp_id)
{
QMutexLocker lk(&g_trace_mutex);
auto it = g_trace_map.constFind(mp_id);
return (it != g_trace_map.constEnd() && it.value() > 0);
}
// 命中一次并扣减;扣到 0 自动删
static void trace_hit_and_decrement(const QString& mp_id)
{
QMutexLocker lk(&g_trace_mutex);
auto it = g_trace_map.find(mp_id);
if (it == g_trace_map.end()) return;
int left = it.value();
left -= 1;
if (left <= 0) g_trace_map.erase(it);
else it.value() = left;
}
//追踪61850原始数据
static QString build_mms_multiline_text(const json_block_data* data)
{
QStringList lines;
QMapIterator<QString, double> it(data->mms_str_map);
while (it.hasNext()) {
it.next();
lines << QString("%1 = %2").arg(it.key()).arg(it.value(), 0, 'g', 15);
}
return lines.join("\n");
}
static QString build_trace_json(const json_block_data* data)
{
if (!data) return "{}";
QString mms_text = build_mms_multiline_text(data);
QString json;
json += "{";
json += QString("\"mp_id\":\"%1\",").arg(escape_json_string(data->mp_id));
json += QString("\"func_type\":%1,").arg(data->func_type);
json += QString("\"data_time\":%1,").arg(QString::number((qlonglong)data->time));
json += QString("\"voltage_level\":\"%1\",").arg(QString::number(data->voltage_level, 'f', 6));
json += QString("\"dev_type\":\"%1\",").arg(escape_json_string(data->dev_type));
json += QString("\"mms_text\":\"%1\"").arg(escape_json_string(mms_text));
json += "}";
return json;
}
static void send_trace_if_needed(json_block_data* pdata)
{
const QString mp_id_q = pdata->mp_id;
if (trace_is_enabled(mp_id_q)) {
// 1) 组 json
QString jsonText = build_trace_json(pdata);
// 2) 组 KafkaData
Ckafka_data_t KafkaData;
KafkaData.monitor_id = pdata->monitorId;
KafkaData.mp_id = pdata->mp_id;
KafkaData.strTopic = "DATA_TRACE_TOPIC";
KafkaData.strText = jsonText;
kafka_data_list_mutex.lock();
kafka_data_list.append(KafkaData);
kafka_data_list_mutex.unlock();
// 3) 次数 -1
trace_hit_and_decrement(mp_id_q);
}
}
////////////////////////////////////////////////////////////////////////////////////////////lnk20250710添加频率值存储
struct mp_freq_save {
double G_FREQ;
@@ -2680,13 +2793,6 @@ static void format_time_ms(long long ms, char* buf, size_t buf_len)
void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long time,char* devtype,int monitor_id)
{
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", mp_id);
//监测点日志的key,lnk20250526
XmlConfig c_xmlcfg;
if (xmlinfo_list.contains(devtype)) {
c_xmlcfg = xmlinfo_list[devtype]->xmlcfg;
@@ -2736,7 +2842,7 @@ void processGGIO_start_data_end(char* mp_id,char* fullname,double v,long long ti
snprintf(mp_name, sizeof(mp_name), "unknown");
}
DIY_WARNLOG_CODE(full_key_m_d, LOG_CODE_REPORT,
DIY_WARNLOG_CODE(mp_id,2 ,LOG_CODE_GGIO_LPHD,
"监测点:%s(%s),在%s发生事件:%s,事件值:%.2f",
mp_name, mp_id, time_str, descBa.constData(), v);
@@ -2820,6 +2926,7 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
{
Xmldata* config2 = new Xmldata();
xmlinfo_list2.insert(type, config2);
xmlinfo_list2[type]->updataflag = true;
}
else
{
@@ -2841,35 +2948,30 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
char file_name[256];
memset(file_name, 0, 256);
sprintf(file_name, "%s", FILE_NAME);
snprintf(file_name, sizeof(file_name), "%s", FILE_NAME);
file_name[sizeof(file_name) - 1] = '\0';
QString Qsavename;
Qsavename.append("/FeProject/dat/").append(id).append(".xml"); //本地保存路径
char save_name[256];
memset(save_name, 0, 256);
sprintf(save_name, "%s", Qsavename.toAscii().data());
snprintf(save_name, sizeof(save_name), "%s", Qsavename.toAscii().data());
save_name[sizeof(save_name) - 1] = '\0';
cout << file_name << "!!!!!!!!!!!!!!!!!!!!!!!!!!" << save_name << endl;
//mq日志
DIY_WARNLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name);
DIY_WARNLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【WARN】前置获取到终端类型%s,该终端类型对应的映射文件为%s,映射文件将下载并保存在本地为%s",TMNL_TYPE,FILE_PATH,save_name);
//20241028 lnk 替换为文件下载web接口
//构造文件下载接口参数
//接口示例http://192.168.1.125:10215/file/download?filePath=/path/xxx.txt
// 调用web获取文件内容
char* fileContent = NULL;
//测试下载
//char downpath[128] = {"/home/pq/FeProject/src/pt61850netd_pqfe_lnk/download/123.txt"};
//char download[128] = {"{\"filename\":\"file_test.txt\"}"};
//SendJsonAPI_web("http://192.168.1.149:8091/file/download", "", download, &fileContent);
std::string fullPath = std::string("filePath=") + std::string(FILE_PATH);
//调试用
std::cout << "fullpath" << fullPath << std::endl;
SendJsonAPI_web(WEB_FILEDOWNLOAD, fullPath.c_str(), "", &fileContent);
if (fileContent != NULL) {
if (fileContent != NULL && fileContent[0] != '\0') {
// 创建并打开文件
//判断返回的是不是错误json响应
@@ -2883,7 +2985,7 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
(dataItem == NULL || (dataItem->type == cJSON_NULL))) {
isErrorJson = true;
std::cerr << "Error: Server returned empty file stream, code=A00555." << std::endl;
DIY_ERRORLOG_CODE("process", LOG_CODE_ICD_AND_DOWNLOAD,
DIY_ERRORLOG_CODE("process",0, LOG_CODE_ICD_AND_DOWNLOAD,
"【ERROR】前置下载文件失败服务端返回A00555(文件流为空),文件=%s",
save_name);
}
@@ -2900,17 +3002,17 @@ void Set_xml_databaseinfo(char* MODEL_ID, char* TMNL_TYPE, char* FILE_PATH, char
outFile.close();
std::cout << "File saved successfully!" << std::endl;
//mq日志
DIY_INFOLOG("process","【NORMAL】前置下载映射文件%s成功",save_name);
DIY_INFOLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【NORMAL】前置下载映射文件%s成功",save_name);
} else {
std::cerr << "Error: Unable to open file for writing." << std::endl;
DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置写入本地映射文件%s失败",save_name);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置写入本地映射文件%s失败",save_name);
}
// 释放分配的内存
free(fileContent);
} else {
std::cerr << "Error: Unable to download file." << std::endl;
DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置调用文件下载接口下载远端文件文件%s失败",FILE_PATH);
}
}
@@ -3171,14 +3273,13 @@ void connectlog_pgsql(char* id,char* datetime,int status)
return;
}
//使用mq
Ckafka_data_t connect_info;
connect_info.strTopic = QString::fromStdString(G_CONNECT_TOPIC);
connect_info.mp_id = QString::fromLocal8Bit(id);//这里填装置id后续作为key
connect_info.strText = QString::fromStdString(std::string(jsonString));
if(g_node_id == STAT_DATA_BASE_NODE_ID){//稳态才上传
if((g_node_id == STAT_DATA_BASE_NODE_ID && RECALL_ONLY_FLAG == 0) || (g_node_id == RECALL_HIS_DATA_BASE_NODE_ID && RECALL_ONLY_FLAG == 1)){//稳态或者补招才上传
kafka_data_list_mutex.lock(); //加锁
kafka_data_list.append(connect_info); //添加 kafka发送链表
kafka_data_list_mutex.unlock(); //解锁
@@ -3241,7 +3342,7 @@ static bool writeJsonToFile(const char* filePath, const char* jsonString)
{
FILE* fp = fopen(filePath, "w");
if (!fp) {
//DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】无法将暂态事件写入本地缓存");
//DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】无法将暂态事件写入本地缓存");
std::cerr << "Failed to write in file : " << filePath << std::endl;
return false;
}
@@ -3328,7 +3429,7 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
// 读取文件内容(即之前存的 JSON)
FILE* fp = fopen(fileList[i].fileName.c_str(), "r");
if (!fp) {
DIY_ERRORLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【ERROR】无法打开本地缓存的暂态事件");
DIY_ERRORLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【ERROR】无法打开本地缓存的暂态事件");
std::cerr << " fail to open exsist file " << fileList[i].fileName << std::endl;
continue;
}
@@ -3348,26 +3449,27 @@ static void scanAndResendOfflineFiles(const std::string &dirPath)
// 尝试发送
char* ptr = NULL; // 接收返回
SendJsonAPI_web(WEB_EVENT, "", jsonContent.c_str(), &ptr);
if (ptr != NULL) {
if (ptr != NULL && ptr[0] != '\0') {
cJSON* j_r = cJSON_Parse(ptr);
if (j_r == NULL) {
std::cout << "old file send fail" << std::endl;
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
handleCommentResponse(std::string(ptr));
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件失败");
DIY_WARNLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件失败");
}
else{
// 表示有响应,则可视为成功;根据项目需要可加更精细的判断
handleCommentResponse(std::string(ptr));
DIY_WARNLOG_CODE("process",LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件成功");
DIY_WARNLOG_CODE("process",0,LOG_CODE_TRANSIENT_COMM,"【WARN】前置重发暂态事件成功");
std::cout << "old file send success,remove it" << std::endl;
// 删除文件
remove(fileList[i].fileName.c_str());
free(j_r);
cJSON_Delete(j_r);
}
}
@@ -3396,13 +3498,6 @@ char* uuid_cfg,char* uuid_dat,
char* mp_id,char* Qvvr_rptname,char* devtype)
{
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", mp_id);
//监测点日志的key,lnk20250526
// 原本的逻辑,不做任何改动
// ---------------------------------------------------------------
XmlConfig c_xmlcfg;
@@ -3413,7 +3508,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
c_xmlcfg = xmlcfg;
}
if (strlen(mp_id) == 0) {
if (NULL == mp_id || strlen(mp_id) == 0 ) {
std::cout << "mp_id is null" << std::endl;
return 0;
}
@@ -3456,6 +3551,12 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
}
char* json_string = cJSON_Print(root);
if (json_string == NULL) {
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s暂态事件生成JSON字符串失败",mp_id);
std::cerr << "Failed to print JSON object." << std::endl;
cJSON_Delete(root);
return 0;
}
printf("%s\n", json_string); // 输出 JSON 字符串
// 发送到暂态接口
@@ -3464,14 +3565,14 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
// ================ 插入新功能 =========================
// ********** 新增功能开始 **********
if(ptr != NULL)
if(ptr != NULL && ptr[0] != '\0')
{
cJSON* j_r = cJSON_Parse(ptr);
// 如果发送失败(j_r == NULL),则把当前 json 存入指定目录(/FeProject/dat/qvvr/)
if (j_r == NULL) {
//mq日志
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件",mp_id);
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口响应异常,无法上送监测点%s的暂态事件",mp_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件
@@ -3493,13 +3594,13 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
// 把 json_string 写入文件
if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id);
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
}
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);
}
else{
free(j_r);
cJSON_Delete(j_r);
//后续处理
}
}
@@ -3512,16 +3613,17 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
// ********** 新增功能结束 **********
// 下面继续原逻辑,不动,处理本次发送
if (ptr != NULL) {
if (ptr != NULL && ptr[0] != '\0') {
std::cout << "current qvvr handle response" << std::endl;
handleCommentResponse(std::string(ptr));
free(ptr);
ptr = NULL;
} else {
// 处理 ptr 为 NULL 的情况,例如日志记录或错误处理
std::cout << "Error: Received NULL response" << std::endl;
//mq日志
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件",mp_id);
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】暂态接口无响应,无法上送监测点%s的暂态事件",mp_id);
std::cout << "qvvr send fail ,store in local" << std::endl;
// 1) 先检查/FeProject/dat/qvvr/目录文件大小是否超过 10M若超过则删除最老的一个文件
@@ -3541,7 +3643,7 @@ char* mp_id,char* Qvvr_rptname,char* devtype)
fileName += ".txt";
// 把 json_string 写入文件
if(!writeJsonToFile(fileName.c_str(), json_string)){
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",start_tm,mp_id);
DIY_ERRORLOG_CODE(mp_id,2,LOG_CODE_TRANSIENT_COMM,"【ERROR】监测点%s无法将暂态时间为%lld的暂态事件写入本地缓存",mp_id,start_tm);
}
checkAndRemoveOldestIfNeeded(qvvrDir, 10LL * 1024 * 1024);

View File

@@ -41,6 +41,8 @@ public:
bool data_have_statistic;//是否有统计数据0没有1有
QMap<QString, double> mms_str_map; //数据值(61850数据属性名, 数据值)
bool data_trace_flag; //数据追踪标记0不追踪1追踪
};
class Ckafka_data_t //kafka发送数据结构类

File diff suppressed because it is too large Load Diff

View File

@@ -670,6 +670,8 @@ struct monitor // 监测点台账
char timestamp[64];
char status[255];
int log_level;//日志级别0ERROR1WARN2NORMAL3DEBUG
};
struct terminal // 终端台账
{
@@ -692,6 +694,7 @@ struct terminal // 终端台账
char timestamp[64];
monitor line[10]; // 最多 10 个监测点
int log_level;//日志级别0ERROR1WARN2NORMAL3DEBUG
};
#ifdef __cplusplus

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,248 @@
/* include/log4cplus/config/defines.hxx. Generated from defines.hxx.in by configure. */
#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX
#define LOG4CPLUS_CONFIG_DEFINES_HXX
/* */
#define LOG4CPLUS_HAVE_SYSLOG_H 1
/* */
#define LOG4CPLUS_HAVE_ARPA_INET_H 1
/* */
#define LOG4CPLUS_HAVE_NETINET_IN_H 1
/* */
#define LOG4CPLUS_HAVE_NETINET_TCP_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_TIMEB_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_TIME_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_TYPES_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_STAT_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_SYSCALL_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_FILE_H 1
/* */
#define LOG4CPLUS_HAVE_TIME_H 1
/* */
#define LOG4CPLUS_HAVE_SYS_SOCKET_H 1
/* */
#define LOG4CPLUS_HAVE_NETDB_H 1
/* */
#define LOG4CPLUS_HAVE_UNISTD_H 1
/* */
#define LOG4CPLUS_HAVE_FCNTL_H 1
/* */
#define LOG4CPLUS_HAVE_STDARG_H 1
/* */
#define LOG4CPLUS_HAVE_STDIO_H 1
/* */
#define LOG4CPLUS_HAVE_STDLIB_H 1
/* */
#define LOG4CPLUS_HAVE_ERRNO_H 1
/* */
#define LOG4CPLUS_HAVE_WCHAR_H 1
/* */
/* #undef LOG4CPLUS_HAVE_ICONV_H */
/* */
#define LOG4CPLUS_HAVE_LIMITS_H 1
/* */
#define LOG4CPLUS_HAVE_FTIME 1
/* */
#define LOG4CPLUS_HAVE_GETADDRINFO 1
/* */
#define LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1
/* */
#define LOG4CPLUS_HAVE_GETPID 1
/* */
#define LOG4CPLUS_HAVE_GMTIME_R 1
/* */
#define LOG4CPLUS_HAVE_HTONL 1
/* */
#define LOG4CPLUS_HAVE_HTONS 1
/* */
#define LOG4CPLUS_HAVE_LOCALTIME_R 1
/* */
#define LOG4CPLUS_HAVE_LSTAT 1
/* */
#define LOG4CPLUS_HAVE_FCNTL 1
/* */
#define LOG4CPLUS_HAVE_LOCKF 1
/* */
#define LOG4CPLUS_HAVE_FLOCK 1
/* */
#define LOG4CPLUS_HAVE_NTOHL 1
/* */
#define LOG4CPLUS_HAVE_NTOHS 1
/* Define to 1 if you have the `shutdown' function. */
#define LOG4CPLUS_HAVE_SHUTDOWN 1
/* */
#define LOG4CPLUS_HAVE_PIPE 1
/* */
#define LOG4CPLUS_HAVE_PIPE2 1
/* */
#define LOG4CPLUS_HAVE_POLL 1
/* */
#define LOG4CPLUS_HAVE_POLL_H 1
/* */
#define LOG4CPLUS_HAVE_STAT 1
/* Define if this is a single-threaded library. */
/* #undef LOG4CPLUS_SINGLE_THREADED */
/* */
/* #undef LOG4CPLUS_USE_PTHREADS */
/* Define for compilers/standard libraries that support more than just the "C"
locale. */
/* #undef LOG4CPLUS_WORKING_LOCALE */
/* Define for C99 compilers/standard libraries that support more than just the
"C" locale. */
/* #undef LOG4CPLUS_WORKING_C_LOCALE */
/* Define to int if undefined. */
/* #undef socklen_t */
/* Defined for --enable-debugging builds. */
/* #undef LOG4CPLUS_DEBUGGING */
/* Defined if the compiler understands __declspec(dllexport) or
__attribute__((visibility("default"))) construct. */
#define LOG4CPLUS_DECLSPEC_EXPORT __attribute__ ((visibility("default")))
/* Defined if the compiler understands __declspec(dllimport) or
__attribute__((visibility("default"))) construct. */
#define LOG4CPLUS_DECLSPEC_IMPORT __attribute__ ((visibility("default")))
/* Defined if the compiler understands
__attribute__((visibility("hidden"))) construct. */
#define LOG4CPLUS_DECLSPEC_PRIVATE __attribute__ ((visibility("hidden")))
/* */
#define LOG4CPLUS_HAVE_TLS_SUPPORT 1
/* */
#define LOG4CPLUS_THREAD_LOCAL_VAR thread_local
/* Defined if the host OS provides ENAMETOOLONG errno value. */
#define LOG4CPLUS_HAVE_ENAMETOOLONG 1
/* */
#define LOG4CPLUS_HAVE_VSNPRINTF 1
/* Define to 1 if you have the `vsnwprintf' function. */
/* #undef LOG4CPLUS_HAVE_VSNWPRINTF */
/* Define to 1 if you have the `_vsnwprintf' function. */
/* #undef LOG4CPLUS_HAVE__VSNWPRINTF */
/* */
/* #undef LOG4CPLUS_HAVE__VSNPRINTF */
/* Define to 1 if you have the `vfprintf_s' function. */
/* #undef LOG4CPLUS_HAVE_VFPRINTF_S */
/* Define to 1 if you have the `vfwprintf_s' function. */
/* #undef LOG4CPLUS_HAVE_VFWPRINTF_S */
/* Define to 1 if you have the `vsprintf_s' function. */
/* #undef LOG4CPLUS_HAVE_VSPRINTF_S */
/* Define to 1 if you have the `vswprintf_s' function. */
/* #undef LOG4CPLUS_HAVE_VSWPRINTF_S */
/* Define to 1 if you have the `_vsnprintf_s' function. */
/* #undef LOG4CPLUS_HAVE__VSNPRINTF_S */
/* Define to 1 if you have the `_vsnwprintf_s' function. */
/* #undef LOG4CPLUS_HAVE__VSNWPRINTF_S */
/* Defined if the compiler supports __FUNCTION__ macro. */
#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1
/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */
#define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1
/* Defined if the compiler supports __func__ symbol. */
#define LOG4CPLUS_HAVE_FUNC_SYMBOL 1
/* Define to 1 if you have the `mbstowcs' function. */
#define LOG4CPLUS_HAVE_MBSTOWCS 1
/* Define to 1 if you have the `wcstombs' function. */
#define LOG4CPLUS_HAVE_WCSTOMBS 1
/* Define to 1 if you have Linux style syscall(SYS_gettid). */
#define LOG4CPLUS_HAVE_GETTID 1
/* Define when iconv() is available. */
/* #undef LOG4CPLUS_WITH_ICONV */
/* Define to 1 if you have the `iconv' function. */
/* #undef LOG4CPLUS_HAVE_ICONV */
/* Define to 1 if you have the `iconv_close' function. */
/* #undef LOG4CPLUS_HAVE_ICONV_CLOSE */
/* Define to 1 if you have the `iconv_open' function. */
/* #undef LOG4CPLUS_HAVE_ICONV_OPEN */
/* Define to 1 if you have the `OutputDebugString' function. */
/* #undef LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING */
/* Define to 1 if the system has the `constructor' function attribute
with priority */
#define LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR_PRIORITY 1
/* Define to 1 if the system has the `constructor' function attribute */
#define LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1
/* Define to 1 if the system has the `init_priority' variable attribute */
#define LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1
/* Defined to enable unit tests. */
/* #undef LOG4CPLUS_WITH_UNIT_TESTS */
#endif // LOG4CPLUS_CONFIG_DEFINES_HXX

View File

@@ -24,12 +24,9 @@
#include "appender.h"
#define LOGTYPE_COM 1
#define LOGTYPE_DATA 2
struct TypedLogger {
log4cplus::Logger logger;
int logtype;
int code;
TypedLogger();
TypedLogger(const log4cplus::Logger& l, int t);
};
@@ -47,7 +44,7 @@ struct DebugSwitch {
void set_level(int level);
void enable_type(int type);
void disable_type(int type);
bool match(const std::string& logger_name, int level, int logtype);
bool match(const std::string& logger_name, int level, int code);
};
extern std::map<std::string, TypedLogger> logger_map;
@@ -71,11 +68,14 @@ log4cplus::Logger init_logger(const std::string& full_name,
const std::string& base_file,
log4cplus::SharedAppenderPtr fileAppender);
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str);
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, int code);
void update_log_entries_countdown();
/////////////////////////////////////////////////////////////////////lnk20260306数据追踪
void process_trace_command(const std::string& id, int times);
extern "C" {
#endif
void remove_loggers_by_terminal_id(const char* terminal_id_cstr);
@@ -89,7 +89,7 @@ void log_warn(const char* key, const char* msg);
void log_error(const char* key, const char* msg);
void send_reply_to_kafka_c(const char* guid, const char* step, const char* result);
void send_reply_to_kafka_recall(const char* guid, const char* step, const char* result,const char* lineIndex,const char* recallStartDate,const char* recallEndDate);
void send_reply_to_kafka_recall_c(const char* guid, const char* step, const char* result,const char* lineIndex,const char* recallStartDate,const char* recallEndDate);
void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...);
// ====================== ★新增:线程局部变量透传 code ======================
@@ -107,43 +107,62 @@ extern LOG_TLS int g_log_code_tls; // 声明为 TLS 变量,定义见 log4.cpp
// ====================== 日志宏区域 ======================
// 原始不带 code 的实现(兼容/复用)
#define DIY_LOG(LEVEL_FUNC, KEY, ...) \
do { \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); \
} while (0)
// ★新增:带 code 的实现C/C++ 通用,使用 TLS 保存/恢复)
#define DIY_LOG_CODE(LEVEL_FUNC, KEY, CODE_INT, ...) \
do { \
int __old_code__ = g_log_code_tls; /* 备份旧值 */ \
g_log_code_tls = (int)(CODE_INT); /* 设置本次日志 code */ \
char buf[256]; \
format_log_msg(buf, sizeof(buf), __VA_ARGS__); \
LEVEL_FUNC(KEY, buf); /* 输出日志 */ \
g_log_code_tls = __old_code__; /* 恢复旧值 */ \
#define DIY_LOG_CODE(LEVEL_FUNC, KEY, KEY_TYPE, CODE_INT, ...) \
do { \
int __old_code__ = g_log_code_tls; \
g_log_code_tls = (int)(CODE_INT); \
\
char __msg_buf__[256]; \
format_log_msg(__msg_buf__, sizeof(__msg_buf__), __VA_ARGS__); \
\
const char* __key_raw__ = (KEY); \
\
char __key_buf__[256]; \
switch ((int)(KEY_TYPE)) { \
case 0: \
snprintf(__key_buf__, sizeof(__key_buf__), "process"); \
break; \
case 1: \
snprintf(__key_buf__, sizeof(__key_buf__), \
"terminal.%s", __key_raw__); \
break; \
case 2: \
snprintf(__key_buf__, sizeof(__key_buf__), \
"monitor.%s", __key_raw__); \
break; \
default: \
snprintf(__key_buf__, sizeof(__key_buf__), "%s", \
__key_raw__); \
break; \
} \
\
LEVEL_FUNC(__key_buf__, __msg_buf__); \
g_log_code_tls = __old_code__; \
} while (0)
// ★修改:默认宏改为 code=0兼容原有用法
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, __VA_ARGS__) // ★修改:默认 code=0
#define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
#define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0
// ★新增:显式传入 code 的便捷宏
// 用法示例DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...);
#define DIY_ERRORLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_ERRORLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_WARNLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_INFOLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
#define DIY_DEBUGLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增
// ====================== 日志宏区域 ======================
typedef enum LogCode {
LOG_CODE_MENU_CONTROL = 94, /* 目录控制类型 */
LOG_CODE_FILE_CONTROL = 95, /* 文件控制类型 */
LOG_CODE_WIRETYPE = 96, /* 接线类型 */
LOG_CODE_CONFIG = 97, /* 配置相关 */
LOG_CODE_JSON = 98, /* JSON结构 */
LOG_CODE_OTHER = 99, /* 其他类型 */
LOG_CODE_LEDGER = 100, /* 台账类型 */
LOG_CODE_RPTINIT = 101, /* 报告初始化 */
@@ -151,6 +170,7 @@ typedef enum LogCode {
LOG_CODE_TRANSIENT = 300, /* 暂态发生 */
LOG_CODE_TRANSIENT_COMM = 301, /* 暂态接口 */
LOG_CODE_COMTRADE_FILE = 302, /* 录波文件Comtrade */
LOG_CODE_GGIO_LPHD = 304, /* GGIO事件 */
LOG_CODE_MQ = 400, /* MQ发送 */
LOG_CODE_RT_DATA = 401, /* 实时数据 */
LOG_CODE_LEDGER_UPDATE = 402, /* 台账更新 */

View File

@@ -45,10 +45,10 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern char* OSS_ENDPOINT;
extern char* ACCESS_KEY_ID;
extern char* ACCESS_KEY_SECRET;
extern char* BUCKET_NAME;
//extern char* OSS_ENDPOINT;
//extern char* ACCESS_KEY_ID;
//extern char* ACCESS_KEY_SECRET;
//extern char* BUCKET_NAME;
extern char* POSTGRES_SCHEMA;
extern char* POSTGRES_TABLEPREFIX;
@@ -105,16 +105,16 @@ void TestToken();
void TestBodyPost();//WW 测试qt post
void TestSMSPost();//WW 测试qt post
void TestJson(char* szJson);
void TestOSS();//WW 测试
void PutOSS(char* File_Name, char* data); //zw修改 2023-9-7 上送oss文件
void GetOSS(char* File_Name, char* savepath); //zw修改 2023-9-7 获取oss文件
void DelOSS(char* File_Name);
//void TestOSS();//WW 测试
//void PutOSS(char* File_Name, char* data); //zw修改 2023-9-7 上送oss文件
//void GetOSS(char* File_Name, char* savepath); //zw修改 2023-9-7 获取oss文件
//void DelOSS(char* File_Name);
void delete_object_new(char* File_Name);
void coutTest();//CZY 2023-09-11 test
void TestOBS();//WW 20230921 测试华为云服务器
void OBSFile(char* localpath, char* cloudpath,const char* code);
void OBSFile_del(char* cloudpath, const char* code);
void DataHub_Send_Datahub(char* topic, char* data);//datahub通讯
//void TestOBS();//WW 20230921 测试华为云服务器
//void OBSFile(char* localpath, char* cloudpath,const char* code);
//void OBSFile_del(char* cloudpath, const char* code);
//void DataHub_Send_Datahub(char* topic, char* data);//datahub通讯
void Nacos_GetParam(char* postgres_uid, char* postgres_pwd, char* web_clientid, char* web_clientsecret);//nacos
void Nacos_GetParam_Ptr(const char* code, char** ptr);
void Read_Nacos_Param_Postgres(char** database_ip, char** database_port, char** postgres_database, char** postgres_username, char** postgres_password, char** postgres_schema, char** postgres_dnsname, char** postgres_tableprefix);
@@ -171,6 +171,21 @@ typedef struct {
bool get_xml_config_by_dev_type(const char* dev_type, XmlConfigC* out_cfg);
//////////////////////////////////////////////////////////////////////////////////////文件控制请求参数
typedef struct file_dir_req_t
{
struct file_dir_req_t *next;
struct file_dir_req_t *prev;
char guid[128];
char frontid[128];
int processNo;
char devid[128];
int type;
char path[256];
time_t create_time;
} file_dir_req_t;
#ifdef __cplusplus
}
#endif

View File

@@ -232,7 +232,7 @@ int main(int argc, const char **argv)
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index);
//log_debug("process", buf);
DIY_INFOLOG("process","【NORMAL】前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index);
DIY_INFOLOG_CODE("process",0,LOG_CODE_OTHER,"【NORMAL】前置的%s%d号进程 进程级日志初始化完毕", get_front_msg_from_subdir(), g_front_seg_index);
#ifdef _OS_UNIX_
#ifdef QT_NO_DEBUG
@@ -268,7 +268,7 @@ int main(int argc, const char **argv)
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程 台账初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv;
}
@@ -277,7 +277,7 @@ int main(int argc, const char **argv)
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程 线程初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv;
}
@@ -324,7 +324,7 @@ int main(int argc, const char **argv)
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的业务线程死锁,退出进程");
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程 业务线程死锁,退出进程", get_front_msg_from_subdir(), g_front_seg_index);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程 业务线程死锁,退出进程", get_front_msg_from_subdir(), g_front_seg_index);
apr_sleep(apr_time_from_sec(10));
exit(-1039);

View File

@@ -34,6 +34,7 @@ extern apr_pool_t* g_init_pool;
extern int g_DevFlag; //日志配置中读取的参数暂无特定使用lnk20250121
extern int IED_COUNT;
extern int RECALL_ONLY_FLAG; //lnk20260309添加一个全局变量标志是否只运行补招程序
//lnk20250115end
@@ -150,13 +151,6 @@ void CloseIECReports(chnl_usr_t *chnl_usr)
void closeChannel(chnl_usr_t *chnl_usr)
{
//终端日志的key,lnk20250526
char full_key_t_c[256]; // 分配足够空间
char full_key_t_d[256]; // 分配足够空间
snprintf(full_key_t_c, sizeof(full_key_t_c), "terminal.%s.COM", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id);
snprintf(full_key_t_d, sizeof(full_key_t_d), "terminal.%s.DATA", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id);
//终端日志的key,lnk20250526
char comm_str[256];
memset(comm_str,0,256);
apr_snprintf(comm_str,sizeof(comm_str),"%16s:%d\t\tdisconnected !!!",chnl_usr->ip_str,chnl_usr->chnl->port);
@@ -184,7 +178,7 @@ void closeChannel(chnl_usr_t *chnl_usr)
ret = mms_disconnectFromServer(chnl_usr->net_info,&chnl_usr->m_reqCtrl);
echo_warn("---------end disconnectFromServer!\n");
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】前置与终端%s - ip端口%s:%d 断开连接", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】前置与终端%s - ip端口%s:%d 断开连接", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
if (ret != SD_SUCCESS){
echo_warn("---------disconnectFromServer success!\n");
@@ -308,26 +302,19 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
{
LD_info = &(ied_usr->LD_info[cpuno]); //遍历监测点
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", LD_info->mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526
if (LD_info->cpuno==0){
// 仅在还没达到5次上限时打印
if (!LD_info->has_logged_regist) {
LD_info->registcount++;
if (LD_info->registcount <= 5) {
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【ERROR】监测点:%s - id:%s报告触发失败,监测点逻辑标识号为0,请检查装置对应的台账信息是否正确", LD_info->name,LD_info->mp_id);
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【ERROR】监测点:%s - id:%s报告触发失败,监测点逻辑标识号为0,请检查装置对应的台账信息是否正确", LD_info->name,LD_info->mp_id);
}
// 到5次就不再打印并标记
if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s监测点逻辑标识号错误日志已达本次记录上限不再输出请检查装置对应的台账信息是否正确",
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s监测点逻辑标识号错误日志已达本次记录上限不再输出请检查装置对应的台账信息是否正确",
LD_info->name, LD_info->mp_id);
}
}
@@ -341,7 +328,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
if (judge_rpt_next_should_do(rptinfo)==SHOULD_DO_NOTHING)//检查是否触发
{
//DIY_DEBUGLOG(full_key_m_c,"【DEBUG】监测点:%s - id:%s不注册报告", LD_info->name,LD_info->mp_id);
//DIY_DEBUGLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【DEBUG】监测点:%s - id:%s不注册报告", LD_info->name,LD_info->mp_id);
continue;
}
@@ -357,7 +344,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
printf("start mms_register_iec_rpt................................\n");
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s开始注册报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】监测点:%s - id:%s开始注册报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
if ( strstr(rptinfo->rptID,"LLN0$BR$brcbFlickerData") )
rptinfo->IntgPd = 600; //10分钟
@@ -385,14 +372,14 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
LD_info->registcount++;
if (LD_info->registcount <= 5) {
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT, "【WARN】监测点:%s - id:%s注册报告失败,报告名:%s",
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT, "【WARN】监测点:%s - id:%s注册报告失败,报告名:%s",
LD_info->name, LD_info->mp_id, rpt_inst_name);
}
// 到5次就不再打印并标记
if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告失败日志已达本次注册上限不再输出请检查装置icd和映射文件是否匹配或者装置存在过多连接",
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告失败日志已达本次注册上限不再输出请检查装置icd和映射文件是否匹配或者装置存在过多连接",
LD_info->name, LD_info->mp_id);
}
}
@@ -415,7 +402,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
//mq日志
LD_info->has_logged_regist = FALSE;
LD_info->registcount = 0;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注册报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
// add here to GI not the same time
GIoffset = 0.5 * g_pt61850app->giTime;
@@ -423,7 +410,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
}
printf("end mms_register_iec_rpt................................\n");
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s注册报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】监测点:%s - id:%s注册报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
}
}
else { //rpt_registered ==TRUE
@@ -432,7 +419,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
printf("start mms_unregister_iec_rpt................................\n");
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s开始注销报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】监测点:%s - id:%s开始注销报告,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
ret = mms_unregister_iec_rpt (chnl_usr->net_info, &g_rpt_typeids,
LD_info->LD_name,rpt_inst_name,g_pt61850app->mmsOpTimeout);
@@ -443,7 +430,7 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
APR_EGENERAL, LD_info->ied->id,LD_info->cpuno,LD_info->LD_name,rpt_inst_name,chnl_usr->ip_str,chnl_usr->chnl_id);
//mq日志
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注销报告失败,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【WARN】监测点:%s - id:%s注销报告失败,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
}
else {
@@ -452,11 +439,11 @@ void ChannelCheckIECReports(chnl_usr_t *chnl_usr)
LD_info->ied->id,LD_info->cpuno,LD_info->LD_name,rpt_inst_name,chnl_usr->ip_str,chnl_usr->chnl->port,chnl_usr->chnl_id );
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s注销报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】监测点:%s - id:%s注销报告成功,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
}
printf("end mms_unregister_iec_rpt................................\n");
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s注销报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】监测点:%s - id:%s注销报告结束,报告名:%s", LD_info->name,LD_info->mp_id,rpt_inst_name);
}
}
@@ -509,13 +496,6 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
for(cpuno=0 ; cpuno<ied->cpucount; cpuno++) {
LD_info = &(ied_usr->LD_info[cpuno]);
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", LD_info->mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526
//日志控制块缺失
if (LD_info->logcount<=0){
// 仅在还没达到5次上限时打印
@@ -523,13 +503,13 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
LD_info->registcount++;
if (LD_info->registcount <= 5) {
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败,监测点缺少日志控制块,请检查装置对应的装置类型是否有配对的icd模型", LD_info->name,LD_info->mp_id);
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败,监测点缺少日志控制块,请检查装置对应的装置类型是否有配对的icd模型", LD_info->name,LD_info->mp_id);
}
// 到5次就不再打印并标记
if (LD_info->registcount > 5) {
LD_info->has_logged_regist = true;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s缺少日志控制块日志已达本次记录上限不再输出请检查装置对应的装置类型是否有配对的icd模型",
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s缺少日志控制块日志已达本次记录上限不再输出请检查装置对应的装置类型是否有配对的icd模型",
LD_info->name, LD_info->mp_id);
}
}
@@ -560,11 +540,11 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
if(strcmp(cfg1.ValueOfTimeUnit, "utc") == 0){//装置时间是utc还是北京
utc_or_beijing = 28800;//秒
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为utc时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为utc时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
else{
utc_or_beijing = 0;
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为beijing时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为beijing时间,监测点对应装置型号:%s", LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
//////////////////////////////////////////////////////////////
@@ -608,7 +588,7 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
LD_info->ied->id, LD_info->cpuno, LD_info->LD_name, loginfo->logName, chnl_usr->ip_str, chnl_usr->chnl_id);
//mq日志
//DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s开始补招数据", LD_info->name,LD_info->mp_id);
//DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s开始补招数据", LD_info->name,LD_info->mp_id);
ret = mms_jread(loginfo, chnl_usr->net_info, loginfo->LD_info->LD_name, loginfo->logName,
loginfo->start_time, loginfo->end_time, g_pt61850app->mmsOpTimeout, chnl_usr->ip_str);
@@ -617,7 +597,7 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
LD_info->ied->id, LD_info->cpuno, LD_info->LD_name, loginfo->logName, chnl_usr->ip_str, chnl_usr->chnl_id);
//mq日志
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败 - 失败时间点:%lld 至 %lld", LD_info->name,LD_info->mp_id,loginfo->start_time,loginfo->end_time);
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【ERROR】监测点:%s - id:%s补招数据失败 - 失败时间点:%lld 至 %lld", LD_info->name,LD_info->mp_id,loginfo->start_time,loginfo->end_time);
failed_count++;
}
@@ -670,7 +650,7 @@ void ChannelCheckIECLogs(chnl_usr_t *chnl_usr)
// ===== [新增结束] =====
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s结束补招数据", LD_info->name,LD_info->mp_id);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_RECALL,"【WARN】监测点:%s - id:%s结束补招数据", LD_info->name,LD_info->mp_id);
//}
}
@@ -1118,9 +1098,9 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml)
//关闭这个终端的所有连接//////////////////////////////////////////////////////////////////////
for(chnl_no=0 ; chnl_no<ied->chncount; chnl_no++) {
chnl_usr = (chnl_usr_t*)ied->channel[chnl_no].connect;
if (chnl_usr->m_state!=CHANNEL_CONNECTED){//跳过未连接的通道
/*if (chnl_usr->m_state!=CHANNEL_CONNECTED){//跳过未连接的通道
continue;
}
}*///20260416任何状态都关闭连接
closeChannel(chnl_usr);//关闭更新台账后,任务会自动连接
}
@@ -1231,9 +1211,9 @@ void process_ledger_update(trigger_update_xml_t *ledger_update_xml)
//关闭这个终端的所有连接//////////////////////////////////////////////////////////////////////
for(chnl_no=0 ; chnl_no<ied->chncount; chnl_no++) {
chnl_usr = (chnl_usr_t*)ied->channel[chnl_no].connect;
if (chnl_usr->m_state!=CHANNEL_CONNECTED){ //跳过没连接的通道,一般一个终端只有一个
/*if (chnl_usr->m_state!=CHANNEL_CONNECTED){ //跳过没连接的通道,一般一个终端只有一个
continue;
}
}*///20260416任何状态都关闭连接
closeChannel(chnl_usr);//关闭更新台账后如果是删除则不会再连接关闭连接时这个ied的报告会被清除报告控制会被注销
}
@@ -1328,6 +1308,7 @@ void print_monitor(const monitor* mon) {
printf("Terminal Connect: %s\n", is_empty(mon->terminal_connect) ? "N/A" : mon->terminal_connect);
printf("Timestamp: %s\n", is_empty(mon->timestamp) ? "N/A" : mon->timestamp);
printf("Status: %s\n", is_empty(mon->status) ? "N/A" : mon->status);
printf("Log Level: %d\n", mon->log_level);
}
// 打印 terminal 结构体信息
@@ -1346,6 +1327,7 @@ void print_terminal(const terminal* tmnl) {
printf("Address: %s\n", is_empty(tmnl->addr_str) ? "N/A" : tmnl->addr_str);
printf("Port: %s\n", is_empty(tmnl->port) ? "N/A" : tmnl->port);
printf("Timestamp: %s\n", is_empty(tmnl->timestamp) ? "N/A" : tmnl->timestamp);
printf("Log Level: %d\n", tmnl->log_level);
// 打印监测点信息,如果监测点字段为空,则打印 N/A
int i;
@@ -1416,11 +1398,14 @@ void check_ledger_update()//lnk20250113
//调试用
print_trigger_update_xml(trigger_ledger_update_xml);
//处理台账更新加台账锁lnk20250114
//pthread_mutex_lock(&mtx); printf("ledgerupdate hold lock !!!!!!!!!!!");
process_ledger_update(trigger_ledger_update_xml); //台账更新
//pthread_mutex_unlock(&mtx); printf("ledgerupdate free lock !!!!!!!!!!!");
//处理台账更新添加控制标志
if (RECALL_ONLY_FLAG != 1 || (g_node_id != STAT_DATA_BASE_NODE_ID)) {
process_ledger_update(trigger_ledger_update_xml); //台账更新
}
else{
printf("only process recall config, skip ledger update\n");
DIY_WARNLOG_CODE("process",0,LOG_CODE_SPACE_ALARM,"【WARN】当前配置为仅日志模式,统计数据进程跳过台账更新");
}
}
// 使用完后释放动态分配的内存
@@ -1475,13 +1460,13 @@ void check_disk_quota()
//printf("Current user disk free size: %dMB ,total size: %dMB \n",freeSizeMB,totalSizeMB);
if (freeSizeMB<g_min_free_size){
echo_warn2("Current user disk free size: %dMB < %dMB, please check!\n",freeSizeMB,g_min_free_size);
DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测 当前磁盘的可用空间为%dMB,小于最小可用空间%dMB,请检查磁盘",freeSizeMB,g_min_free_size);
DIY_WARNLOG_CODE("process",0,LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测 当前磁盘的可用空间为%dMB,小于最小可用空间%dMB,请检查磁盘",freeSizeMB,g_min_free_size);
}
if ((freeSizeMB/(totalSizeMB/100+1) )<10){
echo_warn2("Current user disk free size percent < 10%%, free size: %dMB ,total size: %dMB ,please check!\n",
freeSizeMB,totalSizeMB);
DIY_WARNLOG_CODE("process",LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘",freeSizeMB,totalSizeMB);
DIY_WARNLOG_CODE("process",0,LOG_CODE_SPACE_ALARM,"【WARN】前置磁盘检测 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘",freeSizeMB,totalSizeMB);
}
}
@@ -1545,6 +1530,9 @@ void CheckAllConnectedChannel()
if(chnl_usr->m_state == CHANNEL_CONNECTED)
{
if(g_node_id == THREE_SECS_DATA_BASE_NODE_ID) {
HandleFileDirReqForChannel(chnl_usr);//文件目录请求
}
ChannelCheckIECReports(chnl_usr);//报告
if ( (g_node_id == SOE_COMTRADE_BASE_NODE_ID) || (g_node_id == HIS_DATA_BASE_NODE_ID) || (g_node_id == NEW_HIS_DATA_BASE_NODE_ID) || (g_node_id == RECALL_HIS_DATA_BASE_NODE_ID) || (g_node_id == RECALL_ALL_DATA_BASE_NODE_ID))
@@ -1600,13 +1588,6 @@ void CheckNextNotConnectedChannel()
return;
}
//终端日志的key,lnk20250526
char full_key_t_c[256]; // 分配足够空间
char full_key_t_d[256]; // 分配足够空间
snprintf(full_key_t_c, sizeof(full_key_t_c), "terminal.%s.COM", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id);
snprintf(full_key_t_d, sizeof(full_key_t_d), "terminal.%s.DATA", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id);
//终端日志的key,lnk20250526
//10-11-01 22:03 beijing
if( ( (chnl_total_no+1)==g_pt61850app->chnl_counts) || (g_onlyIP[0]!=0) ){
if(g_pt61850app->initNum<255)
@@ -1632,7 +1613,7 @@ void CheckNextNotConnectedChannel()
//mq日志
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = true;
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = false;
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d连接成功", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d连接成功", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
mvl_free_req_ctrl(chnl_usr->m_reqCtrl);
chnl_usr->m_reqCtrl = NULL;
@@ -1679,11 +1660,11 @@ void CheckNextNotConnectedChannel()
if(true == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = false;
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip/端口:%s:%d,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,secsSince);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip/端口:%s:%d,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,secsSince);
}
else if(false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat && false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip/端口:%s:%d,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,secsSince);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip/端口:%s:%d,从开始连接到目前已经%i秒,连接失败,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,secsSince);
}
mvl_free_req_ctrl(chnl_usr->m_reqCtrl);
@@ -1714,11 +1695,11 @@ void CheckNextNotConnectedChannel()
if(true == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat = false;
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
}
else if(false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->lastconnectstat && false == ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect){
((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->has_logged_disconnect = true;
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d,从开始连接到目前已经300秒,未能获取连接响应,断开连接!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
}
@@ -1758,7 +1739,7 @@ void CheckNextNotConnectedChannel()
if (chnl_usr->chnl->ied->cpucount != NULL && chnl_usr->chnl->ied->cpucount > 0 && ied_usr->dev_flag == ENABLE) {//2023-09-26 czy 如果line count<0 不需要连接//lnk20250121如果终端无效则不连接
//mq日志
//DIY_WARNLOG(full_key_t_c,"【WARN】重新连接终端%s - ip端口:%s:%d", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
//DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】重新连接终端%s - ip端口:%s:%d", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
ret = mms_connectToServer(ied_usr->dev_key, ied_usr->dev_series, serverARName, &(chnl_usr->net_info), &(chnl_usr->m_reqCtrl));
@@ -1770,7 +1751,7 @@ void CheckNextNotConnectedChannel()
chnl_usr->m_StartConnectingTime = sGetMsTime();
//mq日志
//DIY_WARNLOG(full_key_t_c,"【WARN】正在重新连接终端%s - ip端口:%s:%d - 识别码/秘钥:%s/%s", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_series,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_key);
//DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】正在重新连接终端%s - ip端口:%s:%d - 识别码/秘钥:%s/%s", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_series,((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->dev_key);
}
@@ -1782,7 +1763,7 @@ void CheckNextNotConnectedChannel()
echo_warn3("FAILED: mms_connectToServer IP %s:%d ,NetInfo= %x \n", chnl_usr->ip_str, chnl_usr->chnl->port, chnl_usr->net_info);
//mq日志
//DIY_WARNLOG(full_key_t_c,"【WARN】重新连接终端%s - ip端口:%s:%d 失败!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
//DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】重新连接终端%s - ip端口:%s:%d 失败!", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
}
}
@@ -1813,7 +1794,7 @@ void CheckNextNotConnectedChannel()
chnl_usr->chnl->status = STATUS_BREAKOFF;
//mq日志
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d 断连完成,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d 断连完成,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
}
else
@@ -1843,7 +1824,7 @@ void CheckNextNotConnectedChannel()
chnl_usr->chnl->status = STATUS_BREAKOFF;
//mq日志
DIY_WARNLOG_CODE(full_key_t_c,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d 断连未完成,但是已经超时180秒,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
DIY_WARNLOG_CODE(((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,1,LOG_CODE_COMM,"【WARN】终端%s - ip端口:%s:%d 断连未完成,但是已经超时180秒,关闭连接通道", ((ied_usr_t*)(chnl_usr->chnl->ied->usr_ext))->terminal_id,chnl_usr->ip_str,chnl_usr->chnl->port);
}
}
@@ -1995,13 +1976,6 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
ied_usr_t *ied_usr = GET_IEDEXT_ADDR(ied);
int have_new_files = FALSE;
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", LD_info->mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526
for (i=0;i<256;i++) {
if (LD_info->FltNum[i]<=0)
continue;
@@ -2013,7 +1987,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
printf(">>>>>>>> IED [%d]: %s is calling cn wavefile, !!!!!!!! file_match_str=%s \n",ied->id,ied->name,file_match_str);
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s开始召唤录波文件", LD_info->name,LD_info->mp_id);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【NORMAL】监测点:%s - id:%s开始召唤录波文件", LD_info->name,LD_info->mp_id);
ret = SD_FAILURE;
filenum = 0;
@@ -2035,14 +2009,14 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
int ret2,ret3;
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s获取录波文件列表成功,开始匹配录波文件", LD_info->name,LD_info->mp_id);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【NORMAL】监测点:%s - id:%s获取录波文件列表成功,开始匹配录波文件", LD_info->name,LD_info->mp_id);
//WW 2023-11-01将录波段号由字符串匹配修改为int的fltnum匹配
ret2 = parse_file_names_by_fltnum(LD_info->FltNum[i], ldstr, filenames, filenum, &cfg_idx, &dat_idx, file_base_name, file_yyyymm);
//WW 2023-11-01 end
if (ret2 !=APR_SUCCESS){
//mq日志
//DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【WARN】监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]);
//DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【WARN】监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]);
//lnk20250819装置没有对应的文件时清除录波号段
printf("监测点:%s - id:%s前置记录的录波事件上传的录波号段%d与从装置获取的录波文件列表匹配失败,装置没有对应的号段的录波文件,清除该记录", LD_info->name,LD_info->mp_id,LD_info->FltNum[i]);
LD_info->FltNum[i] = -1;
@@ -2058,15 +2032,35 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
if (ret2==SD_SUCCESS && ret3==SD_SUCCESS ) { //两个文件都写好了
//mq日志
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s从终端获取录波文件成功", LD_info->name,LD_info->mp_id);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【NORMAL】监测点:%s - id:%s从终端获取录波文件成功", LD_info->name,LD_info->mp_id);
QVVR_t *qvvr; //暂态事件
long long start_tm,trig_tm,end_tm;
long long start_tm,trig_tm,end_tm;//北京时间
ret2 = extract_timestamp_from_cfg_file(filenames[cfg_idx],&start_tm,&trig_tm);//提取文件的开始时间和触发时间
//添加录波文件时间戳校准20260409
{
XmlConfigC cfg;
long long utc_or_beijing = 0;
if (get_xml_config_by_dev_type(ied_usr->dev_type, &cfg)) {
if(strcmp(cfg.WaveTimeFlag, "utc") == 0){//装置时间是utc还是北京
utc_or_beijing = 28800000;//八小时相差毫秒数
}
else{
utc_or_beijing = 0;
}
trig_tm = trig_tm + utc_or_beijing;//如果是utc时间则转换为北京时间
start_tm = start_tm + utc_or_beijing;//接口上送没用到
}
else {
printf("读取失败,未找到 dev_type\n");
}
}
printf(">>>>>>>> extract_timestamp_from_cfg_file end \n");
if (ret2 ==APR_SUCCESS) {
DIY_INFOLOG(full_key_m_c,"【NORMAL】监测点:%s - id:%s提取录波文件时间成功", LD_info->name,LD_info->mp_id);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【NORMAL】监测点:%s - id:%s提取录波文件时间成功", LD_info->name,LD_info->mp_id);
//to find the paired qvvr by the time of trig_tm
printf(">>>>>>>> extract_timestamp_from_cfg_file success \n");
qvvr = find_qvvr_by_trig_tm(LD_info,trig_tm); //根据文件的触发时间查找检测点记录的匹配上的暂态事件
@@ -2086,18 +2080,18 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
char loc_file_fullname_cfg[256];//本地文件名
memset(loc_file_fullname_cfg, 0, sizeof(loc_file_fullname_cfg));
apr_snprintf(loc_file_fullname_cfg, sizeof(loc_file_fullname_cfg), "/home/pq/FeProject/comtrade/%s", cfg_only_filename_ret);
apr_snprintf(loc_file_fullname_cfg, sizeof(loc_file_fullname_cfg), "/FeProject/comtrade/%s", cfg_only_filename_ret);
char oss_file_fullname_cfg[256];//远端文件名
memset(oss_file_fullname_cfg, 0, sizeof(oss_file_fullname_cfg));
apr_snprintf(oss_file_fullname_cfg, sizeof(oss_file_fullname_cfg), "comtrade/wave/%s/%s", LD_info->mp_id, cfg_only_filename_ret);
if (FILE_FLAG == 1) {
PutOSS(oss_file_fullname_cfg, loc_file_fullname_cfg);//使用buffer推送文件
//PutOSS(oss_file_fullname_cfg, loc_file_fullname_cfg);//使用buffer推送文件
}
else if (FILE_FLAG == 2) {
OBSFile(loc_file_fullname_cfg, oss_file_fullname_cfg, "putObject");//这里并没有上传文件流
//OBSFile(loc_file_fullname_cfg, oss_file_fullname_cfg, "putObject");//这里并没有上传文件流
}
else if(FILE_FLAG==3){
WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_cfg, uuid_cfg, filename_cfg);//通过form-data上传文件
//WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_cfg, uuid_cfg, filename_cfg);//通过form-data上传文件
}
//LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取
else if (FILE_FLAG == 4) {
@@ -2124,18 +2118,18 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
char loc_file_fullname_dat[256];
memset(loc_file_fullname_dat, 0, sizeof(loc_file_fullname_dat));
apr_snprintf(loc_file_fullname_dat, sizeof(loc_file_fullname_dat), "/home/pq/FeProject/comtrade/%s", dat_only_filename_ret);
apr_snprintf(loc_file_fullname_dat, sizeof(loc_file_fullname_dat), "/FeProject/comtrade/%s", dat_only_filename_ret);
char oss_file_fullname_dat[256];
memset(oss_file_fullname_dat, 0, sizeof(oss_file_fullname_dat));
apr_snprintf(oss_file_fullname_dat, sizeof(oss_file_fullname_dat), "comtrade/wave/%s/%s", LD_info->mp_id, dat_only_filename_ret);
if (FILE_FLAG == 1) {
PutOSS(oss_file_fullname_dat, loc_file_fullname_dat);//使用buffer推送文件
//PutOSS(oss_file_fullname_dat, loc_file_fullname_dat);//使用buffer推送文件
}
else if (FILE_FLAG == 2) {
OBSFile(loc_file_fullname_dat, oss_file_fullname_dat, "putObject");//这里并没有上传文件流
//OBSFile(loc_file_fullname_dat, oss_file_fullname_dat, "putObject");//这里并没有上传文件流
}
else if(FILE_FLAG==3){
WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_dat, uuid_dat, filename_dat);//通过form-data上传文件
//WebAPI_Uds_Upload(UDS_UPLOAD_URL, loc_file_fullname_dat, uuid_dat, filename_dat);//通过form-data上传文件
}
//LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取
else if (FILE_FLAG == 4) {
@@ -2283,22 +2277,24 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
//获取时间类型lnk20250520
XmlConfigC cfg;
if (get_xml_config_by_dev_type(ied_usr->dev_type, &cfg)) {
} else {
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是s", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
else{
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是ms", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
}
else {
printf("读取失败,未找到 dev_type\n");
}
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是秒", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
else{
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位是毫秒", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 匹配录波文件失败,录波号段:%d,录波文件的开始时间:%lld触发时间:%lld映射配置的暂态持续时间单位未配置", LD_info->name,LD_info->mp_id,LD_info->FltNum[i],start_tm,trig_tm);
}
}
}
}
else{
DIY_ERRORLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 下载录波文件%s和%s失败录波号段%d", LD_info->name,LD_info->mp_id,filenames[cfg_idx],filenames[dat_idx],LD_info->FltNum[i]);
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【ERROR】监测点:%s - id:%s 下载录波文件%s和%s失败录波号段%d", LD_info->name,LD_info->mp_id,filenames[cfg_idx],filenames[dat_idx],LD_info->FltNum[i]);
}
}
@@ -2306,7 +2302,7 @@ apr_status_t call_cn_wavelist(LD_info_t *LD_info )
if (ied && chnl_usr){
echo_warn2("mms_mvla_fdir Failed: IED [%d] %s \n", ied->id , chnl_usr->ip_str) ;
//mq日志
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_COMTRADE_FILE,"【WARN】监测点:%s - id:%s召唤录波文件列表失败,放弃这个号段", LD_info->name,LD_info->mp_id);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_COMTRADE_FILE,"【WARN】监测点:%s - id:%s召唤录波文件列表失败,放弃这个号段", LD_info->name,LD_info->mp_id);
LD_info->FltNum[i] = -1;
}

View File

@@ -854,15 +854,8 @@ ST_VOID u_iec_rpt_ind_data_by_devtype(MVL_VAR_ASSOC** info_va,
printf("[BEGIND Process] Received Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count);
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", LD_info->mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526
//mq日志
DIY_INFOLOG(full_key_m_d,"【NORMAL】前置收到监测点:%s - id:%s的报告,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】前置收到监测点:%s - id:%s的报告,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
//apr_time_t previousTime = apr_time_now();//
//apr_time_exp_t localTime;
@@ -1162,14 +1155,14 @@ ST_VOID u_iec_rpt_ind_data_by_devtype(MVL_VAR_ASSOC** info_va,
echo_err3("Ignore this report due to line_id invalid , Report From %s %s %s !!!",
APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID);
//mq日志
DIY_ERRORLOG_CODE(full_key_m_d,LOG_CODE_REPORT,"【ERROR】前置不处理这个监测点:%s - id:%s的报告,报告名称:%s,原因是监测点的序号非法", LD_info->name,LD_info->mp_id,rcb_info->RptID);
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【ERROR】前置不处理这个监测点:%s - id:%s的报告,报告名称:%s,原因是监测点的序号非法", LD_info->name,LD_info->mp_id,rcb_info->RptID);
}
printf("[END Process] Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count);
//mq日志
DIY_INFOLOG(full_key_m_d,"【NORMAL】前置处理监测点:%s - id:%s的报告结束,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】前置处理监测点:%s - id:%s的报告结束,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
//apr_time_t previousTimeend = apr_time_now();//
//apr_time_exp_t localTimeend;
@@ -1462,7 +1455,7 @@ ST_VOID u_iec_rpt_ind_data(MVL_VAR_ASSOC** info_va,
//need do nothing!
not_set_rpt_q_this = FALSE;
}
else if (strstr(FULL_FCDA_Name, "GGIO"))
else if (strstr(FULL_FCDA_Name, "GGIO") || strstr(FULL_FCDA_Name, "LPHD"))
{
not_set_rpt_q_this = FALSE;
}
@@ -1485,7 +1478,7 @@ ST_VOID u_iec_rpt_ind_data(MVL_VAR_ASSOC** info_va,
//need do nothing!
not_set_rpt_TimeID_this = FALSE;
}
else if (strstr(FULL_FCDA_Name, "GGIO")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
else if (strstr(FULL_FCDA_Name, "GGIO") || strstr(FULL_FCDA_Name, "LPHD")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
//need do nothing!
not_set_rpt_TimeID_this = FALSE;
}

View File

@@ -1457,6 +1457,29 @@ ST_VOID u_mvl_ident_ind (MVL_IND_PEND *indCtrl)
/************************************************************************/
/* getFile */
/*
先向远端发 fopen打开远程文件
拿到这个远程文件会话句柄 frsmid
循环发 fread一块一块把远程文件内容读回来并写入本地文件
最后发 fclose关闭远程文件
clientNetInfo客户端和 MMS 服务器之间的网络连接信息
loc_file本地保存的文件路径
rem_file远端设备上的文件路径
iTimeout每次请求等待响应的超时时间
返回值:
SD_SUCCESS下载成功
其他:失败错误码
*/
/************************************************************************/
ST_RET mms_getFile (MVL_NET_INFO *clientNetInfo, ST_CHAR *loc_file,
ST_CHAR *rem_file, ST_INT iTimeout)
@@ -1523,6 +1546,59 @@ ERR:
}
}
//***************************lnk20260309下发文件到装置*********************/
ST_RET mms_putFile(MVL_NET_INFO *clientNetInfo,
ST_CHAR *src_file,
ST_CHAR *dest_file,
ST_INT iTimeout)
{
MVL_REQ_PEND *reqCtrl = NULL;
ST_RET ret = SD_FAILURE;
if (clientNetInfo == NULL)
{
printf("\n mms_putFile failed: clientNetInfo is NULL");
return SD_FAILURE;
}
if (src_file == NULL || src_file[0] == '\0')
{
printf("\n mms_putFile failed: src_file is NULL or empty");
return SD_FAILURE;
}
if (dest_file == NULL || dest_file[0] == '\0')
{
printf("\n mms_putFile failed: dest_file is NULL or empty");
return SD_FAILURE;
}
ret = mvla_obtfile(clientNetInfo, src_file, dest_file, &reqCtrl);
if (ret == SD_SUCCESS)
ret = waitReqDone(reqCtrl, iTimeout);
if (ret != SD_SUCCESS)
{
printf("\n mms_putFile failed, src='%s', dest='%s', ret=0x%X",
src_file, dest_file, ret);
}
else
{
printf("\n mms_putFile OK, src='%s', dest='%s'",
src_file, dest_file);
}
if (reqCtrl != NULL)
{
mvl_free_req_ctrl(reqCtrl);
reqCtrl = NULL;
}
return ret;
}
//************************************************************************/
/* putFile */
/************************************************************************/
/* init_mem */

View File

@@ -24,6 +24,7 @@ extern int SOCKET_PORT;
extern int G_TEST_FLAG;
extern int g_front_seg_index;
extern int g_front_seg_num;
extern int RECALL_ONLY_FLAG; //lnk20260309添加一个全局变量标志是否只运行补招程序
#include "../rocketmq/SimpleProducer.h"
#include "../cfg_parse/custom_printf.h"//lnk20250225
@@ -187,48 +188,51 @@ apr_status_t init_rdb()
init_config();
GetServerIndexFromDB();
rv = parse_device_cfg_web();
if (rv != APR_SUCCESS) {
echo_errg("Parsed device config xml file with error,try to run! \n");
//只有补招运行时,统计不读取台账和模型
if (RECALL_ONLY_FLAG != 1 || (g_node_id != STAT_DATA_BASE_NODE_ID)) {
rv = parse_device_cfg_web();
if (rv != APR_SUCCESS) {
echo_errg("Parsed device config xml file with error,try to run! \n");
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_LEDGER,"【ERROR】前置的%s%d号进程调用web台账接口失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv;
}
return rv;
}
//台账读取过后初始化各级的日志
init_loggers();
rv = parse_model_cfg_web();
if (rv != APR_SUCCESS) {//不可能
echo_errg("Parsed model with error,try to run! \n");
//台账读取过后初始化各级的日志
init_loggers();
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
rv = parse_model_cfg_web();
if (rv != APR_SUCCESS) {//不可能
echo_errg("Parsed model with error,try to run! \n");
return rv;
}
//char buf[256];
//format_log_msg(buf,sizeof(buf),"前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
//log_error("process", buf);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_ICD_AND_DOWNLOAD,"【ERROR】前置的%s%d号进程调用web模型接口失败", get_front_msg_from_subdir(), g_front_seg_index);
Set_xml_nodeinfo();//解析xml模型
return rv;
}
rv = parse_rpt_log_ini();//报告块初始化
if (rv != APR_SUCCESS) {
echo_errg("Failed to parse report log define ini file! \n");
Set_xml_nodeinfo();//解析xml模型
DIY_ERRORLOG_CODE("process",LOG_CODE_RPTINIT,"【ERROR】前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
rv = parse_rpt_log_ini();//报告块初始化
if (rv != APR_SUCCESS) {
echo_errg("Failed to parse report log define ini file! \n");
return rv;
DIY_ERRORLOG_CODE("process",0,LOG_CODE_RPTINIT,"【ERROR】前置的%s%d号进程报告初始化失败", get_front_msg_from_subdir(), g_front_seg_index);
return rv;
}
}
if (app_get_private_config(g_my_conf_fname) != APR_SUCCESS) {
echo_errg("Failed when processing private configuration\n");
DIY_ERRORLOG_CODE("process",LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程读取mms配置失败", get_front_msg_from_subdir(), g_front_seg_index);
DIY_ERRORLOG_CODE("process",0,LOG_CODE_OTHER,"【ERROR】前置的%s%d号进程读取mms配置失败", get_front_msg_from_subdir(), g_front_seg_index);
return APR_EGENERAL;
}

View File

@@ -255,6 +255,9 @@ struct LD_info_t{
rptinfo_t **rptinfo; /**< rptinfo_t* 数组 */
int read_flag ; //CZY 2023-02-28 判断是否将监测点是否有效
//测点日志等级
int log_level; //0 ERROR 1 WARN 2 NORMAL 3 DEBUG
char mp_id[256];//CZY 2023-08-20 监测点编码8afaa
char terminal_code[256];//CZY 2023-08-20 终端编码
//int ld_ins;//CZY 2023-08-20 逻辑设备实例号1
@@ -273,8 +276,8 @@ struct LD_info_t{
int registcount;//lnk20250812
bool has_logged_regist;//lnk20250812
//不使用
int iUnitOfTime;//CZY 2023-08-17 WW 2022年12月7日15:43:34 装置上送事件持续时间单位切换(0-ms; 1-s)
//不使用
int iStatOfTime;//CZY 2023-08-17 WW 2022年12月7日15:48:33 统计数据时间 0-北京时间 1-UTC时间
int iJournalTime;//CZY 2023-08-17 WW 2022年12月7日15:52:32 补招日志时间(0-UTC时间(日志、录波文件均为UTC时间); 1-北京时间(日志北京时间、录波文件UTC时间 注:仅四川地区+8小时读取补招日志))
//不使用
@@ -327,6 +330,8 @@ struct ied_usr_t{
void *cookie;
double last_call_wavelist_time ; //上次召录波列表时间
int log_level; //0 ERROR 1 WARN 2 NORMAL 3 DEBUG
char terminal_id[256];//CZY 2023-08-20 终端id8afaa9a15707483a0157262f8e78077d
char org_name[256];//CZY 2023-08-20 所属单位,例:南京供公司
char maint_name[256];//CZY 2023-08-20 运维单位,例:南京供公司
@@ -527,6 +532,8 @@ int extract_timestamp_from_cfg_file(char *comtrade_fn,long long *start_tm,long l
int parse_file_names_by_fltnum(int fltnum, char* domname, char** filenames, int filenum, int* cfg_idx, int* dat_idx, char* file_base_name, char* file_yyyymm);
QVVR_t* find_qvvr_by_trig_tm(LD_info_t* LD_info,long long trig_tm);
void HandleFileDirReqForChannel(chnl_usr_t *chnl_usr);
//////////////////////////////////////////////////////////////////
#ifdef __cplusplus

View File

@@ -534,13 +534,6 @@ void processQVVR_end(LD_info_t* LD_info)
ied_t *ied = LD_info->ied;
ied_usr_t *ied_usr = GET_IEDEXT_ADDR(ied);
int ret;
//监测点日志的key,lnk20250526
char full_key_m_c[256]; // 分配足够空间
char full_key_m_d[256]; // 分配足够空间
snprintf(full_key_m_c, sizeof(full_key_m_c), "monitor.%s.COM", LD_info->mp_id);
snprintf(full_key_m_d, sizeof(full_key_m_d), "monitor.%s.DATA", LD_info->mp_id);
//监测点日志的key,lnk20250526
////////////////////////////////////////////////////////////////////////////////////////////////////////////
int find_paired = FALSE;
@@ -562,11 +555,11 @@ void processQVVR_end(LD_info_t* LD_info)
long long utc_or_beijing;
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
s_or_ms = 0.001;
//DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
//DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
else{
s_or_ms = 1.0;
//DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是毫秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
//DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s上送的暂态持续时间单位是毫秒,监测点对应装置型号:%s",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
if(strcmp(cfg.ValueOfTimeUnit, "utc") == 0){//上送的是utc还是北京
@@ -635,7 +628,7 @@ void processQVVR_end(LD_info_t* LD_info)
//匹配后再发qvvr起始时间要填暂态触发的时间就是第一次事件上送时只有时间没有值的那个时间
//mq日志
DIY_WARNLOG_CODE(full_key_m_d,LOG_CODE_TRANSIENT,"【WARN】监测点%s - id:%s 发生暂态事件,暂态时间:%lld暂态持续时间%f暂态幅值%f暂态类型%d",LD_info->name,LD_info->mp_id,
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_TRANSIENT,"【WARN】监测点%s - id:%s 发生暂态事件,暂态时间:%lld暂态持续时间%f暂态幅值%f暂态类型%d",LD_info->name,LD_info->mp_id,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_time,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_PerTime,
LD_info->qvvr[LD_info->qvvr_idx].QVVR_Amg,
@@ -669,10 +662,10 @@ void processQVVR_end(LD_info_t* LD_info)
//mq日志
if(strcmp(cfg.UnitOfTimeUnit, "1") == 0){//持续时间上送的是秒1还是毫秒0
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s记录了一个暂态事件但是没有匹配到事件的发生时间装置型号:%s 配置的暂态持续时间单位是秒",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s记录了一个暂态事件但是没有匹配到事件的发生时间装置型号:%s 配置的暂态持续时间单位是秒",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
else{
DIY_WARNLOG_CODE(full_key_m_c,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s记录了一个暂态事件但是没有匹配到事件的发生时间装置型号:%s 配置的暂态持续时间单位是毫秒",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
DIY_WARNLOG_CODE(LD_info->mp_id,2,LOG_CODE_TRANSIENT,"【WARN】监测点:%s - id:%s记录了一个暂态事件但是没有匹配到事件的发生时间装置型号:%s 配置的暂态持续时间单位是毫秒",LD_info->name,LD_info->mp_id,ied_usr->dev_type);
}
}

170
mykafka.ini Normal file
View File

@@ -0,0 +1,170 @@
[Kafka]
BrokerList=
EventTopic=
KafkaFlag=
KafkaListSize=
RTDataTopic=Real_Time_Data_Topic
HisTopic=LN_Topic
PSTTopic=LN_Topic
PLTTopic=LN_Topic
AlmTopic=AlmTopic
SngTopic=SngTopic
[Oracle]
OtlType=
OtlConnect=
OtlFlag=
OtlConnectLimit=
SqlListSize=
[Comtrade]
NEWESTFlag=
[SFTP]
SFtpFlag=
[SagSource]
UpdateFlag=
[Unit]
UnitOfTime=
[Recall]
JournalTime=
recall_lenth=
recall_start=
recall_dailytime=
select_day=
[screen]
ScreenFlag=
WebHost=
WebPort=
ScreenUrl=
[AccountUpdate]
Interval=
LastUpdateTime=
[MultiNode]
Interval=
[CommunicationLog]
StatusRecordDuration=
AbnormalRecordDuration=
[Postgres]
Database=
Username=
Password=
Schema=
Dnsname=
TablePrefix=
[Web]
ClientId=
ClientSecret=
TokenUrl=
DeviceUrl=
GrantType=
[Flag]
FileFlag=4
FrontInst=884d132ac3a01225fcacc8c10da07d09
FrontIP=192.168.1.167
SendFlag=3
RecallOnlyFlag=
[Ledger]
TerminalStatus="[0]"
MonitorStatus="[1,2]"
IcdFlag=0
IedCount=300
[Socket]
SocketEnable=0
SocketPort=13000
[Http]
HttpEnable=0
HttpIp=0.0.0.0
HttpPort=12000
WebDevice=http://192.168.1.68:10202/nodeDevice/nodeDeviceList
WebIcd=http://192.168.1.68:10202/icd/icdPathList
WebIntegrity=http://192.168.1.68:10202/LineIntegrityData/saveOrUpdateData
WebComflag=http://192.168.1.68:10202/dev/updateDevComFlag
WebEvent=http://192.168.1.68:10203/event/addEventDetail
WebFileupload=http://192.168.1.68:10207/file/upload
WebFiledownload=http://192.168.1.68:10207/file/download
[Oss]
OssEndpoint=
AccessKeyID=
AccessKeySecret=
BucketName=
[FrontNode]
Node=
[MySql]
ConStr=
[InfluxDb]
SelectUrl=
WriteUrl=
[RocketMq]
producer=Group_producer
Ipport=192.168.1.68:9876
Topic=TEST_Topic
Tag=Test_Tag
Key=Test_Keys
Queuenum=4
Testflag=1
Testnum=100
Testtype=1
TestPort=11000
TestList=
consumer=Group_consumer
ConsumerIpport=192.168.1.68:9876
ConsumerTopicRT=ask_real_data_topic
ConsumerTagRT=Test_Tag
ConsumerKeyRT=Test_Keys
ConsumerAccessKey=rmqroot
ConsumerSecretKey=001@#njcnmq
ConsumerChannel=
ConsumerTopicUD=control_Topic
ConsumerTagUD=Test_Tag
ConsumerKeyUD=Test_Keys
ConsumerTopicRC=recall_Topic
ConsumerTagRC=Test_Tag
ConsumerKeyRC=Test_Keys
ConsumerTopicSET=process_Topic
ConsumerTagSET=Test_Tag
ConsumerKeySET=Test_Keys
ConsumerTopicLOG=ask_log_Topic
ConsumerTagLOG=Test_Tag
ConsumerKeyLOG=Test_Keys
LOGTopic=log_Topic
LOGTag=Test_Tag
LOGKey=Test_Keys
CONNECTTopic=Device_Run_Flag_Topic
CONNECTTag=Test_Tag
CONNECTKey=Test_Keys
Heart_Beat_Topic=Heart_Beat_Topic
Heart_Beat_Tag=Test_Tag
Heart_Beat_Key=Test_Key
Topic_Reply_Topic=Topic_Reply_Topic
Topic_Reply_Tag=Test_Tag
Topic_Reply_Key=Test_Key
[LogRate]
ResetSec=3600
LimitSec=60
KeepAllMs=60000
KeepBurstMs=1000
KeepBurstCount=60
KeepHighFreqCount=10

View File

@@ -1,21 +1,34 @@
#ifdef __cplusplus
#include "../json/mms_json_inter.h"
#include "../rocketmq/CProducer.h"
#include "../rocketmq/CMessage.h"
#include "../rocketmq/CSendResult.h"
#include "../rocketmq/CPushConsumer.h"
//#include "../rocketmq/CProducer.h"
//#include "../rocketmq/CMessage.h"
//#include "../rocketmq/CSendResult.h"
//#include "../rocketmq/CPushConsumer.h"
#include "../rocketmq/DefaultMQProducer.h"
#include "../rocketmq/MQMessage.h"
#include "../rocketmq/SendResult.h"
#include "../rocketmq/SessionCredentials.h"
#include "../rocketmq/MQMessageExt.h"
#include "../rocketmq/ConsumeType.h"
#include "../rocketmq/MQMessageListener.h"
#include <vector>
#include <iostream>
#include <string>
using namespace rocketmq;
/*添加测试函数lnk10-10*/
void producer_send0();
void StartSendMessage(CProducer* producer,const char* strbody);
void producer_send(const char* strbody);
void rocketmq_producer_send(const char* strbody,const char* topic);
void rocketmq_StartSendMessage(CProducer* producer,const char* strbody,const char* topic);
//void producer_send0();
//void StartSendMessage(CProducer* producer,const char* strbody);
//void producer_send(const char* strbody);
//void rocketmq_producer_send(const char* strbody,const char* topic);
//void rocketmq_StartSendMessage(CProducer* producer,const char* strbody,const char* topic);
void rocketmq_producer_send(const std::string& body,
const std::string& topic,
const std::string& tags,
const std::string& keys);
extern "C" {
void rocketmq_test_rt();
void rocketmq_test_ud();
@@ -32,17 +45,25 @@ extern void my_rocketmq_send(Ckafka_data_t& data);
void InitializeProducer();
void ShutdownAndDestroyProducer();
//////////////////////////////////////////////////////消费者
void InitializeConsumer(const std::string& consumerName, const std::string& nameServer, const char* topic, const char* tag, const std::string& key);
void ShutdownAndDestroyConsumer();
typedef ConsumeStatus (*MessageCallBack)(
const MQMessageExt& msg
);
struct Subscription {
std::string topic;
std::string tag;
MessageCallBack callback;
Subscription(const std::string& t, const std::string& tg, MessageCallBack cb)
: topic(t), tag(tg), callback(cb) {std::cout << "Subscription topic: " << topic << std::endl;}
Subscription(const std::string& t,
const std::string& tg,
MessageCallBack cb)
: topic(t), tag(tg), callback(cb) {}
};
//void InitializeConsumer(const std::string& consumerName, const std::string& nameServer, const char* topic, const char* tag, const std::string& key);
void InitializeConsumer(const std::string& consumerName,
const std::string& nameServer,
const std::vector<Subscription>& subscriptions);
void ShutdownAndDestroyConsumer();
void rocketmq_consumer_receive(
const std::string& consumerName,

View File

@@ -8,8 +8,215 @@
#前置all的重置或者新增都是由稳态的第一个进程来处理所有进程收到这条消息后先判断自己的进程号是否是1而且是稳态否则不处理所有操作均由这个进程完成
if [ -z "$SETSID" ]; then
export SETSID=1
nohup setsid "$0" "$@" >> /tmp/set_process_detach.log 2>&1 < /dev/null &
exit 0
fi
# 关闭从父进程继承来的 socket / pipe / 文件描述符
for fd_path in /proc/$$/fd/*; do
fd_num=$(basename "$fd_path")
case "$fd_num" in
0|1|2) ;;
*) eval "exec ${fd_num}>&-" 2>/dev/null ;;
esac
done
# 设置日志文件路径
LOGFILE="$FEP_ENV/dat/log/start_fe.log"
LOGFILE="/FeProject/dat/log/start_fe.log"
INI_FILE="/FeProject/etc/config/mykafka.ini"
LOCK_FILE="/tmp/set_process.lock"
if [ -f "$LOCK_FILE" ]; then
old_pid=$(cat "$LOCK_FILE")
if ps -p "$old_pid" > /dev/null 2>&1; then
echo "Already running: $old_pid"
exit 1
else
echo "Stale lock found, removing"
rm -f "$LOCK_FILE"
fi
fi
echo $$ > "$LOCK_FILE"
trap "rm -f $LOCK_FILE" EXIT
get_ini_value() {
local key="$1"
local line
line=$(grep -E "^[[:space:]]*${key}=" "$INI_FILE" | tail -n 1)
[ -z "$line" ] && return 1
# 去掉 key=
line="${line#*=}"
# 去掉首尾空格
line=$(echo "$line" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
[ -n "$line" ] || return 1
echo "$line"
return 0
}
log() {
echo "$@" | tee -a "$LOGFILE"
}
check_local_port_released() {
local PORT="$1"
for retry in $(seq 1 3); do
for i in $(seq 1 20); do
if ! ss -lntp 2>/dev/null | grep -q ":${PORT}[[:space:]]"; then
log "[OK] Local port $PORT released"
return 0
fi
log "[WAIT] Local port $PORT still in use... ($i/20)"
sleep 1
done
log "[RETRY] Local port $PORT not released, retry $retry/3"
sleep 1
done
log "[FAIL] Local port $PORT still in use after retries:"
ss -lntp 2>/dev/null | grep ":${PORT}[[:space:]]" | tee -a "$LOGFILE"
return 1
}
check_remote_conn_released() {
local REMOTE_IP="$1"
local REMOTE_PORT="$2"
for retry in $(seq 1 3); do
for i in $(seq 1 20); do
if ! ss -ntp 2>/dev/null \
| grep "${REMOTE_IP}:${REMOTE_PORT}" \
| grep -E 'pt61850netd_pqfe|fe_watchdog|fe_main' >/dev/null; then
log "[OK] Remote ${REMOTE_IP}:${REMOTE_PORT} released"
return 0
fi
log "[WAIT] Remote ${REMOTE_IP}:${REMOTE_PORT} still exists... ($i/20)"
ss -ntp 2>/dev/null \
| grep "${REMOTE_IP}:${REMOTE_PORT}" \
| grep -E 'pt61850netd_pqfe|fe_watchdog|fe_main' \
| tee -a "$LOGFILE"
sleep 1
done
log "[RETRY] Remote ${REMOTE_IP}:${REMOTE_PORT} not released, retry $retry/3"
sleep 1
done
log "[FAIL] Remote ${REMOTE_IP}:${REMOTE_PORT} still exists:"
ss -ntp 2>/dev/null \
| grep "${REMOTE_IP}:${REMOTE_PORT}" \
| grep -E 'pt61850netd_pqfe|fe_watchdog|fe_main' \
| tee -a "$LOGFILE"
return 1
}
check_value_released() {
local key="$1"
local value="$2"
[ -z "$value" ] && return 0
# 纯端口
if echo "$value" | grep -Eq '^[0-9]+$'; then
[ "$value" = "0" ] && { log "[SKIP] $key disabled"; return 0; }
log "[CHECK] $key local port: $value"
check_local_port_released "$value"
return $?
fi
# URL
if echo "$value" | grep -Eq '^[a-zA-Z]+://'; then
local hostport ip port
hostport=$(echo "$value" | sed -n 's#^[a-zA-Z]\+://\([^/]*\).*#\1#p')
ip="${hostport%%:*}"
port="${hostport##*:}"
if [ -n "$ip" ] && [ -n "$port" ] && [ "$ip" != "$port" ]; then
log "[CHECK] $key remote: $ip:$port"
check_remote_conn_released "$ip" "$port"
return $?
fi
log "[SKIP] $key invalid URL: $value"
return 0
fi
# ip:port
if echo "$value" | grep -Eq '^[^:]+:[0-9]+$'; then
local ip="${value%%:*}"
local port="${value##*:}"
log "[CHECK] $key remote: $ip:$port"
check_remote_conn_released "$ip" "$port"
return $?
fi
log "[SKIP] $key unsupported value: $value"
return 0
}
check_key_released() {
local key="$1"
local value
value=$(get_ini_value "$key") || {
log "[SKIP] $key not found"
return 0
}
log "==== Checking $key = $value ===="
check_value_released "$key" "$value"
return $?
}
check_all_resources_released() {
local ret=0
log "=============================="
log " Start checking resources..."
log "=============================="
# 本地端口
check_key_released "TestPort" || ret=1
check_key_released "HttpPort" || ret=1
check_key_released "SocketPort" || ret=1
# MQ
check_key_released "Ipport" || ret=1
check_key_released "ConsumerIpport" || ret=1
# Web
check_key_released "WebDevice" || ret=1
check_key_released "WebIcd" || ret=1
check_key_released "WebIntegrity" || ret=1
check_key_released "WebComflag" || ret=1
check_key_released "WebEvent" || ret=1
check_key_released "WebFileupload" || ret=1
check_key_released "WebFiledownload" || ret=1
if [ $ret -eq 0 ]; then
log "✅ ALL resources released"
else
log "❌ Some resources NOT released"
fi
return $ret
}
# 输出当前时间并打印进程停止信息
echo "" ; echo ""
@@ -20,7 +227,7 @@ echo "****** `date "+%F %R:%S"` start setting Processes after 3 sec ******" >>"$
# 函数检查并处理日志文件大小
check_log_file() {
if [ -n "$1" ]; then
if [ -n "$1" ] && [ -f "$1" ]; then
FILE_SIZE=0
FILE_SIZE=$(du "$1" | awk '{print $1}')
@@ -45,23 +252,46 @@ check_log_file $LOGFILE
# 定义查找并杀死进程的函数
kill_process_by_name() {
PROCESS_NAME=$1
PID=$(ps -ef | grep "$PROCESS_NAME" | grep -v "grep" | awk '{print $2}')
local PROCESS_NAME="$1"
local PIDS
if [ -n "$PID" ]; then
echo "Found process '$PROCESS_NAME' with PID: $PID"
PIDS=$(ps -ef | grep "$PROCESS_NAME" | grep -v grep | awk '{print $2}')
if [ -n "$PIDS" ]; then
echo "Found process '$PROCESS_NAME' with PID(s): $PIDS"
echo "Killing process..."
kill -9 $PID
if [ $? -eq 0 ]; then
echo "Process '$PROCESS_NAME' killed successfully."
else
echo "Failed to kill the process '$PROCESS_NAME'."
fi
for pid in $PIDS; do
kill -15 "$pid" 2>/dev/null
done
sleep 3
for pid in $PIDS; do
if ps -p "$pid" >/dev/null 2>&1; then
echo "Process still exists, force kill: $pid"
kill -9 "$pid" 2>/dev/null
fi
done
else
echo "Process '$PROCESS_NAME' not found."
fi
}
wait_all_exit() {
for i in $(seq 1 30); do
COUNT=$(ps -ef | grep -E 'pt61850netd_pqfe|fe_watchdog' | grep -v grep | wc -l)
if [ "$COUNT" -eq 0 ]; then
echo "All FE processes exited"
return 0
fi
echo "Waiting FE processes exit... ($COUNT still running)"
sleep 1
done
echo "Timeout waiting FE processes exit"
return 1
}
# 功能块开始
handle_reset() {
# 功能reset
@@ -71,70 +301,79 @@ handle_reset() {
if [ "$2" == "all" ]; then
# 关闭旧的看门狗进程
kill_process_by_name "/FeProject/bin/fe_watchdog"
#kill_process_by_name "/FeProject/bin/fe_watchdog"
# 关闭旧的 stat 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_stat_data"
#kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_stat_data"
# 关闭旧的 recall 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_recallhis_data"
#kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_recallhis_data"
# 关闭旧的 3s 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_3s_data"
#kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_3s_data"
# 关闭旧的 comtrade 进程
kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_soe_comtrade"
#kill_process_by_name "/FeProject/bin/pt61850netd_pqfe -d cfg_soe_comtrade"
/FeProject/boot/stop_fe.sh
wait_all_exit || exit 1
check_all_resources_released || exit 1
#关闭进程后等待一段时间,防止端口占用
#sleep 5
sleep 5
# 清空 runtime.cf 中的所有进程配置
sed -i '/cfg_stat_data/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/cfg_recallhis_data/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/cfg_3s_data/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/cfg_soe_comtrade/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/fe_watchdog/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/cfg_stat_data/d' /FeProject/etc/runtime.cf
sed -i '/cfg_recallhis_data/d' /FeProject/etc/runtime.cf
sed -i '/cfg_3s_data/d' /FeProject/etc/runtime.cf
sed -i '/cfg_soe_comtrade/d' /FeProject/etc/runtime.cf
sed -i '/fe_watchdog/d' /FeProject/etc/runtime.cf
# 根据进程号添加对应进程配置
if [ "$1" -eq 1 ]; then
#看门狗固定放在第一个防止stop时会把要杀死的进程重启
sed -i "2a\\$(printf '/FeProject/bin/ ^ fe_watchdog -m 18192 ^ ^ ^ 1 ^ IGNORE_RESTART ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ fe_watchdog -m 18192 ^ ^ ^ 1 ^ IGNORE_RESTART ^\n')" /FeProject/etc/runtime.cf
# 进程号为 1按固定格式添加
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s 1_1^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s 1_1^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_3s_data^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_soe_comtrade^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s 1_1^ ^ ^ 1 ^ ^\n')" /FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s 1_1^ ^ ^ 1 ^ ^\n')" /FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_3s_data^ ^ ^ 1 ^ ^\n')" /FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_soe_comtrade^ ^ ^ 1 ^ ^\n')" /FeProject/etc/runtime.cf
else
#看门狗固定放在第一个防止stop时会把要杀死的进程重启
sed -i "2a\\$(printf '/FeProject/bin/ ^ fe_watchdog -m 18192 ^ ^ ^ 1 ^ IGNORE_RESTART ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ fe_watchdog -m 18192 ^ ^ ^ 1 ^ IGNORE_RESTART ^\n')" /FeProject/etc/runtime.cf
# 进程号大于 1按 -s ${i}_ 格式添加
for i in $(seq 1 $1); do
# 在 runtime.cf 中插入对应的配置行,直接插入变量替换结果
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
done
#以下部分没有多进程
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_3s_data^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_soe_comtrade^ ^ ^ 1 ^ ^\n')" /home/pq/FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_3s_data^ ^ ^ 1 ^ ^\n')" /FeProject/etc/runtime.cf
sed -i "2a\\$(printf '/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_soe_comtrade^ ^ ^ 1 ^ ^\n')" /FeProject/etc/runtime.cf
fi
# 修改后等一下
sleep 1
# 确保文件已被写入并刷新
sync
# 重新启动服务
/home/pq/FeProject/boot/start_fe.sh
/FeProject/boot/start_fe.sh
echo "****** reset all in $1******" >>"$LOGFILE"
elif [ "$2" == "stat" ]; then
# 清空 runtime.cf 中包含 cfg_stat_data 的行
sed -i '/cfg_stat_data/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/cfg_stat_data/d' /FeProject/etc/runtime.cf
# 根据进程号来添加新的进程配置
for i in $(seq 1 $1); do
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
done
# 关闭旧的看门狗进程
@@ -146,16 +385,16 @@ handle_reset() {
#sleep 5
# 启动服务不影响其他功能的进程
/home/pq/FeProject/boot/start_fe.sh
/FeProject/boot/start_fe.sh
echo "****** reset stat in $1******" >>"$LOGFILE"
elif [ "$2" == "recall" ]; then
# 清空 runtime.cf 中包含 cfg_recallhis_data 的行
sed -i '/cfg_recallhis_data/d' /home/pq/FeProject/etc/runtime.cf
sed -i '/cfg_recallhis_data/d' /FeProject/etc/runtime.cf
# 根据进程号来添加新的进程配置
for i in $(seq 1 $1); do
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${i}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
done
# 关闭旧的看门狗进程
@@ -166,7 +405,7 @@ handle_reset() {
#sleep 5
# 启动服务不影响其他功能的进程
/home/pq/FeProject/boot/start_fe.sh
/FeProject/boot/start_fe.sh
echo "****** reset recall in $1******" >>"$LOGFILE"
else
@@ -190,22 +429,22 @@ handle_add() {
# 如果 $1 在 1 和 10 之间,进入处理逻辑
if [ "$2" == "all" ]; then
# 检查是否已存在该条目,避免重复添加
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^" /home/pq/FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^" /FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
fi
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^" /home/pq/FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^" /FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
fi
elif [ "$2" == "stat" ]; then
# 检查是否已存在该条目,避免重复添加
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^" /home/pq/FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^" /FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_stat_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
fi
elif [ "$2" == "recall" ]; then
# 检查是否已存在该条目,避免重复添加
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^" /home/pq/FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /home/pq/FeProject/etc/runtime.cf
if ! grep -q "/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^" /FeProject/etc/runtime.cf; then
sed -i "2a/FeProject/bin/ ^ pt61850netd_pqfe -d cfg_recallhis_data -s ${1}_${1}^ ^ ^ 1 ^ ^" /FeProject/etc/runtime.cf
fi
else
echo "****** process add type null ******"
@@ -218,7 +457,7 @@ handle_add() {
#sleep 5
# 启动服务,不影响正在运行的进程
/home/pq/FeProject/boot/start_fe.sh
/FeProject/boot/start_fe.sh
else
# 如果 $1 不在 1 到 10 之间,记录错误日志
@@ -230,14 +469,13 @@ handle_add() {
}
# 获取当前脚本的进程ID
CURRENT_PID=$$
#CURRENT_PID=$$
# 检查是否有其他的set_process.sh脚本正在运行排除当前脚本
if pgrep -f "set_process.sh" | grep -v "^$CURRENT_PID$" > /dev/null; then
echo "set_process.sh is already running. Exiting..."
echo "set_process.sh is already running. Exiting..." >>"$LOGFILE"
exit 1
fi
#if pgrep -f "set_process.sh" | grep -v "^$CURRENT_PID$" > /dev/null; then
# echo "set_process.sh is already running. Exiting..."
# echo "set_process.sh is already running. Exiting..." >>"$LOGFILE"
# exit 1
#fi
#脚本应该等待3秒钟
sleep 3