2025-01-16 16:17:01 +08:00
/**
* @ file : $ RCSfile : mms_process . c , v $
2025-05-09 16:53:07 +08:00
* @ brief : $ PROFIBUS 与 SSRTDB交互
2025-01-16 16:17:01 +08:00
*
* @ version : $ Revision : 1.28 $
* @ date : $ Date : 2022 / 11 / 28 07 : 13 : 13 $
* @ author : $ Author : lizhongming $
* @ state : $ State : Exp $
*
* @ latest : $ Id : mms_process . c , v 1.28 2022 / 11 / 28 07 : 13 : 13 lizhongming Exp $
*/
# include <string.h>
# include "rdb_client.h"
# include <stdlib.h>
# include "db_interface.h"
# include "node.h"
# include "ied.h"
# include "../json/mms_json_inter.h"
2025-03-04 17:29:04 +08:00
# include "../cfg_parse/custom_printf.h"//lnk20250225
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
# include "../log4cplus/log4.h"//lnk添加log4
2025-01-16 16:17:01 +08:00
void clear_rpt_counter_by_trigger ( trigger_t * trigger ) ;
//lnk20241031
extern void SOEFileWeb ( char * localpath , char * cloudpath , char * wavepath ) ;
2025-05-09 16:53:07 +08:00
//lnk 2024-11-4 添加时间转换函数
2025-03-12 11:45:53 +08:00
char * convertMsToDateTimeString ( int64_t msTime ) ;
2025-01-16 16:17:01 +08:00
//lnk20250115
extern pthread_mutex_t mtx ;
extern apr_pool_t * g_cfg_pool ;
extern apr_pool_t * g_init_pool ;
2025-05-09 16:53:07 +08:00
extern int g_DevFlag ; //日志配置中读取的参数, 暂无特定使用lnk20250121
2025-01-21 17:48:37 +08:00
extern int IED_COUNT ;
2025-01-16 16:17:01 +08:00
//lnk20250115end
# ifdef DEBUG_SISCO
SD_CONST static ST_CHAR * SD_CONST thisFileName = __FILE__ ;
# endif
# ifdef _OS_UNIX_
# include <sys/vfs.h>
# endif
extern uint32_t g_dead_lock_counter ;
extern uint32_t g_thread_blocked_times ;
extern uint16_t g_client_id ;
extern RPT_TYPEIDS g_rpt_typeids ;
//extern rdb_t *g_rdb ;
extern node_t * g_node ;
extern char g_my_conf_fname [ 256 ] ;
extern apr_pool_t * g_init_pool ;
extern apr_pool_t * g_run_pool ;
extern pt61850app_t * g_pt61850app ;
//extern char *g_sysfile_filedir;
2025-05-09 16:53:07 +08:00
extern char g_onlyIP [ 255 ] ; //直连某个IP, 仅仅为方便测试
2025-01-16 16:17:01 +08:00
//extern int g_sysfile_appid; //add by rzx
//extern apr_time_t g_file_valid_time;
extern uint32_t g_min_free_size ;
/////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
extern uint32_t g_node_id ;
extern int three_secs_enabled ;
extern int auto_register_report_enabled ;
extern int FRONT_MP_NUM ;
///////////////////////////////////////////////////////////////////////////////
extern int FILE_FLAG ;
extern int recall_len ;
extern int recall_sta ;
extern int recall_daily ;
extern char * UDS_UPLOAD_URL ;
///////////////////////////////////////////////////////////////////
2025-01-22 17:00:34 +08:00
//lnk20250122start
apr_status_t init_rem_dib_table ( )
{
int pos = 0 ;
int iedno , chnl_no ;
ied_t * ied ;
struct in_addr ip ;
chnl_usr_t * chnl_usr ;
2025-02-17 16:58:14 +08:00
if ( IED_COUNT < g_pt61850app - > chnl_counts ) {
2025-05-09 16:53:07 +08:00
set_rem_dib_table_size ( g_pt61850app - > chnl_counts ) ; //按照最大的终端数来申请
2025-02-17 16:58:14 +08:00
g_pt61850app - > chnl_usr = apr_pcalloc ( g_init_pool , g_pt61850app - > chnl_counts * sizeof ( chnl_usr_t * ) ) ;
printf ( " set_rem_dib_table_size %d \n " , g_pt61850app - > chnl_counts ) ;
}
else {
2025-05-09 16:53:07 +08:00
set_rem_dib_table_size ( IED_COUNT ) ; //按照最大的终端数来申请
2025-02-17 16:58:14 +08:00
g_pt61850app - > chnl_usr = apr_pcalloc ( g_init_pool , IED_COUNT * sizeof ( chnl_usr_t * ) ) ;
printf ( " set_rem_dib_table_size %d \n " , IED_COUNT ) ;
}
2025-01-22 17:00:34 +08:00
for ( iedno = 0 ; iedno < g_node - > n_clients ; iedno + + ) {
ied = g_node - > clients [ iedno ] ;
for ( chnl_no = 0 ; chnl_no < ied - > chncount ; chnl_no + + ) {
chnl_usr = ied - > channel [ chnl_no ] . connect ;
g_pt61850app - > chnl_usr [ pos ] = chnl_usr ;
ip . s_addr = htonl ( ied - > channel [ chnl_no ] . addr ) ;
strcpy ( chnl_usr - > ip_str , inet_ntoa ( ip ) ) ;
printf ( " add_rem_dib_table %s:%d \n " , chnl_usr - > ip_str , ied - > channel [ chnl_no ] . port ) ;
add_rem_dib_table ( pos + + , chnl_usr - > ip_str , ied - > channel [ chnl_no ] . port ) ;
{
char comm_str [ 256 ] ;
memset ( comm_str , 0 , 256 ) ;
apr_snprintf ( comm_str , sizeof ( comm_str ) , " %16s:%d \t \t inited " , chnl_usr - > ip_str , ied - > channel [ chnl_no ] . port ) ;
add_comm_log ( comm_str ) ;
}
}
}
return APR_SUCCESS ;
}
//lnk20250122end
2025-01-16 16:17:01 +08:00
void CloseIECReports ( chnl_usr_t * chnl_usr )
{
ied_t * ied ;
ied_usr_t * ied_usr ;
LD_info_t * LD_info ;
rptinfo_t * rptinfo = NULL ;
int cpuno , rpt_no ;
ST_RET ret ;
ied = chnl_usr - > chnl - > ied ;
ied_usr = GET_IEDEXT_ADDR ( ied ) ;
for ( cpuno = 0 ; cpuno < ied - > cpucount ; cpuno + + ) {
LD_info = & ( ied_usr - > LD_info [ cpuno ] ) ;
for ( rpt_no = 0 ; rpt_no < LD_info - > rptcount ; rpt_no + + ) {
char rpt_inst_name [ 65 ] ;
rptinfo = LD_info - > rptinfo [ rpt_no ] ;
if ( ! rptinfo - > rpt_registered )
continue ;
if ( rptinfo - > chnl_id ! = chnl_usr - > chnl_id )
continue ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
rptinfo - > rpt_registered = FALSE ;
2025-05-09 16:53:07 +08:00
//注销报告后, 取消10分钟 再注册一次的限制,可立即注册
2025-01-16 16:17:01 +08:00
rptinfo - > m_LastRegisterFailedTime = sGetMsTime ( ) - 10 * 60 * 1000 ;
rptinfo - > m_rcb_info = NULL ;
}
}
}
void closeChannel ( chnl_usr_t * chnl_usr )
{
2025-05-28 16:09:15 +08:00
//终端日志的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
2025-01-16 16:17:01 +08:00
char comm_str [ 256 ] ;
memset ( comm_str , 0 , 256 ) ;
apr_snprintf ( comm_str , sizeof ( comm_str ) , " %16s:%d \t \t disconnected !!! " , chnl_usr - > ip_str , chnl_usr - > chnl - > port ) ;
add_comm_log ( comm_str ) ;
FRONT_MP_NUM - - ;
echo_warn1 ( " Close Channel IP: %s " , chnl_usr - > ip_str ) ;
CloseIECReports ( chnl_usr ) ;
echo_warn1 ( " -------Close Channel IP: %s success!!!!!!!!! " , chnl_usr - > ip_str ) ;
if ( chnl_usr - > net_info ) {
ALL_RCB_INFO * all_rcb_info ;
RCB_INFO * rcb_info ;
ST_RET ret ;
if ( chnl_usr - > net_info - > user_info )
{
all_rcb_info = ( ALL_RCB_INFO * ) chnl_usr - > net_info - > user_info ;
while ( ( rcb_info = ( RCB_INFO * ) list_get_first ( & all_rcb_info - > rcb_info_list ) ) ! = NULL )
rcb_info_destroy ( rcb_info ) ;
chk_free ( all_rcb_info ) ;
chnl_usr - > net_info - > user_info = NULL ;
}
chnl_usr - > net_info - > rem_vmd = NULL ;
echo_warn ( " ---------start disconnectFromServer! \n " ) ;
ret = mms_disconnectFromServer ( chnl_usr - > net_info , & chnl_usr - > m_reqCtrl ) ;
echo_warn ( " ---------end disconnectFromServer! \n " ) ;
2025-05-28 16:09:15 +08:00
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 ) ;
2025-01-16 16:17:01 +08:00
if ( ret ! = SD_SUCCESS ) {
echo_warn ( " ---------disconnectFromServer success! \n " ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_warn2 ( " CHANNEL %s,NetInfo= %x mms_disconnectFromServer failed ,Disconnect it roughly! \n " , chnl_usr - > ip_str , chnl_usr - > net_info ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
mvl_free_req_ctrl ( chnl_usr - > m_reqCtrl ) ;
chnl_usr - > net_info - > user_ext = NULL ;
chnl_usr - > net_info = NULL ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > m_reqCtrl = NULL ;
chnl_usr - > net_info = NULL ;
chnl_usr - > m_state = CHANNEL_DISCONNECTED ;
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
chnl_usr - > chnl - > status = STATUS_BREAKOFF ;
}
else {
chnl_usr - > m_state = CHANNEL_DISCONNECTING ;
chnl_usr - > m_StartDisconnectingTime = sGetMsTime ( ) ;
}
} else {
chnl_usr - > m_state = CHANNEL_DISCONNECTED ;
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > chnl - > status = STATUS_BREAKOFF ;
}
}
ST_VOID Callback_channel_disconnect_ind ( MVL_NET_INFO * NetInfo , ST_INT discType )
{
chnl_usr_t * chnl_usr ;
chnl_usr = ( chnl_usr_t * ) NetInfo - > user_ext ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( chnl_usr ) {
if ( chnl_usr - > m_state = = CHANNEL_CONNECTING )
{ //do nothing;
printf ( " Do nothing,m_state == CHANNEL_CONNECTING ,NetInfo = %x " , NetInfo ) ;
} else if ( chnl_usr - > m_state = = CHANNEL_CONNECTED )
{
closeChannel ( chnl_usr ) ;
} else if ( chnl_usr - > m_state = = CHANNEL_DISCONNECTING )
{ //do nothing;
printf ( " Do nothing,m_state == CHANNEL_DISCONNECTING ,NetInfo = %x " , NetInfo ) ;
} else if ( chnl_usr - > m_state = = CHANNEL_DISCONNECTED )
{ //do nothing;
printf ( " Do nothing,m_state == CHANNEL_DISCONNECTED ,NetInfo = %x " , NetInfo ) ;
}
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > net_info = NULL ;
NetInfo - > user_ext = NULL ;
}
printf ( " Callback_channel_disconnect_ind ,NetInfo = %x " , NetInfo ) ;
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
//zw修改 2023 - 8 - 17 通讯中断回调函数 PG库记录当日中断次数
2025-01-16 16:17:01 +08:00
ied_usr_t * ied_usr = ( ied_usr_t * ) ( chnl_usr - > chnl [ 0 ] . ied - > usr_ext ) ;
}
void IECReport_tryGI ( chnl_usr_t * chnl_usr , rptinfo_t * rptinfo )
{
char varName [ 64 ] = " " ;
ST_BOOLEAN GI = TRUE ; /* call GI */
if ( ( sGetMsTime ( ) - rptinfo - > m_LastGITime ) < g_pt61850app - > giTime * 1000 )
return ;
rptinfo - > m_LastGITime = sGetMsTime ( ) ;
get_rpt_inst_name ( rptinfo , varName ) ;
strcat ( varName , " $GI " ) ;
mms_named_var_write ( chnl_usr - > net_info , varName , DOM_SPEC , rptinfo - > LD_info - > LD_name ,
g_rpt_typeids . mmsbool , ( ST_CHAR * ) & GI , g_pt61850app - > mmsOpTimeout ) ;
}
2025-05-09 16:53:07 +08:00
//增加处理根据稳态,或暂态功能等,决定 报告是否需要注册、取消注册或 不做任何处理
2025-01-16 16:17:01 +08:00
int judge_rpt_next_should_do ( rptinfo_t * rptinfo )
{
2025-05-09 16:53:07 +08:00
int should_register_state = 1 ; //各功能默认注册
int is_real_report = ( rptinfo - > report_PQ_type & REPORT_TYPE_REAL ) ; //报告控制中包含的类型
2025-01-16 16:17:01 +08:00
int is_soe_report = ( rptinfo - > report_PQ_type & REPORT_TYPE_SOE ) ;
if ( three_secs_enabled ) {
2025-05-09 16:53:07 +08:00
should_register_state = 0 ; //3秒功能模块, 默认不注册
if ( is_real_report ) { //映射中包含控制块且触发
2025-01-16 16:17:01 +08:00
should_register_state = rptinfo - > LD_info - > real_data ;
}
if ( is_soe_report ) {
should_register_state = rptinfo - > LD_info - > soe_data ;
}
}
2025-05-09 16:53:07 +08:00
if ( should_register_state = = rptinfo - > rpt_registered ) //已经触发/没有触发,没有变动
2025-01-16 16:17:01 +08:00
return SHOULD_DO_NOTHING ;
2025-05-09 16:53:07 +08:00
else if ( should_register_state ) //有变动且要触发
2025-01-16 16:17:01 +08:00
return SHOULD_REGISTER ;
else
2025-05-09 16:53:07 +08:00
return SHOULD_UNREGISTER ; //有变动,不触发
2025-01-16 16:17:01 +08:00
}
void ChannelCheckIECReports ( chnl_usr_t * chnl_usr )
{
ied_t * ied ;
ied_usr_t * ied_usr ;
LD_info_t * LD_info ;
rptinfo_t * rptinfo = NULL ;
channel_t * channel = NULL ;
int cpuno , rpt_no ;
char rpt_inst_name [ 65 ] ;
ST_RET ret ;
ied = chnl_usr - > chnl - > ied ;
ied_usr = GET_IEDEXT_ADDR ( ied ) ;
channel = chnl_usr - > chnl ;
2025-02-21 16:24:41 +08:00
2025-01-16 16:17:01 +08:00
for ( cpuno = 0 ; cpuno < ied - > cpucount ; cpuno + + )
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
{
2025-05-09 16:53:07 +08:00
LD_info = & ( ied_usr - > LD_info [ cpuno ] ) ; //遍历监测点
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( LD_info - > cpuno = = 0 )
continue ;
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
for ( rpt_no = 0 ; rpt_no < LD_info - > rptcount ; rpt_no + + ) { //遍历报告(映射文件中读取的报告控制)
2025-05-26 16:51:27 +08:00
//监测点日志的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
2025-01-16 16:17:01 +08:00
rptinfo = LD_info - > rptinfo [ rpt_no ] ;
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
if ( judge_rpt_next_should_do ( rptinfo ) = = SHOULD_DO_NOTHING ) //检查是否触发
2025-05-26 16:51:27 +08:00
{
2025-07-10 18:05:18 +08:00
//DIY_DEBUGLOG(full_key_m_c,"【DEBUG】监测点:%s - id:%s不注册报告", LD_info->name,LD_info->mp_id);
2025-01-16 16:17:01 +08:00
continue ;
2025-05-26 16:51:27 +08:00
}
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( rptinfo - > m_curRptSuffix = = - 1 )
2025-04-29 15:05:36 +08:00
rptinfo - > m_curRptSuffix = g_pt61850app - > rptSuffix [ g_client_id ] [ 0 ] ;
2025-05-09 16:53:07 +08:00
get_rpt_inst_name ( rptinfo , rpt_inst_name ) ; //获取报告名
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( ! rptinfo - > rpt_registered ) {
if ( ( sGetMsTime ( ) - rptinfo - > m_LastRegisterFailedTime ) > 20 * 1000 ) {
2025-05-09 16:53:07 +08:00
//注册失败后间隔 20秒 再注册一次
2025-01-16 16:17:01 +08:00
RCB_INFO * rcb_info ;
printf ( " start mms_register_iec_rpt................................ \n " ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s开始注册报告,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-01-16 16:17:01 +08:00
if ( strstr ( rptinfo - > rptID , " LLN0$BR$brcbFlickerData " ) )
2025-05-09 16:53:07 +08:00
rptinfo - > IntgPd = 600 ; //10分钟
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
/////////////////////////WW 2023-08-30 增加设备类型与报告绑定
2025-01-16 16:17:01 +08:00
rcb_info = mms_register_iec_rpt ( chnl_usr - > net_info , & g_rpt_typeids ,
LD_info - > LD_name , rpt_inst_name , g_pt61850app - > mmsOpTimeout , rptinfo - > IntgPd , rptinfo - > TrgOpt ,
( ST_UINT8 * ) rptinfo - > m_EntryID , ( ST_UINT8 * ) rptinfo - > OptFlds ) ;
//WW end
///////////////////////////
if ( ! rcb_info )
{
if ( + + rptinfo - > m_curRptSuffix > g_pt61850app - > rptSuffix [ g_client_id ] [ 1 ] )
rptinfo - > m_curRptSuffix = g_pt61850app - > rptSuffix [ g_client_id ] [ 0 ] ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
rptinfo - > m_LastRegisterFailedTime = sGetMsTime ( ) ;
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
echo_err9 ( " \n 注册报告失败! Rregister iec_rpt failed !!! IED_ID=%d ,CPU=%d , domain: %s ,rpt_inst_name: %s ,ip: %s:%d,chnl_id: %d ,IntgPd=%d ,TrgOpt=0x%x \n " ,
2025-01-16 16:17:01 +08:00
APR_EGENERAL , 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 , rptinfo - > IntgPd , rptinfo - > TrgOpt ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s注册报告失败,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-01-16 16:17:01 +08:00
}
else
{
double GIoffset ;
rptinfo - > rpt_registered = TRUE ;
rptinfo - > m_rcb_info = rcb_info ;
rptinfo - > chnl_id = chnl_usr - > chnl_id ;
chnl_usr - > m_NegRespTimes = 0 ;
chnl_usr - > m_LastPosRespTime = sGetMsTime ( ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_msg11 ( " \n Register iec_rpt succeed, IED_ID=%d ,CPU=%d ,domain: %s ,rpt_inst_name: %s ,ip: %s:%d,chnl_id: %d ,IntgPd=%d ,TrgOpt=0x%x ,OptFlds=0x%x%x \n " ,
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 ,
rptinfo - > IntgPd , rptinfo - > TrgOpt , rptinfo - > OptFlds [ 0 ] , rptinfo - > OptFlds [ 1 ] ) ;
2025-05-26 16:51:27 +08:00
//mq日志
2025-05-29 16:36:34 +08:00
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s注册报告成功,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
// add here to GI not the same time
GIoffset = 0.5 * g_pt61850app - > giTime ;
rptinfo - > m_LastGITime = sGetMsTime ( ) - GIoffset * 1000 ;
}
printf ( " end mms_register_iec_rpt................................ \n " ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s注册报告结束,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-01-16 16:17:01 +08:00
}
}
else { //rpt_registered ==TRUE
if ( ( sGetMsTime ( ) - rptinfo - > m_LastUnRegisterFailedTime ) > 20 * 1000 ) {
2025-05-09 16:53:07 +08:00
//取消注册失败后间隔 20秒 再取消注册一次
2025-01-16 16:17:01 +08:00
printf ( " start mms_unregister_iec_rpt................................ \n " ) ;
2025-04-29 15:05:36 +08:00
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s开始注销报告,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-01-16 16:17:01 +08:00
ret = mms_unregister_iec_rpt ( chnl_usr - > net_info , & g_rpt_typeids ,
LD_info - > LD_name , rpt_inst_name , g_pt61850app - > mmsOpTimeout ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( ret = = SD_FAILURE ) {
rptinfo - > m_LastUnRegisterFailedTime = sGetMsTime ( ) ;
2025-05-09 16:53:07 +08:00
echo_err6 ( " \n 取消注册报告失败! UnRregister iec_rpt failed !!! IED_ID=%d ,CPU=%d , domain: %s ,rpt_inst_name: %s ,ip: %s,chnl_id: %d \n " ,
2025-01-16 16:17:01 +08:00
APR_EGENERAL , LD_info - > ied - > id , LD_info - > cpuno , LD_info - > LD_name , rpt_inst_name , chnl_usr - > ip_str , chnl_usr - > chnl_id ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s注销报告失败,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-01-16 16:17:01 +08:00
}
else {
rptinfo - > rpt_registered = FALSE ;
echo_msg7 ( " \n UnRegister iec_rpt succeed, IED_ID=%d ,CPU=%d ,domain: %s ,rpt_inst_name: %s ,ip: %s:%d,chnl_id: %d \n " ,
2025-05-26 16:51:27 +08:00
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 ) ;
2025-01-16 16:17:01 +08:00
}
printf ( " end mms_unregister_iec_rpt................................ \n " ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s注销报告结束,报告名:%s " , LD_info - > name , LD_info - > mp_id , rpt_inst_name ) ;
2025-01-16 16:17:01 +08:00
}
2025-04-29 15:05:36 +08:00
}
2025-01-16 16:17:01 +08:00
}
}
}
void ChannelCheckWaveFiles ( chnl_usr_t * chnl_usr )
{
ied_t * ied ;
ied_usr_t * ied_usr ;
LD_info_t * LD_info ;
int cpuno ;
ied = chnl_usr - > chnl - > ied ;
ied_usr = GET_IEDEXT_ADDR ( ied ) ;
for ( cpuno = 0 ; cpuno < ied - > cpucount ; cpuno + + ) {
LD_info = & ( ied_usr - > LD_info [ cpuno ] ) ;
if ( LD_info - > line_id < = 0 ) {
continue ;
}
call_cn_wavelist ( LD_info ) ; //try to call wave file
}
}
void ChannelCheckIECLogs ( chnl_usr_t * chnl_usr )
{
ST_RET ret ;
ied_t * ied ;
ied_usr_t * ied_usr ;
LD_info_t * LD_info ;
loginfo_t * loginfo = NULL ;
int cpuno ;
double now ;
static double last_check_recall_config_time = 0.0 ;
ied = chnl_usr - > chnl - > ied ;
ied_usr = GET_IEDEXT_ADDR ( ied ) ;
2025-05-26 16:51:27 +08:00
2025-01-16 16:17:01 +08:00
for ( cpuno = 0 ; cpuno < ied - > cpucount ; cpuno + + ) {
LD_info = & ( ied_usr - > LD_info [ cpuno ] ) ;
if ( LD_info - > logcount < = 0 )
continue ;
loginfo = LD_info - > loginfo [ 0 ] ;
apr_sleep ( apr_time_from_sec ( 1 ) / 10 ) ;
2025-05-26 16:51:27 +08:00
//监测点日志的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
2025-05-09 16:53:07 +08:00
Check_Recall_Config ( LD_info - > mp_id ) ; //尝试获取xml结构
2025-04-29 15:05:36 +08:00
2025-07-24 16:14:00 +08:00
//补招数量不为0且不是正在补招
2025-01-16 16:17:01 +08:00
if ( LD_info - > autorecallcount ! = 0 & & LD_info - > autorecallflag ! = 1 ) {
int i ;
int failed_count = 0 ;
2025-07-28 15:23:13 +08:00
/////////////////////////////////////////////////////根据配置文件控制下发补招时间为北京时间还是utc时间
printf ( " ~~~~~~~this dev type is %s~~~~~~~ " , ied_usr - > dev_type ) ;
XmlConfigC cfg1 ;
if ( get_xml_config_by_dev_type ( ied_usr - > dev_type , & cfg1 ) ) {
printf ( " ValueOfTimeUnit = %s \n " , cfg1 . ValueOfTimeUnit ) ;
} else {
printf ( " 读取失败,未找到 dev_type \n " ) ;
}
long long utc_or_beijing ;
if ( strcmp ( cfg1 . ValueOfTimeUnit , " utc " ) = = 0 ) { //装置时间是utc还是北京
2025-07-28 17:27:19 +08:00
utc_or_beijing = 28800 ; //秒
2025-07-28 15:23:13 +08:00
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为utc时间,监测点对应装置型号:%s " , LD_info - > name , LD_info - > mp_id , ied_usr - > dev_type ) ;
}
else {
utc_or_beijing = 0 ;
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s开始补招数据,下发补招时间为beijing时间,监测点对应装置型号:%s " , LD_info - > name , LD_info - > mp_id , ied_usr - > dev_type ) ;
}
//////////////////////////////////////////////////////////////
2025-01-16 16:17:01 +08:00
for ( i = 0 ; i < LD_info - > autorecallcount ; i + + ) {
2025-07-24 16:14:00 +08:00
LD_info - > autorecallflag = 1 ; //正在补招
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//当前不区分稳态和暂态lnk20241030, 如果做区分修改: Check_Recall_Config从xml文件获取数据后, 赋值给了LD_info
2025-01-16 16:17:01 +08:00
loginfo - > need_steady = LD_info - > autorecall [ i ] - > need_steady ; loginfo - > need_voltage = LD_info - > autorecall [ i ] - > need_voltage ;
loginfo - > start_time = apr_time_from_sec ( LD_info - > autorecall [ i ] - > start - 5 ) ;
loginfo - > end_time = apr_time_from_sec ( LD_info - > autorecall [ i ] - > end - 5 ) ;
2025-07-28 15:23:13 +08:00
/////////////////////////////////////////////////////根据配置文件控制下发补招时间为北京时间还是utc时间,上送的数据61850库会转换成北京时间?
2025-07-28 17:27:19 +08:00
loginfo - > start_time = loginfo - > start_time - utc_or_beijing ; //下发utc时间需要减去8小时-秒
2025-07-28 15:23:13 +08:00
loginfo - > end_time = loginfo - > end_time - utc_or_beijing ;
/////////////////////////////////////////////////////
2025-01-16 16:17:01 +08:00
if ( loginfo - > need_steady = = 0 & & loginfo - > need_voltage = = 0 )
continue ;
if ( loginfo - > end_time < = loginfo - > start_time )
continue ;
printf ( " start mms_jread................................ \n " ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_msg6 ( " \n mms_jread IED_ID=%d ,CPU=%d ,domain: %s ,logName: %s ,ip: %s,chnl_id: %d \n " ,
LD_info - > ied - > id , LD_info - > cpuno , LD_info - > LD_name , loginfo - > logName , chnl_usr - > ip_str , chnl_usr - > chnl_id ) ;
2025-04-29 15:05:36 +08:00
2025-05-26 16:51:27 +08:00
//mq日志
2025-07-24 16:14:00 +08:00
//DIY_WARNLOG(full_key_m_c,"【WARN】监测点:%s - id:%s开始补招数据", LD_info->name,LD_info->mp_id);
2025-05-26 16:51:27 +08:00
2025-01-16 16:17:01 +08:00
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 ) ;
if ( ret ! = SD_SUCCESS ) {
echo_warn6 ( " \n mms_jread Failed! IED_ID=%d ,CPU=%d ,domain: %s ,logName: %s ,ip: %s,chnl_id: %d \n " ,
LD_info - > ied - > id , LD_info - > cpuno , LD_info - > LD_name , loginfo - > logName , chnl_usr - > ip_str , chnl_usr - > chnl_id ) ;
2025-05-26 16:51:27 +08:00
//mq日志
2025-07-24 16:14:00 +08:00
DIY_ERRORLOG ( full_key_m_c , " 【ERROR】监测点:%s - id:%s补招数据失败 - 失败时间点:%lld 至 %lld " , LD_info - > name , LD_info - > mp_id , loginfo - > start_time , loginfo - > end_time ) ;
2025-05-26 16:51:27 +08:00
2025-01-16 16:17:01 +08:00
failed_count + + ;
}
del_mvl_type_ctrl ( ) ;
loginfo - > need_steady = 0 ;
loginfo - > need_voltage = 0 ;
loginfo - > start_time = loginfo - > end_time ;
g_dead_lock_counter = 0 ;
2025-05-09 16:53:07 +08:00
g_thread_blocked_times = 0 ; //防止补招时间过长导致进程退出
2025-01-16 16:17:01 +08:00
now = sGetMsTime ( ) ;
last_check_recall_config_time = now ;
printf ( " end ==============%.2f================ \n " , last_check_recall_config_time ) ;
printf ( " end mms_jread................................ \n " ) ;
}
2025-07-24 16:14:00 +08:00
//不管是否成功, 这个补招文件必须删除, 可能出现一直失败, 循环读取文件和循环补招导致程序崩溃202050724lnk
//if (failed_count==0) {//成功
2025-01-16 16:17:01 +08:00
Delete_recall_Xml ( LD_info - > mp_id ) ;
2025-07-28 15:23:13 +08:00
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s结束补招数据 " , LD_info - > name , LD_info - > mp_id ) ;
2025-07-24 16:14:00 +08:00
//}
2025-01-16 16:17:01 +08:00
}
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
}
}
void process_3s_config ( trigger_3s_xml_t * trigger_3s_xml )
{
int i , j ;
trigger_t * trigger ;
trigger_t * trigger_work ;
int trigger_num ;
ied_t * ied ;
LD_info_t * LD_info ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
int need_write_file ;
int new_in_work_found ;
printf ( " start process_3s_config \n " ) ;
need_write_file = FALSE ;
2025-05-09 16:53:07 +08:00
trigger = trigger_3s_xml - > new_triggers ; //3s配置文件中的newtrigger数组, 如果没有newtrigger这里就是0
2025-01-16 16:17:01 +08:00
trigger_num = trigger_3s_xml - > new_trigger_num ;
for ( i = 0 ; i < trigger_num ; i + + ) {
new_in_work_found = FALSE ;
for ( j = 0 ; j < trigger_3s_xml - > work_trigger_num ; j + + ) {
trigger_work = & trigger_3s_xml - > work_triggers [ j ] ;
if ( trigger_work - > dev_idx = = trigger [ i ] . dev_idx & & trigger_work - > line_id = = trigger [ i ] . line_id ) {
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( trigger [ i ] . real_data > = 0 )
2025-05-09 16:53:07 +08:00
trigger_work - > real_data = trigger [ i ] . real_data ; //更新rtdata标志
2025-01-16 16:17:01 +08:00
if ( trigger [ i ] . soe_data > = 0 )
2025-05-09 16:53:07 +08:00
trigger_work - > soe_data = trigger [ i ] . soe_data ; //更新soe标志
2025-01-16 16:17:01 +08:00
trigger_work - > limit = trigger [ i ] . limit ;
2025-05-09 16:53:07 +08:00
clear_rpt_counter_by_trigger ( trigger_work ) ; //清理报告
2025-01-16 16:17:01 +08:00
new_in_work_found = TRUE ;
}
}
2025-05-09 16:53:07 +08:00
if ( ! new_in_work_found ) { //newtrigger为0, 这是全新的触发, 不是正在工作的触发
2025-01-16 16:17:01 +08:00
clear_rpt_counter_by_trigger ( & trigger [ i ] ) ;
if ( trigger [ i ] . real_data < 0 )
trigger [ i ] . real_data = 0 ;
if ( trigger [ i ] . soe_data < 0 )
trigger [ i ] . soe_data = 0 ;
trigger_3s_xml - > work_triggers [ trigger_3s_xml - > work_trigger_num + + ] = trigger [ i ] ;
}
2025-05-09 16:53:07 +08:00
need_write_file = TRUE ; //需要将新增的点写到文件中
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
trigger = trigger_3s_xml - > delete_triggers ; //如果没有deletetrigger这里就是0
2025-01-16 16:17:01 +08:00
trigger_num = trigger_3s_xml - > delete_trigger_num ;
for ( i = 0 ; i < trigger_num ; i + + ) {
for ( j = 0 ; j < trigger_3s_xml - > work_trigger_num ; j + + ) {
trigger_work = & trigger_3s_xml - > work_triggers [ j ] ;
if ( trigger_work - > dev_idx = = trigger [ i ] . dev_idx & & trigger_work - > line_id = = trigger [ i ] . line_id ) {
clear_rpt_counter_by_trigger ( trigger_work ) ;
trigger_work - > dev_idx = INVALID_DEV_IDX ;
}
}
need_write_file = TRUE ;
}
2025-05-09 16:53:07 +08:00
trigger = trigger_3s_xml - > modify_triggers ; //如果没有modifytrigger这里就是0
2025-01-16 16:17:01 +08:00
trigger_num = trigger_3s_xml - > modify_trigger_num ;
for ( i = 0 ; i < trigger_num ; i + + ) {
for ( j = 0 ; j < trigger_3s_xml - > work_trigger_num ; j + + ) {
trigger_work = & trigger_3s_xml - > work_triggers [ j ] ;
if ( trigger_work - > dev_idx = = trigger [ i ] . dev_idx & & trigger_work - > line_id = = trigger [ i ] . line_id ) {
* trigger_work = trigger [ i ] ;
clear_rpt_counter_by_trigger ( trigger_work ) ;
}
}
need_write_file = TRUE ;
}
2025-05-09 16:53:07 +08:00
clear_all_LD_real_soe_report_shoud_register ( ) ; //清空所有需要注册的报告, 根据实时配置文件来。这里使LD_info->real_data = 0;LD_info->soe_data = 0;就不会触发报告
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
trigger = trigger_3s_xml - > work_triggers ; //文件的work块
2025-01-16 16:17:01 +08:00
trigger_num = trigger_3s_xml - > work_trigger_num ;
2025-05-09 16:53:07 +08:00
for ( i = 0 ; i < trigger_num ; i + + ) { //遍历work块中所有触发点
int real_report_count = 0 ; //实时报告数量
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
if ( trigger [ i ] . dev_idx = = INVALID_DEV_IDX ) { //跳过错误的终端号
2025-01-16 16:17:01 +08:00
printf ( " dev_idx incaild \n " ) ;
continue ;
}
2025-05-09 16:53:07 +08:00
ied = find_ied_from_dev_idx ( trigger [ i ] . dev_idx ) ; //通过文件中的dev号找到配置的设备, 找不到说明不在这个进程里跳过( 多进程的实现是否有必要? 如果要实现就得每个进程一个操作目录)
2025-01-16 16:17:01 +08:00
if ( ! ied ) {
printf ( " can't find ied by dev_idx \n " ) ;
continue ;
}
2025-05-09 16:53:07 +08:00
LD_info = find_LD_info_from_line_id ( ied , trigger [ i ] . line_id ) ; //用文件中的检测点号找到配置的监测点
2025-01-16 16:17:01 +08:00
if ( ! LD_info ) {
printf ( " can't find line by line_idx \n " ) ;
continue ;
}
2025-05-09 16:53:07 +08:00
real_report_count = get_real_report_count ( LD_info ) ; //获取监测点的实时报告数量LD_info->rptinfo[rpt_no]->count
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//调试用
2025-01-16 16:17:01 +08:00
printf ( " terminal:%s - mp:%s real_report_count %d \n " , ( ( ied_usr_t * ) ( ied - > usr_ext ) ) - > terminal_id , LD_info - > mp_id , real_report_count ) ;
2025-05-09 16:53:07 +08:00
trigger [ i ] . count = real_report_count ; //记录此时这个监测点的实时报告数量
if ( trigger [ i ] . real_data & & trigger [ i ] . limit & & ( real_report_count > trigger [ i ] . limit ) ) { //监测点的实时报告数量大于当前文件中的限制,这个监测点的数据清零不再触发
2025-01-16 16:17:01 +08:00
trigger [ i ] . real_data = 0 ;
trigger [ i ] . limit = 0 ;
trigger [ i ] . count = 0 ;
need_write_file = TRUE ;
}
2025-05-09 16:53:07 +08:00
LD_info - > real_data = trigger [ i ] . real_data ; //根据文件中的配置来设置,然后在报告触发中触发实时报告
2025-01-16 16:17:01 +08:00
LD_info - > soe_data = trigger [ i ] . soe_data ;
LD_info - > limit = trigger [ i ] . limit ;
LD_info - > count = trigger [ i ] . count ;
2025-05-09 16:53:07 +08:00
if ( LD_info - > limit > 0 ) //限制数更新记录
2025-01-16 16:17:01 +08:00
need_write_file = TRUE ;
2025-05-09 16:53:07 +08:00
if ( trigger [ i ] . real_data = = 0 & & trigger [ i ] . soe_data = = 0 ) //不触发条件记录
2025-01-16 16:17:01 +08:00
need_write_file = TRUE ;
}
if ( need_write_file )
2025-05-09 16:53:07 +08:00
create_3s_xml ( trigger_3s_xml ) ; //写入文件的work块
2025-01-16 16:17:01 +08:00
}
void del_process_recall_config ( recall_xml_t * recall_xml )
{
int i , j ;
recall_t * recall ;
recall_t * recall_work ;
int recall_num ;
ied_t * ied ;
LD_info_t * LD_info ;
loginfo_t * loginfo = NULL ;
int need_write_file ;
need_write_file = FALSE ;
recall = recall_xml - > new_recalls ;
recall_num = recall_xml - > new_recall_num ;
for ( i = 0 ; i < recall_num ; i + + ) {
recall_xml - > work_recalls [ recall_xml - > work_recall_num + + ] = recall [ i ] ;
need_write_file = TRUE ;
}
recall = recall_xml - > work_recalls ;
recall_num = recall_xml - > work_recall_num ;
for ( i = 0 ; i < recall_num ; i + + ) {
LD_info = find_LD_info_only_from_line_id ( recall [ i ] . line_id ) ;
if ( ! LD_info )
continue ;
if ( LD_info - > logcount < = 0 )
continue ;
loginfo = LD_info - > loginfo [ 0 ] ;
loginfo - > need_steady = recall [ i ] . need_steady ;
loginfo - > need_voltage = recall [ i ] . need_voltage ;
loginfo - > start_time = recall [ i ] . start_time ;
loginfo - > end_time = recall [ i ] . end_time ;
}
}
void check_3s_config ( )
{
double now ;
2025-05-09 16:53:07 +08:00
static double last_check_3s_config_time = 0.0 ; //初始化时间
trigger_3s_xml_t trigger_3s_xml ; //3s触发文件
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
if ( ! three_secs_enabled ) //cfg_3s_data进程才会开启
2025-01-16 16:17:01 +08:00
return ;
2025-05-09 16:53:07 +08:00
now = sGetMsTime ( ) ; //当前时间
if ( fabs ( now - last_check_3s_config_time ) < 3 * 1000 ) //wait 3secs //当前进程任务执行时查看当前时间和上次执行时间间隔, 小于3秒不执行, 大于等于3秒往下执行
2025-01-16 16:17:01 +08:00
return ;
2025-05-28 16:09:15 +08:00
//调试用
//printf("begin 3s config...\n");
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
last_check_3s_config_time = now ; //记录本次运行时间
2025-05-20 16:31:12 +08:00
while ( APR_SUCCESS = = parse_3s_xml ( & trigger_3s_xml ) ) { //处理3秒文件, 一次处理一个
2025-05-09 16:53:07 +08:00
//处理实时触发加台账锁lnk20250114
2025-02-24 16:45:42 +08:00
//pthread_mutex_lock(&mtx); printf("3s hold lock !!!!!!!!!!!");
2025-05-09 16:53:07 +08:00
process_3s_config ( & trigger_3s_xml ) ; //根据文件处理数据
2025-04-29 15:05:36 +08:00
//pthread_mutex_unlock(&mtx); printf("3s free lock !!!!!!!!!!!");
2025-01-16 16:17:01 +08:00
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2025-05-09 16:53:07 +08:00
//lnk20250114参照实时数据方法处理台账信息
2025-03-13 16:35:19 +08:00
int isValidModelId ( const char * model_id ) {
size_t i ;
2025-05-12 16:43:42 +08:00
if ( model_id = = NULL )
{
printf ( " !!!model_id null!!! \n " ) ;
return 0 ;
} // NULL 无效
2025-03-13 16:35:19 +08:00
size_t len = strlen ( model_id ) ;
2025-05-12 16:43:42 +08:00
if ( len < 4 ) {
printf ( " !!!model_id length < 4!!! \n " ) ;
return 0 ; // 长度 < 4 无效
}
2025-03-13 16:35:19 +08:00
2025-05-09 16:53:07 +08:00
// 检查是否全是空格
2025-03-13 16:35:19 +08:00
for ( i = 0 ; i < len ; i + + ) {
if ( ! isspace ( ( unsigned char ) model_id [ i ] ) ) {
2025-05-09 16:53:07 +08:00
return 1 ; // 只要包含非空格字符,就是合法的
2025-03-13 16:35:19 +08:00
}
}
2025-05-12 16:43:42 +08:00
printf ( " !!!model_id only space!!! \n " ) ;
2025-05-09 16:53:07 +08:00
return 0 ; // 仅包含空格,无效
2025-03-13 16:35:19 +08:00
}
2025-01-16 16:17:01 +08:00
void process_ledger_update ( trigger_update_xml_t * ledger_update_xml )
{
int i , j ;
terminal * update ;
terminal * update_work ;
int update_num ;
ied_t * ied ;
LD_info_t * LD_info ;
int new_in_work_found ;
ied_usr_t * ied_usr ;
2025-01-17 17:10:18 +08:00
int chnl_no ;
chnl_usr_t * chnl_usr = NULL ;
2025-01-16 16:17:01 +08:00
printf ( " !!!start update ledger!!! \n " ) ;
2025-05-09 16:53:07 +08:00
update = ledger_update_xml - > new_updates ; //处理新增台账部分
2025-01-16 16:17:01 +08:00
update_num = ledger_update_xml - > new_update_num ;
printf ( " add ledger num:%d \n " , update_num ) ;
2025-05-09 16:53:07 +08:00
for ( i = 0 ; i < update_num ; i + + ) { //查看所有需要新增的台账
2025-01-16 16:17:01 +08:00
new_in_work_found = FALSE ;
2025-01-16 19:16:26 +08:00
if ( update [ i ] . terminal_id ! = NULL ) {
2025-01-23 16:32:26 +08:00
printf ( " add ledger of %s \n " , update [ i ] . terminal_id ) ;
2025-05-09 16:53:07 +08:00
ied = find_ied_from_terminal_id ( update [ i ] . terminal_id ) ; //通过文件中的终端号找到配置的设备
2025-01-16 19:16:26 +08:00
if ( ied ) {
printf ( " find ied by terminal_id, terminal already exsist \n " ) ;
2025-05-09 16:53:07 +08:00
new_in_work_found = TRUE ; //当前运行的台账中找到已有台账,变为更新
2025-01-16 19:16:26 +08:00
2025-05-09 16:53:07 +08:00
// 将当前终端从 new_updates 数组中移到 modify_updates 数组
2025-01-16 19:16:26 +08:00
if ( ledger_update_xml - > modify_update_num < MAX_UPDATEA_NUM ) {
2025-05-09 16:53:07 +08:00
// 添加到 modify_updates 数组
2025-01-16 19:16:26 +08:00
ledger_update_xml - > modify_updates [ ledger_update_xml - > modify_update_num ] = update [ i ] ;
2025-05-09 16:53:07 +08:00
ledger_update_xml - > modify_update_num + + ; // 更新 modify 数组的计数器
2025-01-16 19:16:26 +08:00
2025-05-09 16:53:07 +08:00
// 删除该终端(从 new_updates 数组中移除)
2025-01-16 19:16:26 +08:00
for ( j = i ; j < ledger_update_xml - > new_update_num - 1 ; j + + ) {
2025-05-09 16:53:07 +08:00
ledger_update_xml - > new_updates [ j ] = ledger_update_xml - > new_updates [ j + 1 ] ; // 向前移动元素
2025-01-16 19:16:26 +08:00
}
2025-05-09 16:53:07 +08:00
ledger_update_xml - > new_update_num - - ; // 更新 new_update_num, 减少一个元素
2025-01-16 19:16:26 +08:00
continue ;
} else {
fprintf ( stderr , " Exceeded MAX_UPDATEA_NUM limit for modify_updates! \n " ) ;
}
}
}
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
if ( ! new_in_work_found ) { //这是全新的台账,在台账数组中没有包含这个设备
2025-01-16 16:17:01 +08:00
2025-01-21 17:48:37 +08:00
int terminal_index ;
2025-05-09 16:53:07 +08:00
int ied_take = 0 ; //当前台账数组里有不使用的ied空间? 0没有, 1有
//进行台账添加和初始化操作
//1-申请新的内存空间//////////////////////////////
//新的台账数量 (n_clients) 和原有的台账数量 (原数量为 g_node->n_clients)
int new_client_count = g_node - > n_clients + 1 ; // 增加一个新的台账
//判断新增进程后是否超过原有的台账数组, 如果超过了就从不使能的ied空间中找可用空间, 如果还是没有那就提示不能荷载更多终端
if ( new_client_count > IED_COUNT ) { //不更新台账数量
2025-01-21 17:48:37 +08:00
ied_t * ied_unused = NULL ;
ied_usr_t * ied_usr_unused = NULL ;
2025-05-09 16:53:07 +08:00
ied_unused = find_ied_unused ( ) ; //遍历g_node找到第一个不使用的ied, 这个ied之前初始化时分配过空间, 直接占用
2025-01-21 17:48:37 +08:00
if ( ied_unused ! = NULL ) {
ied_usr_unused = ( ied_usr_t * ) ied_unused - > usr_ext ;
2025-05-09 16:53:07 +08:00
ied = ied_unused ; //新增的ied指向已有的未使用的ied空间
terminal_index = ied_usr_unused - > dev_idx ; //记录这个ied的编号, 即g_node的下标
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//打印提示
2025-01-22 17:00:34 +08:00
printf ( " !!!!!!!!ied index:%d ,origin terminal_id:%s has been taken!!!!!!!!!! \n " , ied_usr_unused - > dev_idx , ied_usr_unused - > terminal_id ) ;
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//终端初始化,不需要再申请空间
2025-01-21 17:48:37 +08:00
ied_usr = ( ied_usr_t * ) ied - > usr_ext ;
ied_usr - > last_call_wavelist_time = sGetMsTime ( ) + g_pt61850app - > giTime * 1000 ;
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
ied_usr - > dev_flag = ENABLE ; //终端有效
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
ied - > chncount = 1 ; //通信端口数
//不再分配通道空间
ied - > channel [ 0 ] . ied = ied ; //通道的所属设备
ied - > channel [ 0 ] . status = STATUS_BREAKOFF ; //初始化为通信中断
ied - > cpucount = 0 ; //监测点数初始为0, 读取监测点台账时写入
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
ied_take = 1 ; //ied之前存在
2025-01-21 17:48:37 +08:00
}
2025-05-09 16:53:07 +08:00
else { //在已有的全部台账中都没找到不使用的ied, 说明这个进程可挂的台账满了, 不再处理
2025-01-21 17:48:37 +08:00
printf ( " !!!!!!!!!!ledger array is full!!!!!! \n " ) ;
2025-05-09 16:53:07 +08:00
//添加mq响应台账添加失败: 台账挂满
//update[i].guid
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
sprintf ( msg , " 终端 id: %s 台账更新失败, 这个进程的台账空间已满,达到了配置台账数量的最大值 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-05-09 16:53:07 +08:00
2025-01-21 17:48:37 +08:00
return ;
}
2025-05-09 16:53:07 +08:00
} //新台账数量小于等于设定的台账数量
2025-01-22 17:00:34 +08:00
else {
2025-02-11 18:23:19 +08:00
2025-05-09 16:53:07 +08:00
//调试用
2025-02-11 18:23:19 +08:00
printf ( " !!!!!!!!!!gnodeindex:%d!!!!!! \n " , new_client_count - 1 ) ;
2025-05-09 16:53:07 +08:00
// 新增的台账在已有的台账数组中记录
2025-01-21 17:48:37 +08:00
g_node - > clients [ new_client_count - 1 ] = ( ied_t * ) apr_pcalloc ( g_cfg_pool , sizeof ( ied_t ) ) ;
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
// 更新台账数量
g_node - > n_clients = new_client_count ; // 更新台账数量
//1-申请新的内存空间//////////////////////////////
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
//2-处理终端台账///////////////////////////////////
ied = g_node - > clients [ new_client_count - 1 ] ; //终端台账指针定向到ied数组当前位置的后一位
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
terminal_index = new_client_count ; //新的台账终端
2025-01-21 17:48:37 +08:00
ied_usr = ( ied_usr_t * ) apr_pcalloc ( g_init_pool , sizeof ( ied_usr_t ) ) ;
2025-05-09 16:53:07 +08:00
ied - > usr_ext = ied_usr ; //内存挂到ied上
2025-05-12 16:43:42 +08:00
if ( ied_usr = = NULL ) {
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账更新失败,没有找到台账的终端空间 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
return ;
}
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
ied_usr - > last_call_wavelist_time = sGetMsTime ( ) + g_pt61850app - > giTime * 1000 ; //从FeProject/子功能目录/etc/pt61850netd_pqfe.xml中读取的总查询时间
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
ied_usr - > LD_info = ( LD_info_t * ) apr_pcalloc ( g_init_pool , MAX_CPUNO * sizeof ( LD_info_t ) ) ; //内存挂到ied上
2025-05-12 16:43:42 +08:00
if ( ied_usr - > LD_info = = NULL ) {
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账更新失败,没有找到台账的监测点空间 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
return ;
}
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
ied_usr - > dev_flag = ENABLE ; //终端有效
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
ied - > chncount = 1 ; //通信端口数,一个终端一般只有一个
ied - > channel = ( channel_t * ) apr_pcalloc ( g_cfg_pool , sizeof ( channel_t ) * ied - > chncount ) ; //内存挂到ied上
ied - > channel [ 0 ] . ied = ied ; //通道的所属设备
ied - > channel [ 0 ] . status = STATUS_BREAKOFF ; //初始化为通信中断
ied - > cpucount = 0 ; //监测点数初始为0, 读取监测点台账时写入
//2-处理终端台账///////////////////////////////////
2025-01-21 17:48:37 +08:00
}
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//3-写入台账内容//////////////////////////////
2025-01-21 17:48:37 +08:00
int ret = update_one_terminal_ledger ( update , i , ied , terminal_index , ied_take ) ;
2025-01-17 17:10:18 +08:00
if ( ret ) {
printf ( " ledger can not be update!!!!!quit process!!!!! \n " ) ;
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账更新失败,无法写入台账 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-07-01 18:40:05 +08:00
clearIed ( ied ) ; //添加失败清空整个ied
return ;
2025-01-17 17:10:18 +08:00
}
2025-05-09 16:53:07 +08:00
//3-写入台账内容///////////////////////////////////
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//4-配置映射文件//////////////////////////////
2025-07-01 18:40:05 +08:00
char model [ 64 ] = { 0 } ;
2025-05-09 16:53:07 +08:00
// 获取模型ID, 检查是否返回 NULL
2025-05-14 16:42:29 +08:00
parse_model_cfg_web_one ( ied , & model ) ; //存储在/FeProject/dat/
2025-01-17 17:10:18 +08:00
2025-05-12 16:43:42 +08:00
if ( isValidModelId ( model ) ) { //lnk20250313防止拿不到映射文件
2025-05-09 16:53:07 +08:00
// 安全拷贝字符串到 model 数组
2025-05-12 16:43:42 +08:00
strncpy ( model , model , sizeof ( model ) - 1 ) ;
2025-05-09 16:53:07 +08:00
model [ sizeof ( model ) - 1 ] = ' \0 ' ; // 确保以 null 结尾
2025-01-17 17:10:18 +08:00
printf ( " ledger Model ID: %s \n " , model ) ;
} else {
2025-03-13 16:35:19 +08:00
printf ( " ledger No model ID found.quit \n " ) ;
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账更新失败,没有找到装置型号 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-07-01 18:40:05 +08:00
clearIed ( ied ) ; //添加失败清空整个ied
2025-03-13 16:35:19 +08:00
return ;
2025-01-17 17:10:18 +08:00
}
char full_path [ 128 ] ;
2025-05-09 16:53:07 +08:00
snprintf ( full_path , sizeof ( full_path ) , " /FeProject/dat/%s.xml " , model ) ; // 拼接路径
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
// 打印模型路径
2025-01-17 17:10:18 +08:00
printf ( " ledger icd config file full path: %s \n " , full_path ) ;
2025-05-09 16:53:07 +08:00
//映射文件解析
2025-01-17 17:10:18 +08:00
Set_xml_nodeinfo_one ( ied_usr - > dev_type ) ;
2025-05-09 16:53:07 +08:00
//4-配置映射文件///////////////////////////////////
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//5-报告块初始化//////////////////////////////
2025-01-22 17:00:34 +08:00
parse_rpt_log_ini_one ( ied ) ;
2025-05-09 16:53:07 +08:00
//5-报告块初始化///////////////////////////////////
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//调试
2025-02-11 18:23:19 +08:00
printf ( " ledger id: %s \n " , ( ( ied_usr_t * ) ied - > channel [ 0 ] . ied - > usr_ext ) - > terminal_id ) ;
2025-01-16 16:17:01 +08:00
//6-init_rem_dib_table//////////////////////////////
2025-02-07 16:46:53 +08:00
init_rem_dib_table_one ( ied ) ;
2025-01-16 16:17:01 +08:00
//6-init_rem_dib_table///////////////////////////////////
2025-05-09 16:53:07 +08:00
//7启动终端日志
init_loggers_bydevid ( ( ( ied_usr_t * ) ied - > channel [ 0 ] . ied - > usr_ext ) - > terminal_id ) ;
//8响应添加成功
//update[i].guid
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账添加成功 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-01-16 16:17:01 +08:00
}
}
2025-01-17 17:10:18 +08:00
//////////////////////////////////////////////////////////////////////////////modify
2025-05-09 16:53:07 +08:00
update = ledger_update_xml - > modify_updates ; //处理修改台账部分
2025-01-21 17:48:37 +08:00
update_num = ledger_update_xml - > modify_update_num ;
2025-01-17 17:10:18 +08:00
printf ( " modify ledger num:%d \n " , update_num ) ;
2025-05-09 16:53:07 +08:00
for ( i = 0 ; i < update_num ; i + + ) { //查看所有需要新增的台账
2025-01-17 17:10:18 +08:00
new_in_work_found = FALSE ;
if ( update [ i ] . terminal_id ! = NULL ) {
2025-01-23 16:32:26 +08:00
printf ( " modify ledger of %s \n " , update [ i ] . terminal_id ) ;
2025-05-09 16:53:07 +08:00
ied = find_ied_from_terminal_id ( update [ i ] . terminal_id ) ; //通过文件中的终端号找到配置的设备
2025-01-17 17:10:18 +08:00
if ( ied ) {
printf ( " find ied by terminal_id, terminal already exsist \n " ) ;
2025-05-09 16:53:07 +08:00
new_in_work_found = TRUE ; //当前运行的台账中找到已有台账,更新它
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//关闭这个终端的所有连接//////////////////////////////////////////////////////////////////////
2025-01-17 17:10:18 +08:00
for ( chnl_no = 0 ; chnl_no < ied - > chncount ; chnl_no + + ) {
chnl_usr = ( chnl_usr_t * ) ied - > channel [ chnl_no ] . connect ;
2025-05-09 16:53:07 +08:00
if ( chnl_usr - > m_state ! = CHANNEL_CONNECTED ) { //跳过未连接的通道
2025-01-17 17:10:18 +08:00
continue ;
}
2025-05-09 16:53:07 +08:00
closeChannel ( chnl_usr ) ; //关闭更新台账后,任务会自动连接
2025-01-17 17:10:18 +08:00
}
2025-05-09 16:53:07 +08:00
//更新数据/////////////////////////////////////////////////////////////////////////////////
//3-写入台账内容//////////////////////////////
2025-01-17 17:10:18 +08:00
ied_usr = ied - > usr_ext ;
2025-02-07 16:46:53 +08:00
2025-05-09 16:53:07 +08:00
//清空logger
remove_loggers_by_terminal_id ( update [ i ] . terminal_id ) ;
//写入前先清空已有数据
clearIedUsr ( ied_usr ) ; //不会清空dev_idx
2025-02-07 16:46:53 +08:00
2025-05-09 16:53:07 +08:00
//ied_usr->last_call_wavelist_time = sGetMsTime() + g_pt61850app->giTime * 1000;//从FeProject/子功能目录/etc/pt61850netd_pqfe.xml中读取的总查询时间
2025-02-13 11:51:05 +08:00
2025-05-09 16:53:07 +08:00
ied_usr - > dev_flag = ENABLE ; //终端有效
2025-02-13 11:51:05 +08:00
2025-05-09 16:53:07 +08:00
int ret = update_one_terminal_ledger ( update , i , ied , ied_usr - > dev_idx , 1 ) ; //1: 更新已有的ied
2025-01-17 17:10:18 +08:00
if ( ret ) {
printf ( " ledger can not be update!!!!!quit process!!!!! \n " ) ;
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账更新失败,台账无法写入 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-07-01 18:40:05 +08:00
clearIed ( ied ) ; //添加失败清空整个ied
2025-05-12 16:43:42 +08:00
return ;
2025-01-17 17:10:18 +08:00
}
2025-05-09 16:53:07 +08:00
//3-写入台账内容////////////////////////////////////////////
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//4-配置映射文件///////////////////////////////////////////
2025-01-17 17:10:18 +08:00
char model [ 64 ] = { 0 } ;
2025-05-09 16:53:07 +08:00
// 获取模型ID, 检查是否返回 NULL
2025-05-14 16:42:29 +08:00
parse_model_cfg_web_one ( ied , & model ) ; //存储在/FeProject/dat/
2025-01-17 17:10:18 +08:00
2025-05-12 16:43:42 +08:00
if ( isValidModelId ( model ) ) {
2025-05-09 16:53:07 +08:00
// 安全拷贝字符串到 model 数组
2025-05-12 16:43:42 +08:00
strncpy ( model , model , sizeof ( model ) - 1 ) ;
2025-05-09 16:53:07 +08:00
model [ sizeof ( model ) - 1 ] = ' \0 ' ; // 确保以 null 结尾
2025-01-17 17:10:18 +08:00
printf ( " ledger Model ID: %s \n " , model ) ;
} else {
printf ( " ledger No model ID found. \n " ) ;
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账更新失败,没有找到装置型号 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-07-01 18:40:05 +08:00
clearIed ( ied ) ; //添加失败清空整个ied
2025-05-12 16:43:42 +08:00
return ;
2025-01-17 17:10:18 +08:00
}
char full_path [ 128 ] ;
2025-05-09 16:53:07 +08:00
snprintf ( full_path , sizeof ( full_path ) , " /FeProject/dat/%s.xml " , model ) ; // 拼接路径
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
// 打印模型路径
2025-01-17 17:10:18 +08:00
printf ( " ledger icd config file full path: %s \n " , full_path ) ;
2025-05-09 16:53:07 +08:00
//映射文件解析
2025-01-17 17:10:18 +08:00
Set_xml_nodeinfo_one ( ied_usr - > dev_type ) ;
2025-05-09 16:53:07 +08:00
//4-配置映射文件///////////////////////////////////
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//5-报告块初始化//////////////////////////////
2025-02-07 16:46:53 +08:00
parse_rpt_log_ini_one ( ied ) ;
2025-05-09 16:53:07 +08:00
//5-报告块初始化///////////////////////////////////
2025-01-17 17:10:18 +08:00
//6-init_rem_dib_table//////////////////////////////
2025-02-07 16:46:53 +08:00
init_rem_dib_table_one ( ied ) ;
2025-01-17 17:10:18 +08:00
//6-init_rem_dib_table///////////////////////////////////
2025-05-09 16:53:07 +08:00
//更新数据//////////////////////////////////////////////////////////////////////
//7启动终端日志
init_loggers_bydevid ( ( ( ied_usr_t * ) ied - > channel [ 0 ] . ied - > usr_ext ) - > terminal_id ) ;
//8响应添加成功
//update[i].guid
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账修改成功 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-01-16 16:17:01 +08:00
}
2025-01-17 17:10:18 +08:00
}
if ( ! new_in_work_found ) {
printf ( " modify_updates can not find ied!!!!!! \n " ) ;
2025-05-09 16:53:07 +08:00
//添加mq响应台账添加失败: 台账找不到
//update[i].guid
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
sprintf ( msg , " 终端 id: %s 台账修改失败, 无法找到这个终端 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-01-17 17:10:18 +08:00
}
}
///////////////////////////////////////////////////////////////////////////////delete
2025-05-09 16:53:07 +08:00
update = ledger_update_xml - > delete_updates ; //处理删除台账部分
update_num = ledger_update_xml - > delete_update_num ; //删除的数量
2025-01-17 17:10:18 +08:00
printf ( " delete ledger num:%d \n " , update_num ) ;
2025-01-23 16:32:26 +08:00
2025-05-09 16:53:07 +08:00
for ( i = 0 ; i < update_num ; i + + ) { //查看所有需要删除的台账
new_in_work_found = FALSE ; //找到现存台账的标志
if ( update [ i ] . terminal_id ! = NULL ) { //处理非空台账
2025-01-23 16:32:26 +08:00
printf ( " delete ledger of %s \n " , update [ i ] . terminal_id ) ;
2025-05-09 16:53:07 +08:00
ied = find_ied_from_terminal_id ( update [ i ] . terminal_id ) ; //通过文件中的终端号找到配置的设备,没找到就不处理
2025-01-17 17:10:18 +08:00
if ( ied ) {
printf ( " find ied by terminal_id, terminal already exsist \n " ) ;
2025-05-09 16:53:07 +08:00
new_in_work_found = TRUE ; //当前运行的台账中找到已有台账,更新它
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//关闭这个终端的所有连接//////////////////////////////////////////////////////////////////////
2025-01-17 17:10:18 +08:00
for ( chnl_no = 0 ; chnl_no < ied - > chncount ; chnl_no + + ) {
chnl_usr = ( chnl_usr_t * ) ied - > channel [ chnl_no ] . connect ;
2025-05-09 16:53:07 +08:00
if ( chnl_usr - > m_state ! = CHANNEL_CONNECTED ) { //跳过没连接的通道,一般一个终端只有一个
2025-01-17 17:10:18 +08:00
continue ;
}
2025-05-09 16:53:07 +08:00
closeChannel ( chnl_usr ) ; //关闭更新台账后, 如果是删除则不会再连接, 关闭连接时这个ied的报告会被清除, 报告控制会被注销
2025-01-17 17:10:18 +08:00
}
2025-05-09 16:53:07 +08:00
//更新数据//////////////////////////////////////////////////////////////////////
//3-删除台账内容//////////////////////////////
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//调试用
// 假设要删除 g_node->clients 中的某个 ied, index 为删除的索引
2025-01-17 17:10:18 +08:00
int index_to_remove = 0 ;
ied_t * ied_find = NULL ;
int iedno ;
2025-05-09 16:53:07 +08:00
ied_usr_t * ied_usr_find = NULL ; //遍历的ied
ied_usr = ( ied_usr_t * ) ied - > usr_ext ; //要删除的ied
2025-01-17 17:10:18 +08:00
for ( iedno = 0 ; iedno < g_node - > n_clients ; iedno + + ) {
ied_find = g_node - > clients [ iedno ] ;
ied_usr_find = ( ied_usr_t * ) ied_find - > usr_ext ;
if ( ied_usr_find & & strcmp ( ied_usr_find - > terminal_id , ied_usr - > terminal_id ) = = 0 ) {
2025-05-09 16:53:07 +08:00
index_to_remove = iedno ; //找到要删除的ied在g_node中的位置
break ; //找到退出
2025-01-17 17:10:18 +08:00
}
}
2025-01-21 17:48:37 +08:00
2025-05-09 16:53:07 +08:00
// 先清理要删除的 ied 的内容
ied_t * ied_to_remove = g_node - > clients [ index_to_remove ] ; //指向g_node对应的内存区
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
if ( ied_to_remove = = ied ) { //通过终端id找到的ied应该也指向g_node对应的内存区
2025-01-21 17:48:37 +08:00
printf ( " this ied is ied_to_remove \n " ) ;
}
2025-05-09 16:53:07 +08:00
//调试用
//清空logger
remove_loggers_by_terminal_id ( update [ i ] . terminal_id ) ;
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//清空ied的内容
2025-02-07 16:46:53 +08:00
clearIed ( ied_to_remove ) ;
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//3-删除台账内容///////////////////////////////////
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//4-配置映射文件//////////////////////////////
//映射文件保留, 如果再次添加这个ied, 如果是相同的映射文件则可以直接加载
//4-配置映射文件///////////////////////////////////
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//5-报告块//////////////////////////////
//关闭连接时这个ied的报告已清空。报告控制块保留, 因为报告控制块是根据设备类型设置的, 如果删除会影响其他同类型的ied。这个ied对应的控制块在清空内容时已清空
//5-报告块///////////////////////////////////
2025-01-17 17:10:18 +08:00
//6-init_rem_dib_table//////////////////////////////
2025-05-09 16:53:07 +08:00
//rem_dib_table的内容将会被保留, 如果有新的台账使用这个位置, 将会直接覆盖
2025-01-17 17:10:18 +08:00
//6-init_rem_dib_table///////////////////////////////////
2025-05-09 16:53:07 +08:00
//更新数据//////////////////////////////////////////////////////////////////////
//7响应添加成功
2025-05-12 16:43:42 +08:00
//update[i].guid
char msg [ 256 ] ;
snprintf ( msg , sizeof ( msg ) , " 终端 id: %s 台账删除成功 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-01-16 16:17:01 +08:00
}
2025-01-17 17:10:18 +08:00
}
2025-01-16 16:17:01 +08:00
2025-01-17 17:10:18 +08:00
if ( ! new_in_work_found ) {
printf ( " modify_updates can not find ied!!!!!! \n " ) ;
2025-05-09 16:53:07 +08:00
//添加mq响应台账添加失败: 台账找不到
//update[i].guid
2025-05-12 16:43:42 +08:00
char msg [ 256 ] ;
sprintf ( msg , " 终端 id: %s 台账删除失败, 无法找到这个终端 " , update [ i ] . terminal_id ) ;
send_reply_to_kafka_c ( update [ i ] . guid , " 2 " , msg ) ;
2025-05-09 16:53:07 +08:00
2025-01-17 17:10:18 +08:00
}
}
//////////////////////////////////////////////////////////////////////////////
if ( ledger_update_xml - > modify_update_num | | ledger_update_xml - > new_update_num | | ledger_update_xml - > delete_update_num ) {
2025-05-09 16:53:07 +08:00
create_ledger_log ( ledger_update_xml ) ; //写入文件
2025-01-17 17:10:18 +08:00
}
2025-01-16 16:17:01 +08:00
2025-01-17 17:10:18 +08:00
}
2025-05-09 16:53:07 +08:00
//台账更新调试打印函数
// 检查字符串是否为空
// 检查字符串是否为空
2025-01-16 16:17:01 +08:00
int is_empty ( const char * str ) {
return ( str = = NULL | | str [ 0 ] = = ' \0 ' ) ;
}
2025-05-09 16:53:07 +08:00
// 打印 monitor 结构体信息
2025-01-16 16:17:01 +08:00
void print_monitor ( const monitor * mon ) {
printf ( " Monitor ID: %s \n " , is_empty ( mon - > monitor_id ) ? " N/A " : mon - > monitor_id ) ;
printf ( " Terminal Code: %s \n " , is_empty ( mon - > terminal_code ) ? " N/A " : mon - > terminal_code ) ;
printf ( " Monitor Name: %s \n " , is_empty ( mon - > monitor_name ) ? " N/A " : mon - > monitor_name ) ;
printf ( " Logical Device Sequence: %s \n " , is_empty ( mon - > logical_device_seq ) ? " N/A " : mon - > logical_device_seq ) ;
printf ( " Voltage Level: %s \n " , is_empty ( mon - > voltage_level ) ? " N/A " : mon - > voltage_level ) ;
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 ) ;
}
2025-05-09 16:53:07 +08:00
// 打印 terminal 结构体信息
2025-01-16 16:17:01 +08:00
void print_terminal ( const terminal * tmnl ) {
2025-05-09 16:53:07 +08:00
printf ( " GUID: %s \n " , is_empty ( tmnl - > guid ) ? " N/A " : tmnl - > guid ) ; //lnk20250506
2025-01-16 16:17:01 +08:00
printf ( " Terminal ID: %s \n " , is_empty ( tmnl - > terminal_id ) ? " N/A " : tmnl - > terminal_id ) ;
printf ( " Terminal Code: %s \n " , is_empty ( tmnl - > terminal_code ) ? " N/A " : tmnl - > terminal_code ) ;
printf ( " Organization Name: %s \n " , is_empty ( tmnl - > org_name ) ? " N/A " : tmnl - > org_name ) ;
printf ( " Maintenance Name: %s \n " , is_empty ( tmnl - > maint_name ) ? " N/A " : tmnl - > maint_name ) ;
printf ( " Station Name: %s \n " , is_empty ( tmnl - > station_name ) ? " N/A " : tmnl - > station_name ) ;
printf ( " Factory Name: %s \n " , is_empty ( tmnl - > tmnl_factory ) ? " N/A " : tmnl - > tmnl_factory ) ;
printf ( " Terminal Status: %s \n " , is_empty ( tmnl - > tmnl_status ) ? " N/A " : tmnl - > tmnl_status ) ;
printf ( " Device Type: %s \n " , is_empty ( tmnl - > dev_type ) ? " N/A " : tmnl - > dev_type ) ;
printf ( " Device Key: %s \n " , is_empty ( tmnl - > dev_key ) ? " N/A " : tmnl - > dev_key ) ;
printf ( " Device Series: %s \n " , is_empty ( tmnl - > dev_series ) ? " N/A " : tmnl - > dev_series ) ;
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 ) ;
2025-05-09 16:53:07 +08:00
// 打印监测点信息,如果监测点字段为空,则打印 N/A
2025-01-16 16:17:01 +08:00
int i ;
for ( i = 0 ; i < 10 & & ! is_empty ( tmnl - > line [ i ] . monitor_id ) ; + + i ) {
printf ( " Monitor %d: \n " , i + 1 ) ;
print_monitor ( & tmnl - > line [ i ] ) ;
}
}
2025-05-09 16:53:07 +08:00
// 打印 trigger_update_xml_t 结构体信息
2025-01-16 16:17:01 +08:00
void print_trigger_update_xml ( const trigger_update_xml_t * trigger_update ) {
printf ( " Work Updates Count: %d \n " , trigger_update - > work_update_num ) ;
printf ( " New Updates Count: %d \n " , trigger_update - > new_update_num ) ;
printf ( " Delete Updates Count: %d \n " , trigger_update - > delete_update_num ) ;
printf ( " Modify Updates Count: %d \n " , trigger_update - > modify_update_num ) ;
printf ( " \n Work Updates: \n " ) ;
int i ;
for ( i = 0 ; i < trigger_update - > work_update_num ; + + i ) {
printf ( " Work Update %d: \n " , i + 1 ) ;
print_terminal ( & trigger_update - > work_updates [ i ] ) ;
}
printf ( " \n New Updates: \n " ) ;
for ( i = 0 ; i < trigger_update - > new_update_num ; + + i ) {
printf ( " New Update %d: \n " , i + 1 ) ;
print_terminal ( & trigger_update - > new_updates [ i ] ) ;
}
printf ( " \n Delete Updates: \n " ) ;
for ( i = 0 ; i < trigger_update - > delete_update_num ; + + i ) {
printf ( " Delete Update %d: \n " , i + 1 ) ;
print_terminal ( & trigger_update - > delete_updates [ i ] ) ;
}
printf ( " \n Modify Updates: \n " ) ;
for ( i = 0 ; i < trigger_update - > modify_update_num ; + + i ) {
printf ( " Modify Update %d: \n " , i + 1 ) ;
print_terminal ( & trigger_update - > modify_updates [ i ] ) ;
}
}
void check_ledger_update ( ) //lnk20250113
{
double now ;
2025-05-09 16:53:07 +08:00
static double last_check_3s_config_time = 0.0 ; //初始化时间
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
now = sGetMsTime ( ) ; //当前时间
if ( fabs ( now - last_check_3s_config_time ) < 3 * 1000 ) //wait 3secs //当前进程任务执行时查看当前时间和上次执行时间间隔, 小于3秒不执行, 大于等于3秒往下执行
2025-01-16 16:17:01 +08:00
return ;
2025-05-09 16:53:07 +08:00
// 动态分配内存给 trigger_ledger_update_xml 结构体
2025-02-11 18:23:19 +08:00
trigger_update_xml_t * trigger_ledger_update_xml = ( trigger_update_xml_t * ) malloc ( sizeof ( trigger_update_xml_t ) ) ;
if ( trigger_ledger_update_xml = = NULL ) {
printf ( " Memory allocation failed! \n " ) ;
2025-05-09 16:53:07 +08:00
return ; // 如果内存分配失败,返回
2025-02-11 18:23:19 +08:00
}
2025-05-09 16:53:07 +08:00
//每次都初始化防止重复
2025-02-11 18:23:19 +08:00
memset ( trigger_ledger_update_xml , 0 , sizeof ( trigger_update_xml_t ) ) ;
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//printf("check ledger update...trigger_ledger_update_xml:%d\n",trigger_ledger_update_xml->modify_update_num);//减少不必要的打印
2025-01-16 19:16:26 +08:00
2025-05-09 16:53:07 +08:00
last_check_3s_config_time = now ; //记录本次运行时间
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//判断是否满足执行条件,一个文件就是一个终端,读取文件后删除文件
if ( APR_SUCCESS = = parse_ledger_update_xml ( trigger_ledger_update_xml ) ) { //处理台账更新文件,如果有可以更新或者添加台账的
//调试用
2025-02-11 18:23:19 +08:00
print_trigger_update_xml ( trigger_ledger_update_xml ) ;
2025-01-17 17:10:18 +08:00
2025-05-09 16:53:07 +08:00
//处理台账更新加台账锁lnk20250114
2025-02-24 16:45:42 +08:00
//pthread_mutex_lock(&mtx); printf("ledgerupdate hold lock !!!!!!!!!!!");
2025-05-09 16:53:07 +08:00
process_ledger_update ( trigger_ledger_update_xml ) ; //台账更新
2025-02-24 16:45:42 +08:00
//pthread_mutex_unlock(&mtx); printf("ledgerupdate free lock !!!!!!!!!!!");
2025-01-17 17:10:18 +08:00
2025-01-16 16:17:01 +08:00
}
2025-02-11 18:23:19 +08:00
2025-05-09 16:53:07 +08:00
// 使用完后释放动态分配的内存
2025-02-11 18:23:19 +08:00
free ( trigger_ledger_update_xml ) ;
2025-01-16 16:17:01 +08:00
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# ifdef _OS_UNIX_
uint32_t get_freedisk_MB ( uint32_t * totalSizeMB )
{
struct statfs diskInfo ;
unsigned long long totalBlocks = 0 ;
unsigned long long totalSize = 0 ;
size_t mbTotalsize = 0 ;
size_t freeDisk = 0 ;
size_t mbFreeDisk = 0 ;
statfs ( " /home/pq " , & diskInfo ) ;
totalBlocks = diskInfo . f_bsize ;
totalSize = totalBlocks * diskInfo . f_blocks ;
mbTotalsize = totalSize > > 20 ;
freeDisk = diskInfo . f_bfree * totalBlocks ;
mbFreeDisk = freeDisk > > 20 ;
printf ( " /home/pq total=%dMB, free=%dMB \n " , mbTotalsize , mbFreeDisk ) ;
if ( totalSizeMB )
* totalSizeMB = mbTotalsize ;
return mbFreeDisk ;
}
# else
uint32_t get_freedisk_MB ( uint32_t * totalSizeMB ) {
if ( totalSizeMB )
* totalSizeMB = 1000 ;
return 5 ;
}
# endif
void check_disk_quota ( )
{
double now ;
static double last_check_time = - 10000000.0 ;
uint32_t freeSizeMB , totalSizeMB ;
2025-05-28 16:09:15 +08:00
if ( g_node_id ! = STAT_DATA_BASE_NODE_ID | | g_front_seg_index ! = 1 ) //lnk20250527只有稳态进程1监测磁盘
2025-01-16 16:17:01 +08:00
return ;
now = sGetMsTime ( ) ;
if ( fabs ( now - last_check_time ) < 15 * 1000 ) //wait 15 secs
return ;
last_check_time = now ;
freeSizeMB = get_freedisk_MB ( & totalSizeMB ) ;
//printf("Current user disk free size: %dMB ,total size: %dMB \n",freeSizeMB,totalSizeMB);
2025-05-28 16:09:15 +08:00
if ( freeSizeMB < g_min_free_size ) {
2025-01-16 16:17:01 +08:00
echo_warn2 ( " Current user disk free size: %dMB < %dMB, please check! \n " , freeSizeMB , g_min_free_size ) ;
2025-05-29 16:36:34 +08:00
DIY_WARNLOG ( " process " , " 【WARN】前置磁盘检测: 当前磁盘的可用空间为%dMB,小于最小可用空间%dMB,请检查磁盘 " , freeSizeMB , g_min_free_size ) ;
2025-05-28 16:09:15 +08:00
}
if ( ( freeSizeMB / ( totalSizeMB / 100 + 1 ) ) < 10 ) {
2025-01-16 16:17:01 +08:00
echo_warn2 ( " Current user disk free size percent < 10%%, free size: %dMB ,total size: %dMB ,please check! \n " ,
freeSizeMB , totalSizeMB ) ;
2025-05-29 16:36:34 +08:00
DIY_WARNLOG ( " process " , " 【WARN】前置磁盘检测: 当前磁盘的可用空间的百分比小于10%%,可用空间为%dMB,总空间为%dMB,请检查磁盘 " , freeSizeMB , totalSizeMB ) ;
2025-05-28 16:09:15 +08:00
}
2025-01-16 16:17:01 +08:00
}
void create_recall_xml ( )
{
2025-05-09 16:53:07 +08:00
//生成待补招xml文件
2025-01-16 16:17:01 +08:00
if ( 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 ) ) {
DeletcRecallXml ( ) ;
CreateRecallXml ( ) ;
}
}
void Delete_recall_Xml ( char * id ) {
if ( 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 ) ) {
delete_recall_xml ( id ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
}
}
2025-05-09 16:53:07 +08:00
void Check_Recall_Config ( char * id ) //检查补招配置文件Recall.xml
2025-01-16 16:17:01 +08:00
{
if ( 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 ) ) {
recall_xml_t recall_xml ;
memset ( ( char * ) & recall_xml , 0 , sizeof ( recall_xml_t ) ) ;
2025-07-24 16:14:00 +08:00
parse_recall_xml ( & recall_xml , id ) ; //解析补招文件,目录下所有属于这个监测点的文件都读取
2025-05-09 16:53:07 +08:00
process_recall_config ( & recall_xml ) ; //解析的补招数据赋值到全局变量
2025-01-16 16:17:01 +08:00
}
}
void CheckAllConnectedChannel ( )
{
chnl_usr_t * chnl_usr ;
static uint32_t chnl_sequence_no = 0 ;
2025-05-14 16:42:29 +08:00
//lnk20250514如果进程启动没有台账则不往下执行, 等待台账更新
if ( g_pt61850app - > chnl_counts = = 0 ) return ;
//lnk20250514如果进程启动没有台账则不往下执行, 等待台账更新
2025-05-09 16:53:07 +08:00
//一次访问一个终端
2025-01-16 16:17:01 +08:00
do {
chnl_usr = g_pt61850app - > chnl_usr [ chnl_sequence_no ] ;
chnl_sequence_no = ( chnl_sequence_no + 1 ) % g_pt61850app - > chnl_counts ;
2025-07-01 18:40:05 +08:00
if ( chnl_usr = = NULL ) continue ; // 安全防护lnk20250701
2025-01-16 16:17:01 +08:00
} while ( ( g_onlyIP [ 0 ] ! = 0 ) & & ( strcmp ( g_onlyIP , chnl_usr - > ip_str ) ! = 0 ) ) ;
2025-04-29 15:05:36 +08:00
2025-07-01 18:40:05 +08:00
if ( chnl_usr = = NULL | | chnl_usr - > chnl = = NULL | | chnl_usr - > chnl - > ied = = NULL | | chnl_usr - > chnl - > ied - > usr_ext = = NULL ) {
printf ( " chnl_usr or nested member is NULL, skip... \n " ) ;
return ;
}
2025-01-16 16:17:01 +08:00
if ( chnl_usr - > m_state = = CHANNEL_CONNECTED )
{
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
ChannelCheckIECReports ( chnl_usr ) ; //报告
2025-01-16 16:17:01 +08:00
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 ) )
2025-05-09 16:53:07 +08:00
ChannelCheckWaveFiles ( chnl_usr ) ; //录波文件
2025-01-16 16:17:01 +08:00
if ( 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 ) )
2025-05-09 16:53:07 +08:00
ChannelCheckIECLogs ( chnl_usr ) ; //补招文件
if ( ( sGetMsTime ( ) - chnl_usr - > m_LastPosRespTime ) > 15 * 1000 ) //wait 15 secs, 隔15秒获取一次响应, 两次没响应后关闭
2025-01-16 16:17:01 +08:00
{
char * * varnames ;
int varnum ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
ST_RET ret = mms_mvla_getnam ( chnl_usr - > net_info , VMD_SPEC , NULL , MMS_CLASS_DOM , g_pt61850app - > mmsOpTimeout ,
& varnames , & varnum , g_pt61850app - > tmp_pool ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > m_LastPosRespTime = sGetMsTime ( ) ;
if ( ret = = SD_SUCCESS ) {
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > m_NegRespTimes = 0 ;
} else {
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
printf ( " %d-------------- \n " , chnl_usr - > m_NegRespTimes ) ;
chnl_usr - > m_NegRespTimes + + ;
}
}
if ( chnl_usr - > m_NegRespTimes > = 2 ) {
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
closeChannel ( chnl_usr ) ; //???特殊情况是否需要 mms_release_connection
2025-01-16 16:17:01 +08:00
chnl_usr - > m_NegRespTimes = 0 ;
chnl_usr - > m_LastPosRespTime = sGetMsTime ( ) ;
}
}
}
void CheckNextNotConnectedChannel ( )
{
static uint32_t chnl_total_no = 0 ;
chnl_usr_t * chnl_usr ;
2025-04-29 15:05:36 +08:00
2025-05-14 16:42:29 +08:00
//lnk20250514如果进程启动没有台账则不往下执行, 等待台账更新
if ( g_pt61850app - > chnl_counts = = 0 ) return ;
//lnk20250514如果进程启动没有台账则不往下执行, 等待台账更新
2025-01-16 16:17:01 +08:00
do {
chnl_usr = g_pt61850app - > chnl_usr [ chnl_total_no ] ;
chnl_total_no = ( chnl_total_no + 1 ) % g_pt61850app - > chnl_counts ;
2025-07-01 18:40:05 +08:00
if ( chnl_usr = = NULL ) continue ; // 安全防护lnk20250701
2025-02-11 18:23:19 +08:00
} while ( ( g_onlyIP [ 0 ] ! = 0 ) & & ( strcmp ( g_onlyIP , chnl_usr - > ip_str ) ! = 0 ) ) ;
2025-07-01 18:40:05 +08:00
if ( chnl_usr = = NULL | | chnl_usr - > chnl = = NULL | | chnl_usr - > chnl - > ied = = NULL | | chnl_usr - > chnl - > ied - > usr_ext = = NULL ) {
printf ( " chnl_usr or nested member is NULL, skip... \n " ) ;
return ;
}
2025-05-28 16:09:15 +08:00
//终端日志的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
2025-01-16 16:17:01 +08:00
//10-11-01 22:03 beijing
if ( ( ( chnl_total_no + 1 ) = = g_pt61850app - > chnl_counts ) | | ( g_onlyIP [ 0 ] ! = 0 ) ) {
if ( g_pt61850app - > initNum < 255 )
g_pt61850app - > initNum + + ;
}
2025-02-11 18:23:19 +08:00
2025-05-09 16:53:07 +08:00
if ( chnl_usr - > m_state = = CHANNEL_CONNECTING ) //正在连接
2025-01-16 16:17:01 +08:00
{
2025-04-29 15:05:36 +08:00
2025-02-11 18:23:19 +08:00
MVL_REQ_PEND * reqCtrl = chnl_usr - > m_reqCtrl ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( reqCtrl - > done = = SD_TRUE )
{
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( reqCtrl - > result = = SD_SUCCESS )
{
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
ALL_RCB_INFO * all_rcb_info ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_warn4 ( " \n CHANNEL_CONNECTED %s:%d ,NetInfo= %x chnl_usr= %x \n " ,
chnl_usr - > ip_str , chnl_usr - > chnl - > port , chnl_usr - > net_info , chnl_usr ) ;
2025-05-28 16:09:15 +08:00
//mq日志
2025-07-04 15:10:31 +08:00
( ( ied_usr_t * ) ( chnl_usr - > chnl - > ied - > usr_ext ) ) - > lastconnectstat = true ;
( ( ied_usr_t * ) ( chnl_usr - > chnl - > ied - > usr_ext ) ) - > has_logged_disconnect = false ;
2025-05-28 16:09:15 +08:00
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 ) ;
2025-01-16 16:17:01 +08:00
mvl_free_req_ctrl ( chnl_usr - > m_reqCtrl ) ;
chnl_usr - > m_reqCtrl = NULL ;
chnl_usr - > m_state = CHANNEL_CONNECTED ;
chnl_usr - > net_info - > user_ext = chnl_usr ;
all_rcb_info = ( ALL_RCB_INFO * ) chk_calloc ( 1 , sizeof ( ALL_RCB_INFO ) ) ;
all_rcb_info - > rpt_typeids = & g_rpt_typeids ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( chnl_usr - > net_info - > user_info ! = NULL ) {
echo_warn ( " chnl_usr->net_info->user_info is not NULL \n " ) ;
}
chnl_usr - > net_info - > user_info = all_rcb_info ;
chnl_usr - > chnl - > ied - > status = STATUS_NORMAL ;
chnl_usr - > chnl - > status = STATUS_NORMAL ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
{
char comm_str [ 256 ] ;
memset ( comm_str , 0 , 256 ) ;
apr_snprintf ( comm_str , sizeof ( comm_str ) , " %16s:%d \t \t connected " , chnl_usr - > ip_str , chnl_usr - > chnl - > port ) ;
add_comm_log ( comm_str ) ;
FRONT_MP_NUM + + ;
}
2025-05-09 16:53:07 +08:00
//lnk202411-1添加连接成功的记录
2025-01-16 16:17:01 +08:00
ied_usr_t * ied_usr = ( ied_usr_t * ) chnl_usr - > chnl - > ied - > usr_ext ;
2025-03-12 11:45:53 +08:00
apr_time_t t_now = apr_time_now ( ) ;
printf ( " msTime:%ld " , t_now ) ;
2025-05-09 16:53:07 +08:00
connectlog_pgsql ( ied_usr - > terminal_id , convertMsToDateTimeString ( t_now ) , 1 ) ; //1成功
2025-02-11 18:23:19 +08:00
2025-01-16 16:17:01 +08:00
}
else
2025-05-09 16:53:07 +08:00
{ // solaris 9 上 224秒
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
int secsSince = ( int ) ( sGetMsTime ( ) - chnl_usr - > m_StartConnectingTime ) / 1000 ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
ied_usr_t * ied_usr = ( ied_usr_t * ) chnl_usr - > chnl - > ied - > usr_ext ;
2025-04-29 15:05:36 +08:00
2025-05-28 16:09:15 +08:00
printf ( " reqCtrl->result == FAIL, Since StartConnecting %i sec ,channel IP %s:%d \n " , secsSince , chnl_usr - > ip_str , chnl_usr - > chnl - > port ) ;
//mq日志
2025-07-04 15:10:31 +08:00
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 ( full_key_t_c , " 【WARN】终端%s - ip/端口:%s:%d - 识别码/秘钥:%s/%s,从开始连接到目前已经%i秒,连接失败,断开连接! " , ( ( 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 , 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 ( full_key_t_c , " 【WARN】终端%s - ip/端口:%s:%d - 识别码/秘钥:%s/%s,从开始连接到目前已经%i秒,连接失败,断开连接! " , ( ( 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 , secsSince ) ;
}
2025-05-28 16:09:15 +08:00
2025-01-16 16:17:01 +08:00
mvl_free_req_ctrl ( chnl_usr - > m_reqCtrl ) ;
chnl_usr - > m_reqCtrl = NULL ;
chnl_usr - > net_info - > rem_vmd = NULL ;
chnl_usr - > m_state = CHANNEL_DISCONNECTED ;
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
}
}
else
2025-04-29 15:05:36 +08:00
{
if ( ( sGetMsTime ( ) - chnl_usr - > m_StartConnectingTime ) > 300 * 1000 ) //300*1000 ) //wait 300 secs
2025-01-16 16:17:01 +08:00
{
ied_usr_t * ied_usr = ( ied_usr_t * ) chnl_usr - > chnl - > ied - > usr_ext ;
2025-04-29 15:05:36 +08:00
2025-05-28 16:09:15 +08:00
echo_warn2 ( " reqCtrl->done未完成,but time over 300 secs, close channel IP %s,NetInfo= %x " , chnl_usr - > ip_str , chnl_usr - > net_info ) ;
//mq日志
2025-07-04 15:10:31 +08:00
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 ( full_key_t_c , " 【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 ( full_key_t_c , " 【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 ) ;
}
2025-05-28 16:09:15 +08:00
2025-01-16 16:17:01 +08:00
if ( chnl_usr - > net_info - > req_pend_list ) {
2025-05-09 16:53:07 +08:00
echo_warn ( " reqCtrl->done未完成,but time over 300 secs!!!!!!!! \n " ) ;
2025-01-16 16:17:01 +08:00
mvl_free_req_ctrl ( chnl_usr - > m_reqCtrl ) ;
chnl_usr - > m_reqCtrl = NULL ;
}
mms_release_connection ( chnl_usr - > net_info ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > net_info - > rem_vmd = NULL ;
chnl_usr - > m_state = CHANNEL_DISCONNECTED ;
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
}
}
2025-04-29 15:05:36 +08:00
}
2025-01-16 16:17:01 +08:00
else if ( chnl_usr - > m_state = = CHANNEL_DISCONNECTED )
{
2025-02-11 18:23:19 +08:00
2025-01-16 16:17:01 +08:00
if ( ( sGetMsTime ( ) - chnl_usr - > m_ClosedMsTime ) > NEXT_CONNECT_TIME ) //wait 10 secs
{
2025-02-11 18:23:19 +08:00
2025-01-16 16:17:01 +08:00
ST_RET ret ;
ST_CHAR serverARName [ 32 ] ;
ied_usr_t * ied_usr = ( ied_usr_t * ) chnl_usr - > chnl - > ied - > usr_ext ;
apr_snprintf ( serverARName , sizeof ( serverARName ) , " %s:%d " , chnl_usr - > ip_str , chnl_usr - > chnl - > port ) ;
2025-05-09 16:53:07 +08:00
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如果终端无效则不连接
2025-05-28 16:09:15 +08:00
//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);
2025-01-16 16:17:01 +08:00
ret = mms_connectToServer ( ied_usr - > dev_key , ied_usr - > dev_series , serverARName , & ( chnl_usr - > net_info ) , & ( chnl_usr - > m_reqCtrl ) ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
if ( ret = = SD_SUCCESS )
{
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_msg3 ( " mms_connectToServer IP %s:%d ,NetInfo= %x \n " , chnl_usr - > ip_str , chnl_usr - > chnl - > port , chnl_usr - > net_info ) ;
chnl_usr - > m_state = CHANNEL_CONNECTING ;
chnl_usr - > m_StartConnectingTime = sGetMsTime ( ) ;
2025-05-28 16:09:15 +08:00
//mq日志
2025-07-04 15:10:31 +08:00
//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);
2025-05-28 16:09:15 +08:00
2025-01-16 16:17:01 +08:00
}
else
{
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_warn3 ( " FAILED: mms_connectToServer IP %s:%d ,NetInfo= %x \n " , chnl_usr - > ip_str , chnl_usr - > chnl - > port , chnl_usr - > net_info ) ;
2025-05-28 16:09:15 +08:00
//mq日志
2025-07-04 15:10:31 +08:00
//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);
2025-01-16 16:17:01 +08:00
}
}
}
2025-04-29 15:05:36 +08:00
}
2025-05-09 16:53:07 +08:00
else if ( chnl_usr - > m_state = = CHANNEL_DISCONNECTING ) //need check timeout?会不会永远停留在这里
2025-01-16 16:17:01 +08:00
{
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
MVL_REQ_PEND * reqCtrl = chnl_usr - > m_reqCtrl ;
if ( reqCtrl - > done = = SD_TRUE )
2025-02-11 18:23:19 +08:00
{
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
echo_warn3 ( " CHANNEL_DISCONNECTING done %s:%d,NetInfo= %x " , chnl_usr - > ip_str , chnl_usr - > chnl - > port , chnl_usr - > net_info ) ;
mvl_free_req_ctrl ( chnl_usr - > m_reqCtrl ) ;
if ( chnl_usr - > net_info )
chnl_usr - > net_info - > user_ext = NULL ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
chnl_usr - > m_reqCtrl = NULL ;
chnl_usr - > net_info = NULL ;
chnl_usr - > m_state = CHANNEL_DISCONNECTED ;
2025-03-12 11:45:53 +08:00
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
2025-05-09 16:53:07 +08:00
//断联成功
2025-03-12 11:45:53 +08:00
ied_usr_t * ied_usr = ( ied_usr_t * ) chnl_usr - > chnl - > ied - > usr_ext ;
apr_time_t t_now = apr_time_now ( ) ;
connectlog_pgsql ( ied_usr - > terminal_id , convertMsToDateTimeString ( t_now ) , 0 ) ;
2025-05-28 16:09:15 +08:00
//mq日志
2025-05-29 16:36:34 +08:00
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 ) ;
2025-05-28 16:09:15 +08:00
2025-01-16 16:17:01 +08:00
}
else
2025-04-29 15:05:36 +08:00
{
2025-01-16 16:17:01 +08:00
echo_warn2 ( " CHANNEL_DISCONNECTING waiting ... %s,NetInfo= %x " , chnl_usr - > ip_str , chnl_usr - > net_info ) ;
if ( ( sGetMsTime ( ) - chnl_usr - > m_StartDisconnectingTime ) > 30 * 1000 ) // //wait 30 secs ?????
2025-02-24 16:45:42 +08:00
{
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
echo_warn2 ( " CHANNEL_DISCONNECTING reqCtrl->done未完成,but time over 180 secs, close channel IP %s,NetInfo= %x " , chnl_usr - > ip_str , chnl_usr - > net_info ) ;
2025-01-16 16:17:01 +08:00
mvl_free_req_ctrl ( chnl_usr - > m_reqCtrl ) ;
chnl_usr - > net_info - > user_ext = NULL ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
mms_release_connection ( chnl_usr - > net_info ) ;
chnl_usr - > net_info - > rem_vmd = NULL ;
chnl_usr - > m_reqCtrl = NULL ;
chnl_usr - > net_info = NULL ;
chnl_usr - > m_state = CHANNEL_DISCONNECTED ;
chnl_usr - > m_ClosedMsTime = sGetMsTime ( ) ;
2025-05-09 16:53:07 +08:00
//超时断联成功
2025-03-12 11:45:53 +08:00
ied_usr_t * ied_usr = ( ied_usr_t * ) chnl_usr - > chnl - > ied - > usr_ext ;
apr_time_t t_now = apr_time_now ( ) ;
connectlog_pgsql ( ied_usr - > terminal_id , convertMsToDateTimeString ( t_now ) , 0 ) ;
2025-05-28 16:09:15 +08:00
//mq日志
DIY_WARNLOG ( full_key_t_c , " 【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 ) ;
2025-01-16 16:17:01 +08:00
}
}
2025-04-29 15:05:36 +08:00
}
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
//////////////////////*********相关控制操作**********////////////////////////////////////////////////
2025-01-16 16:17:01 +08:00
static ST_RET Read_Named_Var ( LD_info_t * LD_info , chnl_usr_t * chnl_usr , char * VarName , ST_INT type_id , ST_VOID * dataDest , ST_INT timeOut )
{
ST_RET ret = SD_FAILURE ;
ST_CHAR * domName = LD_info - > LD_name ;
int Need_Destroy_Typeid = FALSE ;
assert ( chnl_usr & & LD_info ) ;
if ( type_id = = - 1 ) {
Need_Destroy_Typeid = TRUE ;
type_id = mms_var_type_id_create ( chnl_usr - > net_info , DOM_SPEC , domName , VarName , timeOut ) ;
if ( type_id = = - 1 ) ret = SD_FAILURE ; else ret = SD_SUCCESS ;
if ( ret = = SD_FAILURE ) return SD_FAILURE ;
}
ret = mms_named_var_read ( chnl_usr - > net_info , VarName , DOM_SPEC , domName , type_id , dataDest , timeOut ) ;
if ( Need_Destroy_Typeid )
if ( type_id ! = - 1 ) mvl_type_id_destroy ( type_id ) ;
return ret ;
}
static ST_RET Write_Named_Var ( LD_info_t * LD_info , chnl_usr_t * chnl_usr , char * VarName , ST_INT type_id , ST_VOID * dataDest , ST_INT timeOut )
{
ST_RET ret = SD_FAILURE ;
ST_CHAR * domName = LD_info - > LD_name ;
int Need_Destroy_Typeid = FALSE ;
assert ( chnl_usr & & LD_info ) ;
if ( type_id = = - 1 ) {
Need_Destroy_Typeid = TRUE ;
type_id = mms_var_type_id_create ( chnl_usr - > net_info , DOM_SPEC , domName , VarName , timeOut ) ;
if ( type_id = = - 1 ) ret = SD_FAILURE ; else ret = SD_SUCCESS ;
if ( ret = = SD_FAILURE ) return SD_FAILURE ;
}
ret = mms_named_var_write ( chnl_usr - > net_info , VarName , DOM_SPEC , domName , type_id , dataDest , timeOut ) ;
if ( Need_Destroy_Typeid )
if ( type_id ! = - 1 ) mvl_type_id_destroy ( type_id ) ;
return ret ;
}
/*
< EnumType id = " ctlModelsEnum " >
< EnumVal ord = " 0 " > status - only < / EnumVal >
< EnumVal ord = " 1 " > direct - with - normal - security < / EnumVal >
< EnumVal ord = " 2 " > sbo - with - normal - security < / EnumVal >
< EnumVal ord = " 3 " > direct - with - enhanced - security < / EnumVal >
< EnumVal ord = " 4 " > sbo - with - enhanced - security < / EnumVal >
< / EnumType >
*/
# define TICKS_PER_MIN 60LL*1000LL*1000LL
int pt61850_write_cn_file ( chnl_usr_t * chnl_usr , ied_t * ied , char * rem_filename , char * only_filename_ret )
{
int ret ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
char loc_filename [ 128 ] , loc_file_fullname [ 256 ] , rem_file_fullname [ 256 ] , only_filename_str [ 256 ] ;
2025-04-29 15:05:36 +08:00
2025-01-16 16:17:01 +08:00
char * only_filename , * the_full_file ;
memset ( loc_filename , 0 , sizeof ( loc_filename ) ) ;
memset ( only_filename_str , 0 , sizeof ( only_filename_str ) ) ;
strcat ( only_filename_str , rem_filename ) ;
only_filename = only_filename_str ;
the_full_file = only_filename_str ;
while ( * the_full_file ! = 0 ) {
if ( * the_full_file = = ' / ' )
only_filename = the_full_file + 1 ;
the_full_file + + ;
}
memset ( rem_file_fullname , 0 , sizeof ( rem_file_fullname ) ) ;
if ( strstr ( rem_filename , " / " ) ! = NULL ) {
strcat ( rem_file_fullname , rem_filename ) ;
}
else {
strcat ( rem_file_fullname , g_pt61850app - > accPath ) ;
strcat ( rem_file_fullname , rem_filename ) ;
}
memset ( loc_file_fullname , 0 , sizeof ( loc_file_fullname ) ) ;
apr_snprintf ( loc_file_fullname , sizeof ( loc_file_fullname ) , " ../comtrade/%s " , only_filename ) ;
apr_snprintf ( only_filename_ret , 256 , " %s " , only_filename ) ;
printf ( " \n >>>>>>>>>****** Get wave file : %s from %s \n " , loc_file_fullname , rem_file_fullname ) ;
ret = mms_getFile ( chnl_usr - > net_info , loc_file_fullname , rem_file_fullname , g_pt61850app - > mmsOpTimeout ) ;
if ( ret = = SD_SUCCESS ) {
}
else {
echo_warn3 ( " >>>>>**** Error!!! %s mms_getFile wave file : %s from %s \n " , chnl_usr - > ip_str , loc_file_fullname , rem_file_fullname ) ;
}
return ret ;
}
apr_status_t prepare_call_cn_wavelist ( LD_info_t * LD_info , int FltNum )
{
int i ;
for ( i = 0 ; i < 256 ; i + + ) {
if ( LD_info - > FltNum [ i ] < = 0 ) {
LD_info - > FltNum [ i ] = FltNum ;
break ;
}
}
return APR_SUCCESS ;
}
apr_status_t call_cn_wavelist ( LD_info_t * LD_info )
{
int ret ;
int chnl_no ;
chnl_usr_t * chnl_usr = NULL ;
char * * filenames ;
int filenum ;
int i ;
char file_match_str [ 65 ] ;
char * ldstr ;
ied_t * ied = LD_info - > ied ;
ied_usr_t * ied_usr = GET_IEDEXT_ADDR ( ied ) ;
int have_new_files = FALSE ;
2025-05-26 16:51:27 +08:00
//监测点日志的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
2025-01-16 16:17:01 +08:00
for ( i = 0 ; i < 256 ; i + + ) {
if ( LD_info - > FltNum [ i ] < = 0 )
continue ;
2025-05-26 16:51:27 +08:00
2025-05-09 16:53:07 +08:00
//LD名称规范四字节: PQMn, 或者PQLDn ,有5个字节, 但也只取4个字符进行匹配
2025-01-16 16:17:01 +08:00
ldstr = LD_info - > LD_name + strlen ( LD_info - > LD_name ) - 4 ;
apr_snprintf ( file_match_str , sizeof ( file_match_str ) , " %s_%06d " , ldstr , LD_info - > FltNum [ i ] ) ;
printf ( " >>>>>>>> IED [%d]: %s is calling cn wavefile, !!!!!!!! file_match_str=%s \n " , ied - > id , ied - > name , file_match_str ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s开始召唤录波文件 " , LD_info - > name , LD_info - > mp_id ) ;
2025-01-16 16:17:01 +08:00
ret = SD_FAILURE ;
filenum = 0 ;
assert ( ied - > chncount ) ;
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 )
continue ;
ret = mms_mvla_fdir ( chnl_usr - > net_info , g_pt61850app - > accPath , 3 * g_pt61850app - > mmsOpTimeout , & filenames , & filenum , g_pt61850app - > tmp_pool ) ;
if ( ret = = SD_SUCCESS )
break ;
}
if ( ret = = SD_SUCCESS ) {
int cfg_idx , dat_idx ;
char file_base_name [ 128 ] ;
char file_yyyymm [ 128 ] ;
char cfg_only_filename_ret [ 256 ] ;
char dat_only_filename_ret [ 256 ] ;
int ret2 , ret3 ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s获取录波文件列表成功,开始匹配录波文件 " , LD_info - > name , LD_info - > mp_id ) ;
2025-05-09 16:53:07 +08:00
//WW 2023-11-01将录波段号由字符串匹配修改为int的fltnum匹配
2025-01-16 16:17:01 +08:00
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
2025-05-26 16:51:27 +08:00
if ( ret2 ! = APR_SUCCESS ) {
//mq日志
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s匹配录波文件失败 " , LD_info - > name , LD_info - > mp_id ) ;
2025-01-16 16:17:01 +08:00
return ret2 ;
2025-05-26 16:51:27 +08:00
}
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
//完成录波文件, 记录在文件名dat/cfg_only_filename_ret中, 两个后缀不一样的录波文件, 要上传两次
2025-01-16 16:17:01 +08:00
ret2 = pt61850_write_cn_file ( chnl_usr , ied , filenames [ cfg_idx ] , cfg_only_filename_ret ) ;
ret3 = pt61850_write_cn_file ( chnl_usr , ied , filenames [ dat_idx ] , dat_only_filename_ret ) ;
have_new_files = TRUE ;
2025-05-09 16:53:07 +08:00
/////////////////////////////////////////////////////////////////////////////////////////////上传文件
if ( ret2 = = SD_SUCCESS & & ret3 = = SD_SUCCESS ) { //两个文件都写好了
2025-05-26 16:51:27 +08:00
//mq日志
DIY_INFOLOG ( full_key_m_c , " 【NORMAL】监测点:%s - id:%s从终端获取录波文件成功,开始上传录波文件到web并更新暂态事件 " , LD_info - > name , LD_info - > mp_id ) ;
2025-05-09 16:53:07 +08:00
QVVR_t * qvvr ; //暂态事件
2025-01-16 16:17:01 +08:00
long long start_tm , trig_tm , end_tm ;
2025-04-29 15:05:36 +08:00
2025-05-09 16:53:07 +08:00
ret2 = extract_timestamp_from_cfg_file ( filenames [ cfg_idx ] , & start_tm , & trig_tm ) ; //提取文件的开始时间和触发时间
2025-01-16 16:17:01 +08:00
printf ( " >>>>>>>> extract_timestamp_from_cfg_file end \n " ) ;
if ( ret2 = = APR_SUCCESS ) {
//to find the paired qvvr by the time of trig_tm
2025-03-10 21:26:17 +08:00
printf ( " >>>>>>>> extract_timestamp_from_cfg_file success \n " ) ;
2025-05-09 16:53:07 +08:00
qvvr = find_qvvr_by_trig_tm ( LD_info , trig_tm ) ; //根据文件的触发时间查找检测点记录的匹配上的暂态事件
2025-01-16 16:17:01 +08:00
if ( qvvr ) {
2025-05-09 16:53:07 +08:00
char * uuid_cfg = ( char * ) malloc ( 65 * sizeof ( char ) ) ; //上传文件后获取到的路径
2025-01-16 16:17:01 +08:00
char * uuid_dat = ( char * ) malloc ( 65 * sizeof ( char ) ) ;
2025-05-09 16:53:07 +08:00
char * filename_cfg = ( char * ) malloc ( 100 * sizeof ( char ) ) ; //上传文件后获取到的文件名
2025-01-16 16:17:01 +08:00
char * filename_dat = ( char * ) malloc ( 100 * sizeof ( char ) ) ;
2025-05-09 16:53:07 +08:00
//lnk202411-5 记录web返回的路径+文件名
2025-03-10 21:26:17 +08:00
char * wavepath_cfg = ( char * ) malloc ( 256 * sizeof ( char ) ) ;
char * wavepath_dat = ( char * ) malloc ( 256 * sizeof ( char ) ) ;
2025-05-09 16:53:07 +08:00
/*上传.cfg和.dat两个文件*/
2025-01-16 16:17:01 +08:00
char linux_cmd [ 256 ] = { 0 } ;
printf ( " >>>>>>>> qvvr ok end \n " ) ;
2025-05-09 16:53:07 +08:00
apr_snprintf ( linux_cmd , sizeof ( linux_cmd ) , " ./sftp_upload %s %s/%04d " , cfg_only_filename_ret , file_yyyymm , LD_info - > line_id ) ; //没有使用
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
char loc_file_fullname_cfg [ 256 ] ; //本地文件名
2025-01-16 16:17:01 +08:00
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 ) ;
2025-05-09 16:53:07 +08:00
char oss_file_fullname_cfg [ 256 ] ; //远端文件名
2025-01-16 16:17:01 +08:00
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 ) {
2025-05-09 16:53:07 +08:00
PutOSS ( oss_file_fullname_cfg , loc_file_fullname_cfg ) ; //使用buffer推送文件
2025-01-16 16:17:01 +08:00
}
else if ( FILE_FLAG = = 2 ) {
2025-05-09 16:53:07 +08:00
OBSFile ( loc_file_fullname_cfg , oss_file_fullname_cfg , " putObject " ) ; //这里并没有上传文件流
2025-01-16 16:17:01 +08:00
}
else if ( FILE_FLAG = = 3 ) {
2025-05-09 16:53:07 +08:00
WebAPI_Uds_Upload ( UDS_UPLOAD_URL , loc_file_fullname_cfg , uuid_cfg , filename_cfg ) ; //通过form-data上传文件
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
//LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取
2025-01-16 16:17:01 +08:00
else if ( FILE_FLAG = = 4 ) {
2025-05-09 16:53:07 +08:00
char mq_file_fullname_cfg [ 256 ] ; // 远端文件名
2025-03-10 21:26:17 +08:00
memset ( mq_file_fullname_cfg , 0 , sizeof ( mq_file_fullname_cfg ) ) ;
2025-05-09 16:53:07 +08:00
// 使用修改后的文件名传入 apr_snprintf
2025-03-11 11:29:24 +08:00
apr_snprintf ( mq_file_fullname_cfg , sizeof ( mq_file_fullname_cfg ) , " comtrade/%s/ " ,
LD_info - > ied - > channel [ 0 ] . addr_str ) ;
2025-03-10 21:26:17 +08:00
SOEFileWeb ( loc_file_fullname_cfg , mq_file_fullname_cfg , wavepath_cfg ) ;
2025-03-11 11:29:24 +08:00
printf ( " \n >>>>>>!! %s %s...... \n " , mq_file_fullname_cfg , loc_file_fullname_cfg ) ;
2025-01-16 16:17:01 +08:00
}
2025-03-11 11:29:24 +08:00
if ( FILE_FLAG = = 4 ) {
2025-01-16 16:17:01 +08:00
}
2025-03-11 11:29:24 +08:00
else {
printf ( " \n >>>>>>!! %s %s...... \n " , oss_file_fullname_cfg , loc_file_fullname_cfg ) ;
}
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
apr_snprintf ( linux_cmd , sizeof ( linux_cmd ) , " ./sftp_upload %s %s/%04d " , dat_only_filename_ret , file_yyyymm , LD_info - > line_id ) ; //先通过sftp上传才发json过去
2025-01-16 16:17:01 +08:00
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 ) ;
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 ) {
2025-05-09 16:53:07 +08:00
PutOSS ( oss_file_fullname_dat , loc_file_fullname_dat ) ; //使用buffer推送文件
2025-01-16 16:17:01 +08:00
}
else if ( FILE_FLAG = = 2 ) {
2025-05-09 16:53:07 +08:00
OBSFile ( loc_file_fullname_dat , oss_file_fullname_dat , " putObject " ) ; //这里并没有上传文件流
2025-01-16 16:17:01 +08:00
}
else if ( FILE_FLAG = = 3 ) {
2025-05-09 16:53:07 +08:00
WebAPI_Uds_Upload ( UDS_UPLOAD_URL , loc_file_fullname_dat , uuid_dat , filename_dat ) ; //通过form-data上传文件
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
//LNK20241031使用JSON编码文件上传-具体的远端路径可以用原本代码的硬编码或者在配置文件中获取
2025-01-16 16:17:01 +08:00
else if ( FILE_FLAG = = 4 ) {
2025-05-09 16:53:07 +08:00
char mq_file_fullname_dat [ 256 ] ; // 远端文件名
2025-03-10 21:26:17 +08:00
memset ( mq_file_fullname_dat , 0 , sizeof ( mq_file_fullname_dat ) ) ;
2025-05-09 16:53:07 +08:00
// 使用修改后的文件名传入 apr_snprintf
2025-03-11 11:29:24 +08:00
apr_snprintf ( mq_file_fullname_dat , sizeof ( mq_file_fullname_dat ) , " comtrade/%s/ " ,
LD_info - > ied - > channel [ 0 ] . addr_str ) ;
2025-03-10 21:26:17 +08:00
2025-03-11 11:29:24 +08:00
SOEFileWeb ( loc_file_fullname_dat , mq_file_fullname_dat , wavepath_dat ) ;
printf ( " \n >>>>>>!! %s %s...... \n " , mq_file_fullname_dat , loc_file_fullname_dat ) ;
}
if ( FILE_FLAG = = 4 ) {
}
else {
printf ( " \n >>>>>>!! %s %s...... \n " , oss_file_fullname_dat , loc_file_fullname_dat ) ;
2025-01-16 16:17:01 +08:00
}
2025-03-11 11:29:24 +08:00
2025-05-09 16:53:07 +08:00
/*上传.cfg和.dat两个文件*/
/*上传消息*/
2025-05-20 16:31:12 +08:00
/////////////////////////////////////////////////////lnk20250520
//根据配置文件控制上传的暂态事件时间为北京时间的ms数
printf ( " ~~~~~~~this dev type is %s~~~~~~~ " , ied_usr - > dev_type ) ;
XmlConfigC cfg1 ;
if ( get_xml_config_by_dev_type ( ied_usr - > dev_type , & cfg1 ) ) {
printf ( " UnitOfTimeUnit = %s \n " , cfg1 . UnitOfTimeUnit ) ;
printf ( " ValueOfTimeUnit = %s \n " , cfg1 . ValueOfTimeUnit ) ;
} else {
printf ( " 读取失败,未找到 dev_type \n " ) ;
}
double s_or_ms ;
long long utc_or_beijing ;
2025-05-21 10:45:44 +08:00
if ( strcmp ( cfg1 . UnitOfTimeUnit , " 1 " ) = = 0 ) { //持续时间上送的是秒1还是毫秒0
2025-05-20 16:31:12 +08:00
s_or_ms = 0.001 ;
}
else {
s_or_ms = 1.0 ;
}
2025-05-21 10:45:44 +08:00
if ( strcmp ( cfg1 . ValueOfTimeUnit , " utc " ) = = 0 ) { //上送的是utc还是北京
2025-05-20 16:31:12 +08:00
utc_or_beijing = 28800000 ;
}
else {
utc_or_beijing = 0 ;
}
/////////////////////////////////////////////////////
2025-01-16 16:17:01 +08:00
//to send json of this qvvr and rdre
2025-05-09 16:53:07 +08:00
end_tm = ( long long ) ( qvvr - > QVVR_PerTime * 1000 ) + trig_tm ; //结束时间是持续时间加触发时间
2025-01-16 16:17:01 +08:00
if ( FILE_FLAG = = 3 ) {
2025-05-09 16:53:07 +08:00
size_t cfg_len = strlen ( uuid_cfg ) + strlen ( filename_cfg ) + 3 ; // 额外的3个字符用于"-"和结束符'\0'
char * cfg_result = ( char * ) malloc ( cfg_len * sizeof ( char ) ) ; // 动态分配足够的内存空间
size_t dat_len = strlen ( uuid_dat ) + strlen ( filename_dat ) + 3 ; // 额外的3个字符用于"-"和结束符'\0'
char * dat_result = ( char * ) malloc ( dat_len * sizeof ( char ) ) ; // 动态分配足够的内存空间
2025-01-16 16:17:01 +08:00
if ( cfg_result ! = NULL & & dat_result ! = NULL ) {
2025-05-09 16:53:07 +08:00
snprintf ( cfg_result , cfg_len , " %s-%s " , uuid_cfg , filename_cfg ) ; // 拼接字符串并确保不会溢出目标缓冲区
snprintf ( dat_result , dat_len , " %s-%s " , uuid_dat , filename_dat ) ; // 拼接字符串并确保不会溢出目标缓冲区
2025-05-20 16:31:12 +08:00
ret3 = transfer_json_qvvr_data ( g_node_id ,
LD_info - > line_id ,
( double ) qvvr - > QVVR_Amg ,
( double ) qvvr - > QVVR_PerTime / s_or_ms , //lnk20250520上送的暂态持续时间为毫秒
start_tm + utc_or_beijing , //lnk20250520上送的暂态时间为北京时间
end_tm + utc_or_beijing , //lnk20250520上送的暂态时间为北京时间
qvvr - > QVVR_type ,
cfg_result ,
dat_result ,
LD_info - > mp_id ,
qvvr - > QVVR_Rptname ,
ied_usr - > dev_type ) ;
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
free ( cfg_result ) ; // 使用完毕后释放动态分配的内存空间
free ( dat_result ) ; // 使用完毕后释放动态分配的内存空间
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
else if ( FILE_FLAG = = 4 ) //lnk20241031发送暂态web消息
2025-01-16 16:17:01 +08:00
{
2025-05-09 16:53:07 +08:00
//内存分配部分不修改
2025-03-10 21:26:17 +08:00
size_t cfg_len = strlen ( wavepath_cfg ) + 1 ;
2025-05-09 16:53:07 +08:00
char * cfg_result = ( char * ) malloc ( cfg_len * sizeof ( char ) ) ; // 动态分配足够的内存空间
2025-03-10 21:26:17 +08:00
size_t dat_len = strlen ( wavepath_dat ) + 1 ;
2025-05-09 16:53:07 +08:00
char * dat_result = ( char * ) malloc ( dat_len * sizeof ( char ) ) ; // 动态分配足够的内存空间
2025-01-16 16:17:01 +08:00
if ( cfg_result ! = NULL & & dat_result ! = NULL ) {
2025-05-09 16:53:07 +08:00
snprintf ( cfg_result , cfg_len , wavepath_cfg ) ; // 拼接字符串并确保不会溢出目标缓冲区
snprintf ( dat_result , dat_len , wavepath_dat ) ; // 拼接字符串并确保不会溢出目标缓冲区
ret3 = transfer_json_qvvr_data ( g_node_id , //这个参数没有使用
LD_info - > line_id , //监测点序号
2025-05-20 16:31:12 +08:00
( double ) qvvr - > QVVR_Amg ,
( double ) qvvr - > QVVR_PerTime / s_or_ms , //lnk20250520上送的暂态持续时间为毫秒
qvvr - > QVVR_time + utc_or_beijing , //lnk20250520上送的暂态时间为北京时间 //这里不使用文件中的开始时间start_tm, 因为会影响写库, 使用QVVR的时间QVVR_time//lnk20250311
end_tm + utc_or_beijing , //lnk20250520上送的暂态时间为北京时间
qvvr - > QVVR_type , //伏值、持续时间、开始时间、结束时间、暂态类型
cfg_result ,
dat_result , //两个文件路径
LD_info - > mp_id ,
qvvr - > QVVR_Rptname ,
ied_usr - > dev_type ) ; //监测点号,文件和监测点暂态事件匹配上的暂态报告名,终端类型
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
free ( cfg_result ) ; // 使用完毕后释放动态分配的内存空间
free ( dat_result ) ; // 使用完毕后释放动态分配的内存空间
2025-01-16 16:17:01 +08:00
}
else if ( FILE_FLAG = = 1 | | FILE_FLAG = = 2 )
{
2025-05-09 16:53:07 +08:00
size_t cfg_len = strlen ( oss_file_fullname_cfg ) + strlen ( cfg_only_filename_ret ) + 3 ; // 额外的3个字符用于"-"和结束符'\0'
char * cfg_result = ( char * ) malloc ( cfg_len * sizeof ( char ) ) ; // 动态分配足够的内存空间
size_t dat_len = strlen ( oss_file_fullname_dat ) + strlen ( dat_only_filename_ret ) + 3 ; // 额外的3个字符用于"-"和结束符'\0'
char * dat_result = ( char * ) malloc ( dat_len * sizeof ( char ) ) ; // 动态分配足够的内存空间
2025-01-16 16:17:01 +08:00
if ( cfg_result ! = NULL & & dat_result ! = NULL ) {
2025-05-09 16:53:07 +08:00
snprintf ( cfg_result , cfg_len , " %s-%s " , oss_file_fullname_cfg , cfg_only_filename_ret ) ; // 拼接字符串并确保不会溢出目标缓冲区
snprintf ( dat_result , dat_len , " %s-%s " , oss_file_fullname_dat , dat_only_filename_ret ) ; // 拼接字符串并确保不会溢出目标缓冲区
2025-05-20 16:31:12 +08:00
ret3 = transfer_json_qvvr_data ( g_node_id ,
LD_info - > line_id ,
( double ) qvvr - > QVVR_Amg ,
( double ) qvvr - > QVVR_PerTime / s_or_ms , //lnk20250520上送的暂态持续时间为毫秒
start_tm + utc_or_beijing , //lnk20250520上送的暂态时间为北京时间
end_tm + utc_or_beijing , //lnk20250520上送的暂态时间为北京时间
qvvr - > QVVR_type ,
cfg_result ,
dat_result ,
LD_info - > mp_id ,
qvvr - > QVVR_Rptname ,
ied_usr - > dev_type ) ;
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
free ( cfg_result ) ; // 使用完毕后释放动态分配的内存空间
free ( dat_result ) ; // 使用完毕后释放动态分配的内存空间
2025-01-16 16:17:01 +08:00
}
2025-05-09 16:53:07 +08:00
/*上传消息*/
qvvr - > used_status = QVVR_DATA_NOT_USED ; //上传信息后这个qvvr的状态置为未使用
2025-01-16 16:17:01 +08:00
free ( uuid_cfg ) ;
free ( uuid_dat ) ;
free ( filename_cfg ) ;
free ( filename_dat ) ;
//lnk 202411-5
free ( wavepath_cfg ) ;
free ( wavepath_dat ) ;
}
}
}
}
else {
2025-05-26 16:51:27 +08:00
if ( ied & & chnl_usr ) {
2025-01-16 16:17:01 +08:00
echo_warn2 ( " mms_mvla_fdir Failed: IED [%d] %s \n " , ied - > id , chnl_usr - > ip_str ) ;
2025-05-26 16:51:27 +08:00
//mq日志
DIY_WARNLOG ( full_key_m_c , " 【WARN】监测点:%s - id:%s召唤录波文件失败 " , LD_info - > name , LD_info - > mp_id ) ;
}
2025-01-16 16:17:01 +08:00
return APR_EAGAIN ;
}
LD_info - > FltNum [ i ] = - 1 ;
}
if ( have_new_files )
clear_old_comtrade_files ( ) ;
return APR_SUCCESS ;
}
2025-05-09 16:53:07 +08:00
//lnk 2024-11-4 添加时间转换函数
2025-03-12 11:45:53 +08:00
char * convertMsToDateTimeString ( int64_t usTime ) {
2025-05-09 16:53:07 +08:00
// 确保时间戳是有效的
2025-03-12 11:45:53 +08:00
if ( usTime < 0 ) {
return " Invalid timestamp " ;
}
2025-05-09 16:53:07 +08:00
// 将 `apr_time_t` 微秒( us) 转换为 `time_t` 秒( s)
2025-03-12 11:45:53 +08:00
time_t seconds = usTime / 1000000 ;
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
// 用 `struct tm` 变量存储时间
2025-03-12 11:45:53 +08:00
struct tm timeInfo ;
2025-05-09 16:53:07 +08:00
// **使用 `localtime_r()` 考虑系统时区**
2025-03-12 11:45:53 +08:00
localtime_r ( & seconds , & timeInfo ) ;
2025-01-16 16:17:01 +08:00
2025-05-09 16:53:07 +08:00
// 静态分配的字符数组存储转换后的字符串
2025-03-12 11:45:53 +08:00
static char buffer [ 30 ] ;
strftime ( buffer , sizeof ( buffer ) , " %Y-%m-%d %H:%M:%S " , & timeInfo ) ;
2025-01-16 16:17:01 +08:00
return buffer ;
}