Files
microser/mms/mmscli_rpt.c

2706 lines
108 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file: $RCSfile: mmscli_rpt.c,v $
* @brief: $IEC 61850 Protocol
*
* @version: $Revision: 1.12 $
* @date: $Date: 2022/11/28 07:13:13 $
* @author: $Author: lizhongming $
* @state: $State: Exp $
*
* @latest: $Id: mmscli_rpt.c,v 1.12 2022/11/28 07:13:13 lizhongming Exp $
*
*/
//$Header: /JoyProject/jspqfe/src/pt61850netd_pqfe/source/mms/mmscli_rpt.c,v 1.12 2022/11/28 07:13:13 lizhongming Exp $
/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 2003 - 2005, All Rights Reserved */
/* */
/* MODULE NAME : cli_rpt.c */
/* PRODUCT(S) : MMSEASE-LITE */
/* */
/* MODULE DESCRIPTION : */
/* Functions to perform "client" processing of IEC-61850 Reports */
/* and UCA Reports received from "servers". */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* rpt_typeids_find */
/* rcb_info_create */
/* rcb_info_destroy */
/* u_iec_rpt_ind */
/* u_iec_rpt_ind_data (user modify or replace) */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 07/22/05 JRB 08 Allow one conn to control multiple RCBs */
/* (user_info must point to ALL_RCB_INFO). */
/* Save varNameArray in rcb_info to use later. */
/* Chg u_iec_rpt_ind_data 4th arg to (RCB_INFO *).*/
/* 12/03/04 JRB 07 Extract domain name of NVL from dataSetName. */
/* Increase RptID length to vstring65. */
/* 08/04/04 EJV 06 rcb_info_create: added typecast for Inclusion*/
/* 06/29/04 JRB 05 Del mvl_tdl_to_type_id & instead use new */
/* mvl_type_id_create_from_tdl. */
/* 05/13/04 JRB 04 Chg SqNum to INT16U to match 61850-7-2. */
/* 01/23/04 JRB 03 Use ms_local_to_text. */
/* 12/17/03 JRB 02 61850-8-1 FDIS changes: */
/* Decode ConfRev in rpt if enabled by OptFlds. */
/* Move SubSeqNum, MoreSegmentsFollow to just */
/* before inclusion bitstring. */
/* Chg OptFlds from bvstring9 to bvstring10. */
/* 10/24/03 JRB 01 New */
/************************************************************************/
#include "rdb_client.h"
#include "db_interface.h"
#include "../json/mms_json_inter.h"
#include "../cfg_parse/custom_printf.h"//lnk20250225
#include "../log4cplus/log4.h"//lnk添加log4 20250526
/************************************************************************/
/* For debug version, use a static pointer to avoid duplication of */
/* __FILE__ strings. */
/************************************************************************/
#ifdef DEBUG_SISCO
SD_CONST static ST_CHAR* SD_CONST thisFileName = __FILE__;
#endif
extern pt61850app_t* g_pt61850app;
extern RPT_TYPEIDS g_rpt_typeids;
//lnk20250115
extern pthread_mutex_t mtx;
/************************************************************************/
/* Global variables. */
/************************************************************************/
/* NONE */
/************************************************************************/
/* Static function prototypes. */
/************************************************************************/
static OBJECT_NAME** nvl_var_name_array_create(MVL_NET_INFO* net_info, ST_CHAR* domName,
ST_CHAR* nvlName, ST_INT* numVarOut, ST_INT timeOut);
static ST_VOID nvl_var_name_array_destroy(OBJECT_NAME** varNameArray, ST_INT numVar);
static ST_INT var_type_create(MVL_NET_INFO* net_info, OBJECT_NAME* varObj,
ST_INT timeOut);
static ST_RET rcb_info_var_create(RCB_INFO* rcb_info, RPT_TYPEIDS* rpt_typeids);
static ST_VOID rcb_info_var_destroy(RCB_INFO* rcb_info);
static ST_VOID log_var_data(MVL_VAR_ASSOC* var, MMS_DECODE_DATA* data);
/* DEBUG: move these functions to library modules? */
OBJECT_NAME* object_name_clone_create(OBJECT_NAME* srcobj);
ST_VOID object_name_clone_destroy(OBJECT_NAME* obj);
static ST_ULONG a_get_rem_ip_addr_inline(ST_LONG acse_conn_id, int* nPort);
static char* _convert_ip_2_char(unsigned long dwIP);
#if 1 //测试 获取服务器IP WW 2023-08-29
static char* _convert_ip_2_char(unsigned long dwIP)
{
static char buf[64] = { 0 };
sprintf(buf, "%d.%d.%d.%d", (dwIP >> 24) & 0xff, (dwIP >> 16) & 0xff, (dwIP >> 8) & 0xff, (dwIP) & 0xff);
return buf;
}
#if defined (TP0_ENABLED)
/************************************************************************/
/* a_get_rem_ip_addr */
/* This function returns the remote IP Address as an unsigned long in */
/* "network byte order", just like the "standard sockets" function */
/* "inet_addr" does. If there is an error, it returns */
/* "htonl (INADDR_NONE)", just like "inet_addr" does. */
/* The return value can be stored in the appropriate union member */
/* in the structure "in_addr", which can be passed to "inet_ntoa". */
/************************************************************************/
#include "tp4.h" /* Need internal TP4 defines */
#include "tp0_sock.h" /* Need "sockets" defines */
#include "acse2.h" /* Need "sockets" defines */
#define MAX_PATH 256
static ST_ULONG get_rem_ip_addr_inline(ST_LONG acse_conn_id, int* nPort)
{
ACSE_CONN *acse_conn;
ST_LONG tp_conn_id;
TP0_CONN *tp0_conn;
ST_INT ret;
SOCKADDR_IN sockaddr_in;
SOCK_ADDRLEN addr_len;
char buf[MAX_PATH] = { 0 };
acse_conn = (ACSE_CONN *)acse_conn_id;
tp_conn_id = acse_conn->tp4_conn_id;
if (tp_conn_id >= MIN_TP0_CONN_ID &&
tp_conn_id < tp0_cfg.max_num_conns + MIN_TP0_CONN_ID)
{ /* Conn id is a legal TP0 conn id */
tp0_conn = &tp0_conn_arr[tp_conn_id - MIN_TP0_CONN_ID];
addr_len = sizeof(SOCKADDR_IN); /* CRITICAL: set to expected len.*/
ret = getpeername(tp0_conn->sock_info->genSock->hSock, (SOCKADDR *)&sockaddr_in, &addr_len);
*nPort = htons(sockaddr_in.sin_port);
if (ret == 0)
return (sockaddr_in.sin_addr.s_addr);
}
return (htonl(INADDR_NONE)); /* something failed */
}
#endif /* defined (TP0_ENABLED) */
#endif
/************************************************************************/
/* rpt_typeids_find */
/* Find ALL types needed for controlling & decoding IEC/UCA reports. */
/* These types must be defined in the ODF file and created by Foundry. */
/* RETURN: SD_SUCCESS or SD_FAILURE (if ANY type is NOT found) */
/* NOTE: this function based on "mvlu_rpt_find_typeids" in "mvlu_rpt.c".*/
/************************************************************************/
ST_RET rpt_typeids_find(RPT_TYPEIDS* rpt_typeids)
{
ST_RET retCode = SD_FAILURE; /* assume FAILURE for now */
ST_CHAR* type_name; /* name of type to be found */
/* stop on any error */
do
{ /* "one-time" loop: just to have something to break out of */
if ((rpt_typeids->mmsbool = mvl_typename_to_typeid(type_name = "RTYP_BOOL")) < 0)
break;
if ((rpt_typeids->bstr6 = mvl_typename_to_typeid(type_name = "RTYP_BSTR6")) < 0)
break;
if ((rpt_typeids->bstr8 = mvl_typename_to_typeid(type_name = "RTYP_BSTR8")) < 0)
break;
if ((rpt_typeids->bstr9 = mvl_typename_to_typeid(type_name = "RTYP_BSTR9")) < 0)
break;
if ((rpt_typeids->bvstring6 = mvl_typename_to_typeid(type_name = "RTYP_BVSTR6")) < 0)
break;
if ((rpt_typeids->bvstring8 = mvl_typename_to_typeid(type_name = "RTYP_BVSTR8")) < 0)
break;
if ((rpt_typeids->bvstring10 = mvl_typename_to_typeid(type_name = "RTYP_BVSTR10")) < 0)
break;
if ((rpt_typeids->btime6 = mvl_typename_to_typeid(type_name = "RTYP_BTIME6")) < 0)
break;
if ((rpt_typeids->int8u = mvl_typename_to_typeid(type_name = "RTYP_INT8U")) < 0)
break;
if ((rpt_typeids->int16u = mvl_typename_to_typeid(type_name = "RTYP_INT16U")) < 0)
break;
if ((rpt_typeids->int32u = mvl_typename_to_typeid(type_name = "RTYP_INT32U")) < 0)
break;
if ((rpt_typeids->ostring8 = mvl_typename_to_typeid(type_name = "RTYP_OSTR8")) < 0)
break;
if ((rpt_typeids->vstring32 = mvl_typename_to_typeid(type_name = "RTYP_VSTR32")) < 0)
break;
if ((rpt_typeids->vstring65 = mvl_typename_to_typeid(type_name = "RTYP_VSTR65")) < 0)
break;
retCode = SD_SUCCESS; /* If we get here, all were successful */
} while (0); /* end of "one-time" loop */
if (retCode)
MVL_LOG_ERR1("Can't find type '%s'", type_name);
return (retCode); /* If ANY find failed, SD_FAILURE is returned */
}
/************************************************************************/
/* rcb_info_create */
/************************************************************************/
RCB_INFO* rcb_info_create(MVL_NET_INFO* net_info, ST_CHAR* domName,
ST_CHAR* rcbName, RPT_TYPEIDS* rpt_typeids, ST_INT timeOut)
{
RCB_INFO* rcb_info;
ST_CHAR varName[MAX_IDENT_LEN + 1];
ST_CHAR datSetName[65 + 1]; /* data set name (Vstring65) */
ST_CHAR datdomName[65 + 1]; /* data set name (Vstring65) */
ST_CHAR RptID[65 + 1]; /* RptID (Vstring65) */
ST_CHAR* nvlName;
ST_INT numDsVar; /* num variables in NVL */
OBJECT_NAME** varNameArray; /* array of variable names in NVL */
ST_INT j;
size_t extended_size;
ST_CHAR* extended_ptr;
ST_CHAR InclusionTdl[30]; /* place to create TDL for inclusion bstr*/
ST_RET status = SD_SUCCESS; /* set to SD_FAILURE if anything fails. */
ST_CHAR* nvlDomName;
ST_INT rcb_type;
assert(rpt_typeids->mmsbool || rpt_typeids->int8u); /* make sure global struct initialized*/
/* Read "RptID" from the server & save in "RptID" local variable. */
/* Copy to "rcb_info" struct later. */
strcpy(varName, rcbName);
strcat(varName, "$RptID");
if (mms_named_var_read(net_info, varName, DOM_SPEC, domName, rpt_typeids->vstring65, RptID, timeOut))
{
echo_warn2("Error reading RptID '%s' in domain '%s'\n", varName, domName);
return (NULL);
}
/* Figure out RCB type from 'rcbName'. */
if (strstr(rcbName, "$BR$") != NULL)
rcb_type = RCB_TYPE_IEC_BRCB;
else if (strstr(rcbName, "$RP$") != NULL)
{
/* This could be IEC URCB or UCA URCB. Only IEC contains "Resv" attr.*/
/* Try to read "Resv". If successful, RCB is IEC_URCB, else it is UCA.*/
/* NOTE: "RptID" read was successful, so we know this RCB exists. */
ST_BOOLEAN tmpResv;
strcpy(varName, rcbName);
strcat(varName, "$Resv");
if (mms_named_var_read(net_info, varName, DOM_SPEC, domName, rpt_typeids->mmsbool, &tmpResv, timeOut) == SD_SUCCESS)
rcb_type = RCB_TYPE_IEC_URCB;
else
rcb_type = RCB_TYPE_UCA;
}
else
{
echo_warn1("RCB name '%s' invalid. Must contain 'BR' or 'RP'.\n", rcbName);
return (NULL);
}
/* Read "DatSet" from the server. */
strcpy(varName, rcbName);
strcat(varName, "$DatSet");
if (mms_named_var_read(net_info, varName, DOM_SPEC, domName, rpt_typeids->vstring65, datSetName, timeOut))
{ /* can't read data set name */
echo_warn2("Error reading data set name ('%s' in domain '%s')\n", varName, domName);
return (NULL);
}
/* datSetName should now be set */
strcpy(datdomName, datSetName);//WW 2023-10-23
nvlDomName = strtok(datdomName, "/");/* extract domain name of NVL */
nvlName = strtok(NULL, ""); /* extract NVL name */
if (nvlName == NULL) /* "/" not found */
{
echo_warn1("datSetName '%s' invalid. Does not contain '/' character.", datSetName);
return (NULL);
}
/* Get NVL Attributes from the server */
/* NOTE: Resources allocated by this funct are freed by calling */
/* nvl_var_name_array_destroy (called from rcb_info_destroy). */
varNameArray = nvl_var_name_array_create(net_info, nvlDomName, nvlName, &numDsVar, timeOut);
if (varNameArray == NULL)
{
echo_warn2("GetNamedVariableListAttributes request failed for '%s' in domain '%s'",
nvlName, domName);
return (NULL);
}
/* Allocate RCB_INFO structure plus extra room for additional data
* that depends on "numDsVar". This effectively combines 8 allocations into one.
* Set pointers in RCB_INFO structure to point into the extra space.
* CRITICAL: use chk_calloc to start with clean structure
*/
extended_size = sizeof(RCB_INFO)
+ numDsVar * sizeof(ST_INT) /* rcb_info->typeIdArr */
+ numDsVar * sizeof(MVL_VAR_ASSOC*) /* rcb_info->rcb_var.dataRefName*/
+ numDsVar * sizeof(MVL_VAR_ASSOC*) /* rcb_info->rcb_var.dataValue */
+ numDsVar * sizeof(MVL_VAR_ASSOC*) /* rcb_info->rcb_var.Reason */
+ numDsVar * 66 /* rcb_info->rcb_data.dataRefName*/
+ numDsVar * sizeof(MMS_BVSTRING) /* rcb_info->rcb_data.Reason */
+ BSTR_NUMBITS_TO_NUMBYTES(numDsVar); /* rcb_info->rcb_data.Inclusion */
rcb_info = (RCB_INFO*)chk_calloc(1, extended_size);
strcpy(rcb_info->dom_Name, domName); //WW 2023-08-29 逻辑设备名称
strcpy(rcb_info->rcb_name, rcbName); //WW 2023-08-29 报告控制块名称
//////////////////////////////////////////////////////////////////////////
strcpy(rcb_info->ds_Nam, datSetName); //WW 2023-08-29 数据集名称
//////////////////////////////////////////////////////////////////////////
echo_msg4("Client RCB info 0x%X created for '%s' in domain '%s'.datasetnam '%s' \n", rcb_info, rcbName, domName, datSetName);
extended_ptr = (ST_CHAR*)(rcb_info + 1); /* point after RCB_INFO struct */
rcb_info->typeIdArr = (ST_INT*)extended_ptr;
extended_ptr += numDsVar * sizeof(ST_INT); /* point after rcb_info->typeIdArr*/
rcb_info->rcb_var.dataRefName = (MVL_VAR_ASSOC**)extended_ptr;
extended_ptr += numDsVar * sizeof(MVL_VAR_ASSOC*); /* rcb_info->rcb_var.dataRefName*/
rcb_info->rcb_var.dataValue = (MVL_VAR_ASSOC**)extended_ptr;
extended_ptr += numDsVar * sizeof(MVL_VAR_ASSOC*); /* rcb_info->rcb_var.dataValue */
rcb_info->rcb_var.Reason = (MVL_VAR_ASSOC**)extended_ptr;
extended_ptr += numDsVar * sizeof(MVL_VAR_ASSOC*); /* rcb_info->rcb_var.Reason */
rcb_info->rcb_data.dataRefName = extended_ptr;
extended_ptr += numDsVar * 66; /* rcb_info->rcb_data.dataRefName*/
rcb_info->rcb_data.Reason = (MMS_BVSTRING*)extended_ptr;
extended_ptr += numDsVar * sizeof(MMS_BVSTRING); /* rcb_info->rcb_data.Reason */
rcb_info->rcb_data.Inclusion = (ST_UINT8*)extended_ptr;
extended_ptr += BSTR_NUMBITS_TO_NUMBYTES(numDsVar); /* rcb_info->rcb_data.Inclusion */
/* Make sure we computed sizes correctly. */
assert(extended_ptr == (ST_CHAR*)rcb_info + extended_size);
/* Fill in other rcb_info structure members. */
rcb_info->rcb_type = rcb_type;
strcpy(rcb_info->RptID, RptID); /* save RptID to compare when RPTs received*/
rcb_info->varNameArray = varNameArray;
rcb_info->numDsVar = numDsVar;
/* Create all necessary types. */
/* Try to create all types even if one fails. */
/* This way, we can later destroy all without remembering which */
/* were successfully created. */
/* Create a Type for the Inclusion bitstring. Save it in "rcb_info->InclusionTypeid" */
apr_snprintf(InclusionTdl, sizeof(InclusionTdl), "Bstring%d", rcb_info->numDsVar);
rcb_info->InclusionTypeid = mvl_type_id_create_from_tdl(NULL, InclusionTdl);
if (rcb_info->InclusionTypeid < 0)
{
echo_warn("Error - could not add type for 'Inclusion'.");
status = SD_FAILURE;
}
/* Create types and fill in rcb_info->typeIdArr */
/* Start with all set to invalid, so if some fail, cleanup is easier. */
for (j = 0; j < numDsVar; j++)
rcb_info->typeIdArr[j] = -1; /* invalid type_id */
for (j = 0; j < numDsVar; j++)
{
if ((rcb_info->typeIdArr[j] = var_type_create(net_info, varNameArray[j], timeOut))
< 0)
{ /* couldn't create this type, so stop */
echo_warn1("Error creating type for variable '%s'",
varNameArray[j]->obj_name.vmd_spec);
status = SD_FAILURE;
break;
}
}
if (status == SD_SUCCESS)
{
/* Types created OK, so create variables */
status = rcb_info_var_create(rcb_info, rpt_typeids); /* returns SD_SUCCESS or SD_FAILURE*/
}
if (status != SD_SUCCESS)
{ /* something failed. Destroy anything created. */
rcb_info_destroy(rcb_info);
rcb_info = NULL;
}
return (rcb_info);
}
/************************************************************************/
/* rcb_info_destroy */
/************************************************************************/
ST_VOID rcb_info_destroy(RCB_INFO* rcb_info)
{
ST_INT j;
/* Free up array of variable names saved in rcb_info_create */
nvl_var_name_array_destroy(rcb_info->varNameArray, rcb_info->numDsVar);
/* Destroy all variables. */
rcb_info_var_destroy(rcb_info);
/* Destroy "Inclusion" Type (this should be AFTER destroying "Inclusion" Variable).*/
if (rcb_info->InclusionTypeid > 0) /* 0=never created. -1=error */
mvl_type_id_destroy(rcb_info->InclusionTypeid);
/* Destroy "dataValue" Types (this should be AFTER destroying "dataValue" variables). */
for (j = 0; j < rcb_info->numDsVar; j++)
{
/* All types were initialized to -1. They are also set to -1 if create failed.*/
/* Only destroy types that are NOT (-1). */
if (rcb_info->typeIdArr[j] >= 0)
mvl_type_id_destroy(rcb_info->typeIdArr[j]);
}
chk_free(rcb_info);
echo_warn1("Client RCB info 0x%X destroyed", rcb_info);
}
/************************************************************************/
/* nvl_var_name_array_create */
/* Send a GetNamedVariableListAttributes request to get a list of */
/* variable names in a NamedVariableList (NVL). */
/* Assume the NVL is domain-specific */
/* RETURN: ptr to array of ptrs to variable names (OBJECT_NAME structs).*/
/* Also the variable pointed to by numVarOut contains the number*/
/* of variables in the NVL. */
/* NOTE: this function allocates memory for the (OBJECT_NAME *) array. */
/* Call "nvl_var_name_array_destroy" to free the memory. */
/************************************************************************/
static OBJECT_NAME** nvl_var_name_array_create(MVL_NET_INFO* net_info, ST_CHAR* domName, ST_CHAR* nvlName,
ST_INT* numVarOut,
ST_INT timeOut)
{
MVL_REQ_PEND* reqCtrl;
GETVLIST_REQ_INFO getvlist_req;
GETVLIST_RESP_INFO* getvlist_resp; /* set to reqCtrl->u.getvlist_resp_info*/
VARIABLE_LIST* variable_list;
OBJECT_NAME** varNameArray; /* Ptr to array of ptrs to var names */
ST_RET ret; /* general purpose return code */
ST_INT j;
getvlist_req.vl_name.object_tag = DOM_SPEC;
getvlist_req.vl_name.domain_id = domName;
getvlist_req.vl_name.obj_name.vmd_spec = nvlName;
ret = mvla_getvlist(net_info, &getvlist_req, &reqCtrl);
if (ret == SD_SUCCESS)
ret = waitReqDone(reqCtrl, timeOut);
if (ret != SD_SUCCESS)
{
echo_warn1("mvla_getvlist Error = 0x%X.", ret);
varNameArray = NULL;
}
else
{
getvlist_resp = reqCtrl->u.getvlist.resp_info;
variable_list = (VARIABLE_LIST*)(getvlist_resp + 1);
/* Allocate array of variable names. */
*numVarOut = getvlist_resp->num_of_variables;
varNameArray = (OBJECT_NAME**)chk_malloc(getvlist_resp->num_of_variables * sizeof(OBJECT_NAME*));
/* Copy info from response to allocated array */
for (j = 0; j < getvlist_resp->num_of_variables; j++, variable_list++)
{
/* Assume all variables are named. */
assert(variable_list->var_spec.var_spec_tag == VA_SPEC_NAMED);
varNameArray[j] = object_name_clone_create(&variable_list->var_spec.vs.name);
}
}
mvl_free_req_ctrl(reqCtrl); /* CRITICAL: */
return (varNameArray);
}
/************************************************************************/
/* nvl_var_name_array_destroy */
/* Free up all resources allocated by "nvl_var_name_array_create". */
/************************************************************************/
static ST_VOID nvl_var_name_array_destroy(OBJECT_NAME** varNameArray, ST_INT numVar)
{
ST_INT j;
for (j = 0; j < numVar; j++)
object_name_clone_destroy(varNameArray[j]);
chk_free(varNameArray);
}
/************************************************************************/
/* var_type_create */
/* Send GetVariableAccessAttributes request. Wait for response. When */
/* response received, create new type. Pass NULL as type_name arg to */
/* "mvl_type_id_create" (this avoids the problem of duplicate names). */
/* RETURN: Type ID */
/* NOTE: Call "mvl_type_id_destroy" to destroy the type created here. */
/************************************************************************/
static ST_INT var_type_create(MVL_NET_INFO* net_info, OBJECT_NAME* varObj,
ST_INT timeOut)
{
MVL_REQ_PEND* reqCtrl;
GETVAR_REQ_INFO getvar_req;
VAR_ACC_TSPEC* type_spec;
ST_INT type_id = -1; /* invalid. If anything fails, this value returned*/
ST_RET ret;
getvar_req.req_tag = GETVAR_NAME;
getvar_req.name = *varObj;
/* Send GetVariableAccessAttributes request & wait for response. */
ret = mvla_getvar(net_info, &getvar_req, &reqCtrl);
if (ret == SD_SUCCESS)
ret = waitReqDone(reqCtrl, timeOut);
if (ret != SD_SUCCESS)
echo_warn1("GetVariableAccessAttributes error = 0x%x.", ret);
else
{
type_spec = &reqCtrl->u.getvar.resp_info->type_spec;
/* First arg (type_name) is NULL to avoid duplicate names. */
type_id = mvl_type_id_create(NULL, type_spec->data, type_spec->len);
}
mvl_free_req_ctrl(reqCtrl);
return (type_id);
}
/************************************************************************/
/* rcb_info_var_create */
/* Create dummy variables to be used later when a report is received. */
/* These variables are needed to decode the data received in a report. */
/* This function fills in "rcb_info->rcb_data" and "rcb_info->rcb_var". */
/************************************************************************/
static ST_RET rcb_info_var_create(RCB_INFO* rcb_info, RPT_TYPEIDS* rpt_typeids)
{
OBJECT_NAME dummyvar_objname; /* dummy variable object name */
ST_INT j;
ST_INT incSize; /* num bytes for inclusion bitstring */
/* CRITICAL: "mvl_var_create" is used (NOT "mvl_var_add") to create
* local variables to store data received later in IEC/UCA Reports.
* These are NOT real variables, so remote MMS nodes cannot access them.
* All variables use the same name (dummyvar): that's OK because
* "mvl_var_create" does NOT add them to the database and nothing needs
* to use the name.
*/
/* NOTE: last arg to mvl_var_create is always SD_FALSE, so the name is
* NOT copied. This is OK because all names here are fixed strings.
*/
/* Set up one OBJECT_NAME to use for all variables. */
dummyvar_objname.object_tag = VMD_SPEC;
dummyvar_objname.obj_name.vmd_spec = "dummyvar"; /* all vars use same name */
if ((rcb_info->rcb_var.RptID = mvl_var_create(&dummyvar_objname, rpt_typeids->vstring65,
&rcb_info->rcb_data.RptID, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.OptFlds = mvl_var_create(&dummyvar_objname, rpt_typeids->bvstring10,
&rcb_info->rcb_data.OptFlds, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.SqNum = mvl_var_create(&dummyvar_objname, rpt_typeids->int16u,
&rcb_info->rcb_data.SqNum, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.TimeOfEntry = mvl_var_create(&dummyvar_objname, rpt_typeids->btime6,
&rcb_info->rcb_data.TimeOfEntry, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.DatSetNa = mvl_var_create(&dummyvar_objname, rpt_typeids->vstring65,
&rcb_info->rcb_data.DatSetNa, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.BufOvfl = mvl_var_create(&dummyvar_objname, rpt_typeids->mmsbool,
&rcb_info->rcb_data.BufOvfl, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.SubSeqNum = mvl_var_create(&dummyvar_objname, rpt_typeids->int16u,
&rcb_info->rcb_data.SubSeqNum, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.MoreSegmentsFollow = mvl_var_create(&dummyvar_objname, rpt_typeids->mmsbool,
&rcb_info->rcb_data.MoreSegmentsFollow, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.EntryID = mvl_var_create(&dummyvar_objname, rpt_typeids->ostring8,
&rcb_info->rcb_data.EntryID, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
if ((rcb_info->rcb_var.ConfRev = mvl_var_create(&dummyvar_objname, rpt_typeids->int32u,
&rcb_info->rcb_data.ConfRev, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
incSize = BSTR_NUMBITS_TO_NUMBYTES(rcb_info->numDsVar);
/* Note: rcb_info->rcb_data.Inclusion is a "ptr" to data, so don't add "&". */
if ((rcb_info->rcb_var.Inclusion = mvl_var_create(&dummyvar_objname, rcb_info->InclusionTypeid,
rcb_info->rcb_data.Inclusion, NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
/* Allocate array of DataRefName (vstring65) */
/* & array of (MVL_VAR_ASSOC *). */
/* Can't alloc array of strings, so we just allocate one big buffer */
/* and use [j*66] to find postion for each string in the buffer. */
/* Create separate variable for each array entry. */
for (j = 0; j < rcb_info->numDsVar; j++)
{
if ((rcb_info->rcb_var.dataRefName[j] = mvl_var_create(&dummyvar_objname, rpt_typeids->vstring65,
&rcb_info->rcb_data.dataRefName[j * 66], NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
}
/* Create variable for each DataSet variable. */
for (j = 0; j < rcb_info->numDsVar; j++)
{
ST_VOID* remote_data; /* buffer to store remote data */
MVL_TYPE_CTRL* type_ctrl;
type_ctrl = mvl_type_ctrl_find(rcb_info->typeIdArr[j]);
assert(type_ctrl); /* find should never fail */
/* Allocate buffer to store remote data. */
remote_data = chk_malloc(type_ctrl->data_size);
if ((rcb_info->rcb_var.dataValue[j] = mvl_var_create(&dummyvar_objname,
rcb_info->typeIdArr[j], /* Use type just created */
remote_data, /* buffer for data */
NULL, /* proc funs */
SD_FALSE)) /* DON'T copy name */
== NULL)
{ /* couldn't create this variable, so stop */
return (SD_FAILURE);
}
}
/* Allocate array of Reason (bstr6)(one byte for each Reason) */
/* & array of (MVL_VAR_ASSOC *). */
/* Create separate variable for each array entry. */
for (j = 0; j < rcb_info->numDsVar; j++)
{
/* Use bvstring8 because IEC sends bstr6 and UCA sends bstr8. */
if ((rcb_info->rcb_var.Reason[j] = mvl_var_create(&dummyvar_objname, rpt_typeids->bvstring8,
&rcb_info->rcb_data.Reason[j], NULL, SD_FALSE)) == NULL)
return (SD_FAILURE);
}
/* If we get this far, everything was successful. */
return (SD_SUCCESS);
}
/************************************************************************/
/* rcb_info_var_destroy */
/* Destroy everything created in "rcb_info_var_create". */
/* Check that each was successfully creating before destroying. Any one */
/* of the "mvl_var_create" calls in "rcb_info_var_create" may have failed.*/
/************************************************************************/
static ST_VOID rcb_info_var_destroy(RCB_INFO* rcb_info)
{
ST_INT j;
if (rcb_info->rcb_var.RptID)
mvl_var_destroy(rcb_info->rcb_var.RptID);
if (rcb_info->rcb_var.OptFlds)
mvl_var_destroy(rcb_info->rcb_var.OptFlds);
if (rcb_info->rcb_var.SqNum)
mvl_var_destroy(rcb_info->rcb_var.SqNum);
if (rcb_info->rcb_var.TimeOfEntry)
mvl_var_destroy(rcb_info->rcb_var.TimeOfEntry);
if (rcb_info->rcb_var.DatSetNa)
mvl_var_destroy(rcb_info->rcb_var.DatSetNa);
if (rcb_info->rcb_var.BufOvfl)
mvl_var_destroy(rcb_info->rcb_var.BufOvfl);
if (rcb_info->rcb_var.SubSeqNum)
mvl_var_destroy(rcb_info->rcb_var.SubSeqNum);
if (rcb_info->rcb_var.MoreSegmentsFollow)
mvl_var_destroy(rcb_info->rcb_var.MoreSegmentsFollow);
if (rcb_info->rcb_var.EntryID)
mvl_var_destroy(rcb_info->rcb_var.EntryID);
if (rcb_info->rcb_var.ConfRev)
mvl_var_destroy(rcb_info->rcb_var.ConfRev);
if (rcb_info->rcb_var.Inclusion)
mvl_var_destroy(rcb_info->rcb_var.Inclusion);
/* Destroy "dataRefName" variables. */
for (j = 0; j < rcb_info->numDsVar; j++)
{
if (rcb_info->rcb_var.dataRefName[j])
mvl_var_destroy(rcb_info->rcb_var.dataRefName[j]);
}
/* Destroy "dataValue" variables. */
for (j = 0; j < rcb_info->numDsVar; j++)
{
if (rcb_info->rcb_var.dataValue[j] != NULL)
{
chk_free(rcb_info->rcb_var.dataValue[j]->data);
mvl_var_destroy(rcb_info->rcb_var.dataValue[j]);
}
}
/* Destroy "Reason" variables. */
for (j = 0; j < rcb_info->numDsVar; j++)
{
if (rcb_info->rcb_var.Reason[j])
mvl_var_destroy(rcb_info->rcb_var.Reason[j]);
}
}
/************************************************************************/
/* This sample function sets some options and enables the RCB. */
/* If any write fails, stop. */
/* If more options needed, add more arguments to this function. */
/************************************************************************/
ST_RET rcb_enable(MVL_NET_INFO* netInfo, ST_CHAR* domName,
ST_CHAR* rcbName, ST_UCHAR* OptFlds, ST_UCHAR* TrgOps,
ST_UINT32 IntgPd, RPT_TYPEIDS* rpt_typeids, ST_INT timeOut)
{
ST_BOOLEAN RptEna = 1; /* 1 = enable the report */
ST_RET ret = SD_SUCCESS;
ST_CHAR varName[MAX_IDENT_LEN + 1];
//if (ret == SD_SUCCESS)
//{
// apr_snprintf (varName,sizeof(varName),"%s$IntgPd", rcbName);
// ret = mms_named_var_write (netInfo, varName, DOM_SPEC, domName, rpt_typeids->int32u, (ST_CHAR *) &IntgPd, timeOut);
//}
if (ret == SD_SUCCESS)
{
/* NOTE: only write 9 bits. 10th bit (segmentation) is read-only. */
apr_snprintf(varName, sizeof(varName), "%s$OptFlds", rcbName);
ret = mms_named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->bstr9, OptFlds, timeOut);
}
if (ret == SD_SUCCESS)
{
apr_snprintf(varName, sizeof(varName), "%s$TrgOps", rcbName);
ret = mms_named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->bstr6, TrgOps, timeOut);
if (ret != SD_SUCCESS) {
printf("%s Write Error!!!", varName);
echo_warn1("Report注册 %s Write Error!!!", varName);
}
}
#if 0 /* Add something like this if other options needed. ???????? BufTm 等??*/
if (ret == SD_SUCCESS)
{
apr_snprintf(varName, sizeof(varName), "%s$Trgs", rcbName);
ret = mms_named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->int16u, (ST_CHAR*)&Trgs, timeOut);
}
#endif
if (ret == SD_SUCCESS)
{
apr_snprintf(varName, sizeof(varName), "%s$RptEna", rcbName);
ret = mms_named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->mmsbool, (ST_CHAR*)&RptEna, timeOut);
}
return (ret);
}
ST_RET rcb_disable(MVL_NET_INFO* netInfo, ST_CHAR* domName,
ST_CHAR* rcbName, RPT_TYPEIDS* rpt_typeids, ST_INT timeOut)
{
ST_BOOLEAN RptEna = 0; /* 0 = disable the report */
ST_UINT32 IntgPd = 0;
ST_RET ret = SD_SUCCESS;
ST_CHAR varName[MAX_IDENT_LEN + 1];
if (ret == SD_SUCCESS)
{
apr_snprintf(varName, sizeof(varName), "%s$RptEna", rcbName);
ret = mms_named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->mmsbool, (ST_CHAR*)&RptEna, timeOut);
}
if (ret == SD_SUCCESS)
{
apr_snprintf(varName, sizeof(varName), "%s$IntgPd", rcbName);
ret = mms_named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->int32u, (ST_CHAR*)&IntgPd, timeOut);
}
return (ret);
}
/************************************************************************/
/************************************************************************/
static ST_VOID log_var_data(MVL_VAR_ASSOC* var, MMS_DECODE_DATA* data)
{
ST_CHAR tdl_buf[500]; /* increase size if complex TDL expected*/
MVL_TYPE_CTRL* type_ctrl;
type_ctrl = mvl_type_ctrl_find(var->type_id);
if (type_ctrl)
{
/* If the TDL produced is longer than max_tdl_len, this function */
/* "gracefully" fails (i.e. returns 0). */
if (ms_runtime_to_tdl(type_ctrl->rt, type_ctrl->num_rt, tdl_buf, sizeof(tdl_buf)) > 0)
;//SLOGCALWAYS1 (" TYPE: %s", tdl_buf);
else
echo_warn(" TYPE: unknown");
//printf ("\nTYPE: %s \n", tdl_buf);
//printf("type_ctrl->num_rt %d %x %x \n", type_ctrl->num_rt , &data, &(var->data));
my_local_to_data((ST_CHAR*)var->data, type_ctrl->rt, type_ctrl->num_rt, data);
if (data->item_num == 0) {
echo_warn("!!!!!!!!!!!!!!!!!!!data num is 0 !!!!!!!!!!!!!!!!\n");
}
}
else
echo_warn(" ERR: type_id is invalid");
}
/************************************************************************/
/* u_iec_rpt_ind_data */
/* User function to process the received report data. This example */
/* function simply writes the data to the log file. */
/* */
/* It should be easy to modify or rewrite this function to do whatever */
/* is appropriate for your application. */
/************************************************************************/
ST_VOID u_iec_rpt_ind_data_by_devtype(MVL_VAR_ASSOC** info_va,
ST_UINT8* OptFldsData, /* ptr to data part of OptFlds bvstring */
ST_UINT8* InclusionData, /* ptr to Inclusion bstring */
RCB_INFO* rcb_info,
ST_INT va_total,
MVL_NET_INFO* net_info)
{
ST_INT va_num = 0;
ST_INT j;
MMS_DECODE_DATA mms_dec_data;
//uint32_t add_mms_dec_data = &mms_dec_data;
ied_t* ied;
rptinfo_t* rptinfo;
// element_t* pDataOMSObject;
LD_info_t* LD_info;
chnl_usr_t* chnl_usr;
char** DataObjectFullName;
// LD_info_t* LD_info_of_Data;
ST_INT not_set_rpt_TimeID_this;
ST_INT not_set_rpt_q_this;
//printf("Var# %02d: RptId", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
rptinfo = find_rptinfo_from_net_rpt_info_name(net_info, rcb_info);
//rptinfo->m_LastDataTime = sGetMsTime();//WW 2023-08-29 去除
LD_info = rptinfo->LD_info;
chnl_usr = net_info->user_ext;
ied = chnl_usr->chnl->ied;
not_set_rpt_TimeID_this = TRUE;
not_set_rpt_q_this = TRUE;
//g_db_inf_clear_data(RPT_IDX);
rptinfo->count++;
printf("[BEGIND Process] Received Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count);
//mq日志
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】前置收到监测点:%s - id:%s的报告,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
//apr_time_t previousTime = apr_time_now();//
//apr_time_exp_t localTime;
//apr_time_exp_gmt(&localTime, previousTime);
//printf("\n ------>>>>>>> begind time %d %d:%d:%d.%d \n",
// localTime.tm_mday, localTime.tm_hour, localTime.tm_min, localTime.tm_sec, localTime.tm_usec);
va_num++;
// SLOGCALWAYS1("Var# %02d: OptFlds", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
/* NOTE: Don't change initial entries in "info_va". Add these right after "OptFlds".*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SQNUM))
{
// SLOGCALWAYS1("Var# %02d: SqNum", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
printf("\n ------>>>>>>> SqNum received in Report From %s %s %s ,SqNum = %d \n",
chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID, mms_dec_data.data_item[0].u.data_uint);
va_num++;
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_TIMESTAMP))
{
// SLOGCALWAYS1("Var# %02d: TimeOfEntry", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
//set_rpt_TimeID(convert_btime6_to_apr_time(&(mms_dec_data.data_item[0].u.data_bTime6)) );
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATSETNAME))
{
// SLOGCALWAYS1("Var# %02d: DatSetNa", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_BUFOVFL))
{
// SLOGCALWAYS1("Var# %02d: BufOvfl", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_ENTRYID))
{
char* EntryIDStr;
int i;
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
EntryIDStr = mms_dec_data.data_item[0].u.data_str;
printf("\n ------>>>>>>> EntryID received in Report From %s %s %s ,EntryID = %s\n\n\n",
chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID, EntryIDStr);
for (i = 0; i < 8; i++) {
EntryIDStr[2] = '\0';
rptinfo->m_EntryID[i] = (byte_t)strtol(EntryIDStr, NULL, 16);
EntryIDStr += 3; //skip a blank
}
va_num++;
}
printf("\n -------------rptinfo->m_EntryID %02x %02x %02x %02x %02x %02x %02x %02x -------- EntryID\n\n\n",
*rptinfo->m_EntryID, *(rptinfo->m_EntryID + 1), *(rptinfo->m_EntryID + 2),
*(rptinfo->m_EntryID + 3), *(rptinfo->m_EntryID + 4), *(rptinfo->m_EntryID + 5),
*(rptinfo->m_EntryID + 6), *(rptinfo->m_EntryID + 7));
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_CONFREV))
{
// SLOGCALWAYS1("Var# %02d: ConfRev", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
//printf("\n ----1--va_num %d -\n", va_num);
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SUBSEQNUM))
{
// SLOGCALWAYS1("Var# %02d: SubSeqNum", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
// SLOGCALWAYS1("Var# %02d: MoreSegmentsFollow", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
//printf("\n ----2---va_num %d \n", va_num);
// SLOGCALWAYS1("Var# %02d: Inclusion", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
/* If data-Ref enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATAREF))
{
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j))
{
// SLOGCALWAYS2("Var# %02d: DataRefName# %d", va_num, j);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
}
}
//printf("\n ----3---%d \n", va_num);
//rcb_info->numDsVar+1 just to avoid rcb_info->numDsVar==0 ,waste a little memory
DataObjectFullName = apr_pcalloc(g_pt61850app->tmp_pool, (rcb_info->numDsVar + 1) * sizeof(char*));
//RWCStringVec DataName(rcb_info->numDsVar+1);
//RWCStringVec AttrName(rcb_info->numDsVar+1);
//RWTValVector<CDataOMSObject*> pDataOMSObjects(rcb_info->numDsVar+1);
//printf("\n ----4--%d rcb_info->numDsVar %d -\n", va_num, rcb_info->numDsVar);
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j))
{
DataObjectFullName[j] = apr_pstrdup(g_pt61850app->tmp_pool, rcb_info->varNameArray[j]->obj_name.vmd_spec);
}
}
//printf("\n ----5--%d-\n", va_num);
// if (g_pt61850app->IsCallEvtDes )
// cout<<"pEquipment->m_OMSObject_FULL_FCDA_Map.entries() = "<<pEquipment->m_OMSObject_FULL_FCDA_Map.entries()<<endl
//assert(0);
if (LD_info->line_id > 0) {
if (strstr(rcb_info->RptID, "QVVR"))//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
processQVVR_start(LD_info);
else if (strstr(rcb_info->RptID, "RDRE"))//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_start(LD_info);
else {
ied_t* ied;
ied = find_ied_from_dev_code(LD_info->terminal_code);
ied_usr_t* ied_usr = (ied_usr_t*)ied->usr_ext;
if (rptinfo->flickerflag==1)//CZY 2023-08-17 WW 2022-11-14 只有闪变和第一次进入才会初始化 json_block_create_start(LD_info->line_id);
json_block_create_start( LD_info->voltage_level, LD_info->mp_id, rptinfo->flickerflag, ied_usr->dev_type, LD_info->line_id);
else if(rptinfo->flickerflag == 0) {
if (LD_info->rptRecvCheckFlag == 0)
json_block_create_start( LD_info->voltage_level, LD_info->mp_id, rptinfo->flickerflag, ied_usr->dev_type, LD_info->line_id);
LD_info->rptRecvCheckFlag |= 0x01 << rptinfo->rptNo;
}
else if (rptinfo->flickerflag == 2) {
if (LD_info->rptPstRecvCheckFlag == 0)
json_block_create_start(LD_info->voltage_level, LD_info->mp_id, rptinfo->flickerflag, ied_usr->dev_type, LD_info->line_id);
LD_info->rptPstRecvCheckFlag |= 0x01 << rptinfo->rptNo;
}
}
}
/* HERE'S THE DATA. Check "Inclusion" to figure out what is being received.*/
for (j = 0; j < rcb_info->numDsVar; ++j)
{
/*if (rcb_info->numDsVar==13) {
printf("bbbbbbbbbbbbbbbbbbbbbbbbb\n");
}*/
if (BSTR_BIT_GET(InclusionData, j))
{
int ii;
// SLOGCALWAYS3("Var# %02d: DataSet Var# %d: Name=%s", va_num, j,
// rcb_info->varNameArray[j]->obj_name.vmd_spec);
//printf("\n ----5.0--%d-\n", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
//printf("\n ----5.1--%d-%d\n", va_num,mms_dec_data.item_num);
// if ( !pDataOMSObjects[j] ) continue;
//cout<<endl<<j<<" $ "<<AttrName[j]<<" $ "<<DataName[j]<<" = ";
//cout<<endl<<j<<" "<<DataObjectFullName[j]<<" "<<endl;
// cout<<" mms_dec_data.item_num ="<<(int)mms_dec_data.item_num<<endl;
for (ii = 0; ii < mms_dec_data.item_num; ++ii)
{
char* FULL_FCDA_Name;
int length_FCDA;
//printf("\n ----5.11--%d-%s\n", va_num, mms_dec_data.data_item[ii].comp_name);
if (strcmp(mms_dec_data.data_item[ii].comp_name, "") == 0)
FULL_FCDA_Name = apr_pstrdup(g_pt61850app->tmp_pool, DataObjectFullName[j]);
else
FULL_FCDA_Name = apr_pstrcat(g_pt61850app->tmp_pool, DataObjectFullName[j], "$", mms_dec_data.data_item[ii].comp_name, NULL);
// cout<<" FULL_FCDA_Name "<< FULL_FCDA_Name <<endl;
//printf("\n ----5.12--%d- %s \n", va_num, FULL_FCDA_Name);
length_FCDA = strlen(FULL_FCDA_Name);
//11 08 beijing 许继装置不处理q
if (('$' == FULL_FCDA_Name[length_FCDA - 2]) && ('q' == FULL_FCDA_Name[length_FCDA - 1])) {
if (not_set_rpt_q_this) {
int flag = Set_q_from_61850rpt(mms_dec_data.data_item[ii].u.data_str);
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
//need do nothing!
not_set_rpt_q_this = FALSE;
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
//need do nothing!
not_set_rpt_q_this = FALSE;
}
else {
json_block_create_flag(LD_info->mp_id, flag, rptinfo->flickerflag);
not_set_rpt_q_this = FALSE;
}
}
}
else if (('$' == FULL_FCDA_Name[length_FCDA - 2]) && ('t' == FULL_FCDA_Name[length_FCDA - 1])) {
if (not_set_rpt_TimeID_this) {
apr_time_t t = convert_btime6_to_apr_time(&(mms_dec_data.data_item[ii].u.data_bTime6));//微秒
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
if (strstr(FULL_FCDA_Name, "VarStr$t")) {
processQVVR_time(LD_info, t / 1000);//毫秒
not_set_rpt_TimeID_this = FALSE;
}
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
//need do nothing!
not_set_rpt_TimeID_this = FALSE;
}
else {
json_block_create_time(LD_info->mp_id, t / 1000, rptinfo->flickerflag);
printf("rcb_info->RptID=%s ,LineId=%d , Timestamp= %lld \n", rcb_info->RptID, LD_info->line_id, t / 1000);
not_set_rpt_TimeID_this = FALSE;
/*if (strstr(rcb_info->RptID, "LLN0$RP$urcbRealData")) {//lnk 20250624
//20241223lnk添加终端号参数
ied_usr_t *ied_usr = GET_IEDEXT_ADDR(ied);
if (urcbRealDataHasReceived(ied_usr->dev_idx,LD_info, t / 1000))
return;
}*/
}
}
}
else {
double v = 0.0;
if (mms_dec_data.data_item[ii].type == DATA_INT_TYPE)
v = mms_dec_data.data_item[ii].u.data_int;
else if (mms_dec_data.data_item[ii].type == DATA_UINT_TYPE)
v = mms_dec_data.data_item[ii].u.data_uint;
else if (mms_dec_data.data_item[ii].type == DATA_INT64_TYPE)
v = (double)mms_dec_data.data_item[ii].u.data_int64;
else if (mms_dec_data.data_item[ii].type == DATA_UINT64_TYPE)
v = (double)mms_dec_data.data_item[ii].u.data_uint64;
else if (mms_dec_data.data_item[ii].type == DATA_DOUBLE_TYPE)
v = mms_dec_data.data_item[ii].u.data_double;
else if (mms_dec_data.data_item[ii].type == DATA_STR_TYPE)
v = strtol(mms_dec_data.data_item[ii].u.data_str, NULL, 2);
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
processQVVR_data(LD_info, FULL_FCDA_Name, v);
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_data(LD_info, FULL_FCDA_Name, v);
}
else
json_block_create_data(LD_info->mp_id, FULL_FCDA_Name, v, rptinfo->flickerflag);
}//else
}
}
}
if (LD_info->line_id > 0) {
//set_rpt_LineID(LD_info->line_id);
//set_line_info(RPT_IDX,LD_info->line_id,LD_info->SubV_Index,LD_info->Dev_Index,LD_info->Sub_Index,LD_info->GD_Index);
//write_updatetime_to_db(chnl_usr->chnl->addr);
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
processQVVR_end(LD_info);
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_end(LD_info);
}
else {
printf("%d : %d", LD_info->rptRecvFlag, LD_info->rptRecvCheckFlag);
//append_db_records(RPT_IDX);
if (rptinfo->flickerflag==1)//CZY 2023-08-17 WW 2022-11-14 增加闪变标志
{
//ied_usr_t* ied_usr = ied->usr_ext;//CZY 2023-08-17 WW 2022年12月6日14:09:08 增加多个ICD支持
//int devkind = ied_usr->dev_flag;
json_block_create_end(LD_info->v_wiring_type, LD_info->mp_id, rptinfo->flickerflag); //lnk2024-8-16增加接线类型参数
}
else if(rptinfo->flickerflag == 0){//CZY 2023-08-17 WW 2022-11-14 增加多个报告判断
if (LD_info->rptRecvFlag == LD_info->rptRecvCheckFlag) {
//ied_usr_t* ied_usr = ied->usr_ext;//CZY 2023-08-17 WW 2022年12月6日14:09:08 增加多个ICD支持
//int devkind = ied_usr->dev_flag;
json_block_create_end(LD_info->v_wiring_type, LD_info->mp_id, rptinfo->flickerflag); //lnk2024-8-16增加接线类型参数
LD_info->rptRecvCheckFlag = 0;
}
}
else if (rptinfo->flickerflag == 2) {//CZY 2023-08-17 WW 2022-11-14 增加多个报告判断
if (LD_info->rptPstRecvFlag == LD_info->rptPstRecvCheckFlag) {
//ied_usr_t* ied_usr = ied->usr_ext;//CZY 2023-08-17 WW 2022年12月6日14:09:08 增加多个ICD支持
//int devkind = ied_usr->dev_flag;
json_block_create_end(LD_info->v_wiring_type, LD_info->mp_id, rptinfo->flickerflag); //lnk2024-8-16增加接线类型参数
LD_info->rptPstRecvCheckFlag = 0;
}
}
}
}
else {
echo_err3("Ignore this report due to line_id invalid , Report From %s %s %s !!!",
APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID);
//mq日志
DIY_ERRORLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【ERROR】前置不处理这个监测点:%s - id:%s的报告,报告名称:%s,原因是监测点的序号非法", LD_info->name,LD_info->mp_id,rcb_info->RptID);
}
printf("[END Process] Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count);
//mq日志
DIY_INFOLOG_CODE(LD_info->mp_id,2,LOG_CODE_REPORT,"【NORMAL】前置处理监测点:%s - id:%s的报告结束,报告名称:%s,监测点对应终端的ip和端口是: %s:%d,报告总数:%i,当前报告数:%i", LD_info->name,LD_info->mp_id,rcb_info->RptID,chnl_usr->ip_str,chnl_usr->chnl->port,va_total, rptinfo->count);
//apr_time_t previousTimeend = apr_time_now();//
//apr_time_exp_t localTimeend;
//apr_time_exp_gmt(&localTimeend, previousTimeend);
//printf("\n ------>>>>>>> end time %d %d:%d:%d.%d \n",
// localTimeend.tm_mday, localTimeend.tm_hour, localTimeend.tm_min, localTimeend.tm_sec, localTimeend.tm_usec);
//printf("\n ----6-%d--\n", va_num);
/* If "reason" enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_REASON)) {
for (j = 0; j < rcb_info->numDsVar; ++j) {
if (BSTR_BIT_GET(InclusionData, j)) {
// SLOGCALWAYS2("Var# %02d: Reason# %d", va_num, j);
//log_var_data (info_va[va_num],&mms_dec_data);
va_num++;
}
}
}
//设置响应时间,避免频繁召唤装置名称,导致丢包 add on Aug 3 for testing of guangdong CRITICAL
chnl_usr->m_LastPosRespTime = sGetMsTime();
//assert (va_num==va_total); /* Did we count right? */
if (va_num != va_total)
echo_err5("va_num!=va_total! Report From %s %s %s , %d!=%d !!!",
APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID, va_num, va_total);
}
//lnk 20250624匹配不同的实时控制块
const char* extractAfterUrCb(const char* rptID) {
if (!rptID) return "N/A";
// 查找 "urcb"(区分大小写)
const char* pos = strstr(rptID, "urcb");
if (!pos) return "N/A"; // 如果没有 urcb
return pos + 4; // 返回 "urcb" 后面的部分指针
}
//lnk
ST_VOID u_iec_rpt_ind_data(MVL_VAR_ASSOC** info_va,
ST_UINT8* OptFldsData, /* ptr to data part of OptFlds bvstring */
ST_UINT8* InclusionData, /* ptr to Inclusion bstring */
RCB_INFO* rcb_info,
ST_INT va_total,
MVL_NET_INFO* net_info)
{
ST_INT va_num = 0;
ST_INT j;
MMS_DECODE_DATA mms_dec_data;
//uint32_t add_mms_dec_data = &mms_dec_data;
ied_t* ied;
rptinfo_t* rptinfo;
// element_t* pDataOMSObject;
LD_info_t* LD_info;
chnl_usr_t* chnl_usr;
char** DataObjectFullName;
// LD_info_t* LD_info_of_Data;
ST_INT not_set_rpt_TimeID_this;
ST_INT not_set_rpt_q_this;
//printf("Var# %02d: RptId", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
rptinfo = find_rptinfo_from_net_rcb_info(net_info, rcb_info);
//rptinfo->m_LastDataTime = sGetMsTime();//WW 2023-08-29 去除
LD_info = rptinfo->LD_info;
chnl_usr = net_info->user_ext;
ied = chnl_usr->chnl->ied;
not_set_rpt_TimeID_this = TRUE;
not_set_rpt_q_this = TRUE;
//g_db_inf_clear_data(RPT_IDX);
rptinfo->count++;
printf("[BEGIND Process] Received Report From %s:%d %s %s ,va_total = %i ,【count = %i】 mp_id=%s\n",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count, LD_info->mp_id);
//apr_time_t previousTime = apr_time_now();//
//apr_time_exp_t localTime;
//apr_time_exp_gmt(&localTime, previousTime);
//printf("\n ------>>>>>>> begind time %d %d:%d:%d.%d \n",
// localTime.tm_mday, localTime.tm_hour, localTime.tm_min, localTime.tm_sec, localTime.tm_usec);
va_num++;
// SLOGCALWAYS1("Var# %02d: OptFlds", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
/* NOTE: Don't change initial entries in "info_va". Add these right after "OptFlds".*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SQNUM))
{
// SLOGCALWAYS1("Var# %02d: SqNum", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
printf("\n ------>>>>>>> SqNum received in Report From %s %s %s ,SqNum = %d \n",
chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID, mms_dec_data.data_item[0].u.data_uint);
va_num++;
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_TIMESTAMP))
{
// SLOGCALWAYS1("Var# %02d: TimeOfEntry", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
//set_rpt_TimeID(convert_btime6_to_apr_time(&(mms_dec_data.data_item[0].u.data_bTime6)) );
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATSETNAME))
{
// SLOGCALWAYS1("Var# %02d: DatSetNa", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_BUFOVFL))
{
// SLOGCALWAYS1("Var# %02d: BufOvfl", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_ENTRYID))
{
char* EntryIDStr;
int i;
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
EntryIDStr = mms_dec_data.data_item[0].u.data_str;
printf("\n ------>>>>>>> EntryID received in Report From %s %s %s ,EntryID = %s\n\n\n",
chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID, EntryIDStr);
for (i = 0; i < 8; i++) {
EntryIDStr[2] = '\0';
rptinfo->m_EntryID[i] = (byte_t)strtol(EntryIDStr, NULL, 16);
EntryIDStr += 3; //skip a blank
}
va_num++;
}
printf("\n -------------rptinfo->m_EntryID %02x %02x %02x %02x %02x %02x %02x %02x -------- EntryID\n\n\n",
*rptinfo->m_EntryID, *(rptinfo->m_EntryID + 1), *(rptinfo->m_EntryID + 2),
*(rptinfo->m_EntryID + 3), *(rptinfo->m_EntryID + 4), *(rptinfo->m_EntryID + 5),
*(rptinfo->m_EntryID + 6), *(rptinfo->m_EntryID + 7));
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_CONFREV))
{
// SLOGCALWAYS1("Var# %02d: ConfRev", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
//printf("\n ----1--va_num %d -\n", va_num);
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SUBSEQNUM))
{
// SLOGCALWAYS1("Var# %02d: SubSeqNum", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
// SLOGCALWAYS1("Var# %02d: MoreSegmentsFollow", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
//printf("\n ----2---va_num %d \n", va_num);
// SLOGCALWAYS1("Var# %02d: Inclusion", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
/* If data-Ref enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATAREF))
{
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j))
{
// SLOGCALWAYS2("Var# %02d: DataRefName# %d", va_num, j);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
}
}
}
//printf("\n ----3---%d \n", va_num);
//rcb_info->numDsVar+1 just to avoid rcb_info->numDsVar==0 ,waste a little memory
DataObjectFullName = apr_pcalloc(g_pt61850app->tmp_pool, (rcb_info->numDsVar + 1) * sizeof(char*));
//RWCStringVec DataName(rcb_info->numDsVar+1);
//RWCStringVec AttrName(rcb_info->numDsVar+1);
//RWTValVector<CDataOMSObject*> pDataOMSObjects(rcb_info->numDsVar+1);
//printf("\n ----4--%d rcb_info->numDsVar %d -\n", va_num, rcb_info->numDsVar);
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j))
{
DataObjectFullName[j] = apr_pstrdup(g_pt61850app->tmp_pool, rcb_info->varNameArray[j]->obj_name.vmd_spec);
}
}
//printf("\n ----5--%d-\n", va_num);
// if (g_pt61850app->IsCallEvtDes )
// cout<<"pEquipment->m_OMSObject_FULL_FCDA_Map.entries() = "<<pEquipment->m_OMSObject_FULL_FCDA_Map.entries()<<endl
//assert(0);
if (LD_info->line_id > 0) {
if (strstr(rcb_info->RptID, "QVVR"))//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
processQVVR_start(LD_info);//上送的报告里面的监测点号
else if (strstr(rcb_info->RptID, "RDRE"))//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_start(LD_info);
else {
ied_t* ied;
ied = find_ied_from_dev_code(LD_info->terminal_code);
ied_usr_t* ied_usr = (ied_usr_t*)ied->usr_ext;
if (rptinfo->flickerflag == 1)//CZY 2023-08-17 WW 2022-11-14 只有闪变和第一次进入才会初始化 json_block_create_start(LD_info->line_id);
json_block_create_start(LD_info->voltage_level, LD_info->mp_id, rptinfo->flickerflag, ied_usr->dev_type, LD_info->line_id);
else if (rptinfo->flickerflag == 0) {
if (LD_info->rptRecvCheckFlag == 0)
json_block_create_start(LD_info->voltage_level, LD_info->mp_id, rptinfo->flickerflag, ied_usr->dev_type, LD_info->line_id);
LD_info->rptRecvCheckFlag |= 0x01 << rptinfo->rptNo;
}
else if (rptinfo->flickerflag == 2) {
if (LD_info->rptPstRecvCheckFlag == 0)
json_block_create_start(LD_info->voltage_level, LD_info->mp_id, rptinfo->flickerflag, ied_usr->dev_type, LD_info->line_id);
LD_info->rptPstRecvCheckFlag |= 0x01 << rptinfo->rptNo;
printf("LD_info->rptPstRecvCheckFlag=%d",LD_info->rptPstRecvCheckFlag);
}
}
}
/* HERE'S THE DATA. Check "Inclusion" to figure out what is being received.*/
for (j = 0; j < rcb_info->numDsVar; ++j)
{
/*if (rcb_info->numDsVar==13) {
printf("bbbbbbbbbbbbbbbbbbbbbbbbb\n");
}*/
if (BSTR_BIT_GET(InclusionData, j))
{
int ii;
// SLOGCALWAYS3("Var# %02d: DataSet Var# %d: Name=%s", va_num, j,
// rcb_info->varNameArray[j]->obj_name.vmd_spec);
//printf("\n ----5.0--%d-\n", va_num);
log_var_data(info_va[va_num], &mms_dec_data);
//assert(add_mms_dec_data== (uint32_t)&mms_dec_data);
va_num++;
//printf("\n ----5.1--%d-%d\n", va_num,mms_dec_data.item_num);
// if ( !pDataOMSObjects[j] ) continue;
//cout<<endl<<j<<" $ "<<AttrName[j]<<" $ "<<DataName[j]<<" = ";
//cout<<endl<<j<<" "<<DataObjectFullName[j]<<" "<<endl;
// cout<<" mms_dec_data.item_num ="<<(int)mms_dec_data.item_num<<endl;
long long time;
for (ii = 0; ii < mms_dec_data.item_num; ++ii)
{
char* FULL_FCDA_Name;
int length_FCDA;
if (strcmp(mms_dec_data.data_item[ii].comp_name, "") == 0)
FULL_FCDA_Name = apr_pstrdup(g_pt61850app->tmp_pool, DataObjectFullName[j]);
else
FULL_FCDA_Name = apr_pstrcat(g_pt61850app->tmp_pool, DataObjectFullName[j], "$", mms_dec_data.data_item[ii].comp_name, NULL);
length_FCDA = strlen(FULL_FCDA_Name);
if (('$' == FULL_FCDA_Name[length_FCDA - 2]) && ('t' == FULL_FCDA_Name[length_FCDA - 1]))
{
apr_time_t t = convert_btime6_to_apr_time(&(mms_dec_data.data_item[ii].u.data_bTime6));
time = t / 1000;
break;
}
}
for (ii = 0; ii < mms_dec_data.item_num; ++ii)//遍历FCDA
{
char* FULL_FCDA_Name;
int length_FCDA;
//printf("\n ----5.11--%d-%s\n", va_num, mms_dec_data.data_item[ii].comp_name);
if (strcmp(mms_dec_data.data_item[ii].comp_name, "") == 0)
FULL_FCDA_Name = apr_pstrdup(g_pt61850app->tmp_pool, DataObjectFullName[j]);
else
FULL_FCDA_Name = apr_pstrcat(g_pt61850app->tmp_pool, DataObjectFullName[j], "$", mms_dec_data.data_item[ii].comp_name, NULL);
// cout<<" FULL_FCDA_Name "<< FULL_FCDA_Name <<endl;
//printf("\n ----5.12--%d- %s \n", va_num, FULL_FCDA_Name);
length_FCDA = strlen(FULL_FCDA_Name);
//11 08 beijing 许继装置不处理q
if (('$' == FULL_FCDA_Name[length_FCDA - 2]) && ('q' == FULL_FCDA_Name[length_FCDA - 1])) {
if (not_set_rpt_q_this) {
int flag = Set_q_from_61850rpt(mms_dec_data.data_item[ii].u.data_str);
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
//need do nothing!
not_set_rpt_q_this = FALSE;
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
//need do nothing!
not_set_rpt_q_this = FALSE;
}
else if (strstr(FULL_FCDA_Name, "GGIO"))
{
not_set_rpt_q_this = FALSE;
}
else {
json_block_create_flag(LD_info->mp_id, flag, rptinfo->flickerflag);
not_set_rpt_q_this = FALSE;
}
}
}
else if (('$' == FULL_FCDA_Name[length_FCDA - 2]) && ('t' == FULL_FCDA_Name[length_FCDA - 1])) {
if (not_set_rpt_TimeID_this) {
apr_time_t t = convert_btime6_to_apr_time(&(mms_dec_data.data_item[ii].u.data_bTime6));
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
if (strstr(FULL_FCDA_Name, "VarStr$t")) {
processQVVR_time(LD_info, t / 1000);
not_set_rpt_TimeID_this = FALSE;
}
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
//need do nothing!
not_set_rpt_TimeID_this = FALSE;
}
else if (strstr(FULL_FCDA_Name, "GGIO")) {//CZY 2023-08-17 WW 2022-11-14修改判断 LLN0$BR$brcbRDRE
//need do nothing!
not_set_rpt_TimeID_this = FALSE;
}
else {
json_block_create_time(LD_info->mp_id, t / 1000, rptinfo->flickerflag);
printf("rcb_info->RptID=%s ,LineId=%d , Timestamp= %lld \n", rcb_info->RptID, LD_info->line_id, t / 1000);
not_set_rpt_TimeID_this = FALSE;
//if (strstr(rcb_info->RptID, "LLN0$RP$urcbRealData")) {
int rpt_no;
//20241223lnk添加终端号参数
ied_usr_t *ied_usr = GET_IEDEXT_ADDR(ied);
for(rpt_no=0 ; rpt_no<LD_info->rptcount; rpt_no++) {//实时数据的每份报告都进行时间判断lnk20250624
printf("LD_info->rptinfo[%d]->rptID=%s ",rpt_no,LD_info->rptinfo[rpt_no]->rptID);
if(strstr(rcb_info->RptID,extractAfterUrCb(LD_info->rptinfo[rpt_no]->rptID ))){
printf("rtdata RptID match");
if (urcbRealDataHasReceived(ied_usr->dev_idx,rpt_no,LD_info, t / 1000)){//判断时间重复
printf("this rt report Time repeats");
return;
}
}
}
}
}
}
else {
double v = 0.0;
if (mms_dec_data.data_item[ii].type == DATA_INT_TYPE)
v = mms_dec_data.data_item[ii].u.data_int;
else if (mms_dec_data.data_item[ii].type == DATA_UINT_TYPE)
v = mms_dec_data.data_item[ii].u.data_uint;
else if (mms_dec_data.data_item[ii].type == DATA_INT64_TYPE)
v = (double)mms_dec_data.data_item[ii].u.data_int64;
else if (mms_dec_data.data_item[ii].type == DATA_UINT64_TYPE)
v = (double)mms_dec_data.data_item[ii].u.data_uint64;
else if (mms_dec_data.data_item[ii].type == DATA_DOUBLE_TYPE)
v = mms_dec_data.data_item[ii].u.data_double;
else if (mms_dec_data.data_item[ii].type == DATA_STR_TYPE)
v = strtol(mms_dec_data.data_item[ii].u.data_str, NULL, 2);
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
processQVVR_data(LD_info, FULL_FCDA_Name, v);
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_data(LD_info, FULL_FCDA_Name, v);
}
else if (strstr(FULL_FCDA_Name, "GGIO") || strstr(FULL_FCDA_Name, "LPHD"))
{
ied_t* ied = LD_info->ied;
ied_usr_t* ied_usr = GET_IEDEXT_ADDR(ied);
processGGIO_start_data_end(LD_info->mp_id, FULL_FCDA_Name, v, time, ied_usr->dev_type, LD_info->line_id);//GGIO数据全套处理流程
}
else
json_block_create_data(LD_info->mp_id, FULL_FCDA_Name, v, rptinfo->flickerflag);
}//else
}
}
}
if (LD_info->line_id > 0) {
//set_rpt_LineID(LD_info->line_id);
//set_line_info(RPT_IDX,LD_info->line_id,LD_info->SubV_Index,LD_info->Dev_Index,LD_info->Sub_Index,LD_info->GD_Index);
//write_updatetime_to_db(chnl_usr->chnl->addr);
if (strstr(rcb_info->RptID, "QVVR")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbQVVR
processQVVR_end(LD_info);
}
else if (strstr(rcb_info->RptID, "RDRE")) {//CZY 2023-08-17 WW 2022-11-14 修改判断LLN0$BR$brcbRDRE
processRDRE_end(LD_info);
}
else {
printf("%d : %d", LD_info->rptRecvFlag, LD_info->rptRecvCheckFlag);
//append_db_records(RPT_IDX);
if (rptinfo->flickerflag == 1)//CZY 2023-08-17 WW 2022-11-14 增加闪变标志
{
//ied_usr_t* ied_usr = ied->usr_ext;//CZY 2023-08-17 WW 2022年12月6日14:09:08 增加多个ICD支持
//int devkind = ied_usr->dev_flag;
json_block_create_end(LD_info->v_wiring_type, LD_info->mp_id, rptinfo->flickerflag);//lnk角形处理
}
else if (rptinfo->flickerflag == 0) {//CZY 2023-08-17 WW 2022-11-14 增加多个报告判断
if (LD_info->rptRecvFlag == LD_info->rptRecvCheckFlag) {
//LD_info->rptRecvFlag是报告初始化时报告序号左移之和固定于报告初始化
//ied_usr_t* ied_usr = ied->usr_ext;//CZY 2023-08-17 WW 2022年12月6日14:09:08 增加多个ICD支持
//int devkind = ied_usr->dev_flag;
json_block_create_end(LD_info->v_wiring_type, LD_info->mp_id, rptinfo->flickerflag);//lnk角形处理
LD_info->rptRecvCheckFlag = 0;
}
}
else if (rptinfo->flickerflag == 2) {//CZY 2023-08-17 WW 2022-11-14 增加多个报告判断
if (LD_info->rptPstRecvFlag == LD_info->rptPstRecvCheckFlag) {
//ied_usr_t* ied_usr = ied->usr_ext;//CZY 2023-08-17 WW 2022年12月6日14:09:08 增加多个ICD支持
//int devkind = ied_usr->dev_flag;
json_block_create_end(LD_info->v_wiring_type, LD_info->mp_id, rptinfo->flickerflag);//lnk角形处理
LD_info->rptPstRecvCheckFlag = 0;
}
}
}
}
else {
echo_err3("Ignore this report due to line_id invalid , Report From %s %s %s !!!",
APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID);
}
printf("[END Process] Report From %s:%d %s %s ,va_total = %i ,【count = %i】 \n",
chnl_usr->ip_str, chnl_usr->chnl->port, LD_info->LD_name, rcb_info->RptID, va_total, rptinfo->count);
//apr_time_t previousTimeend = apr_time_now();//
//apr_time_exp_t localTimeend;
//apr_time_exp_gmt(&localTimeend, previousTimeend);
//printf("\n ------>>>>>>> end time %d %d:%d:%d.%d \n",
// localTimeend.tm_mday, localTimeend.tm_hour, localTimeend.tm_min, localTimeend.tm_sec, localTimeend.tm_usec);
//printf("\n ----6-%d--\n", va_num);
/* If "reason" enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_REASON)) {
for (j = 0; j < rcb_info->numDsVar; ++j) {
if (BSTR_BIT_GET(InclusionData, j)) {
// SLOGCALWAYS2("Var# %02d: Reason# %d", va_num, j);
//log_var_data (info_va[va_num],&mms_dec_data);
va_num++;
}
}
}
//设置响应时间,避免频繁召唤装置名称,导致丢包 add on Aug 3 for testing of guangdong CRITICAL
chnl_usr->m_LastPosRespTime = sGetMsTime();
//assert (va_num==va_total); /* Did we count right? */
if (va_num != va_total)
echo_err5("va_num!=va_total! Report From %s %s %s , %d!=%d !!!",
APR_EGENERAL, chnl_usr->ip_str, LD_info->LD_name, rcb_info->RptID, va_num, va_total);
}
/************************************************************************/
/* object_name_clone_create */
/* Create clone of OBJECT_NAME struct. Can't just copy struct because */
/* struct contains pointers to strings. */
/* The function "object_name_clone_destroy" should be called to destroy */
/* the clone. */
/************************************************************************/
OBJECT_NAME* object_name_clone_create(OBJECT_NAME* srcobj)
{
OBJECT_NAME* dstobj;
size_t extended_size;
ST_CHAR* extended_ptr;
/* Allocate OBJECT_NAME structure plus extra room for additional data.
* This effectively combines 3 allocations into one.
* Set pointers in OBJECT_NAME structure to point into the extra space.
*/
extended_size = sizeof(OBJECT_NAME)
+ MAX_IDENT_LEN + 1 /* dstobj->obj_name.vmd_spec */
+ MAX_IDENT_LEN + 1; /* dstobj->domain_id */
dstobj = (OBJECT_NAME*)chk_malloc(extended_size);
/* Copy old struct to new struct (before setting ptrs in new struct). */
memcpy(dstobj, srcobj, sizeof(OBJECT_NAME));
/* Fix ptrs to strings in new struct */
extended_ptr = (ST_CHAR*)(dstobj + 1); /* point after dstobj struct */
dstobj->obj_name.vmd_spec = extended_ptr;
extended_ptr += (MAX_IDENT_LEN + 1); /* point after dstobj->obj_name.vmd_spec*/
dstobj->domain_id = extended_ptr;
/* Copy strings to the new struct. */
strcpy(dstobj->obj_name.vmd_spec, srcobj->obj_name.vmd_spec);
if (dstobj->object_tag == DOM_SPEC)
strcpy(dstobj->domain_id, srcobj->domain_id);
return (dstobj);
}
/************************************************************************/
/* object_name_clone_destroy */
/* Destroy OBJECT_NAME clone created by "object_name_clone_create". */
/************************************************************************/
ST_VOID object_name_clone_destroy(OBJECT_NAME* obj)
{
/* allocated by object_name_clone_create using chk_malloc, so use chk_free.*/
chk_free(obj);
}
ST_RET check_va_count_too_big(ST_INT va_current_count, ST_INT va_total)
{
if (va_current_count < va_total) {
return SD_SUCCESS;
}
else {
echo_warn1("report va total %d is so small,may be error\n", va_total);
return SD_FAILURE;
}
}
/************************************************************************/
/* u_iec_rpt_ind */
/* This function processes ONLY IEC-61850 and UCA Reports. If any */
/* other InformationReport is received, it logs an error message and */
/* ignores it. */
/* CRITICAL: this function assumes that a pointer to an ALL_RCB_INFO */
/* structure has been saved in the */
/* user_info member of the MVL_NET_INFO structure for this conn. */
/************************************************************************/
ST_RET u_iec_rpt_ind_by_devtype(MVL_COMM_EVENT* event)
{
INFO_REQ_INFO* info_ptr;
ST_INT j, va_num, va_total;
VAR_ACC_SPEC* va_spec;
MVL_VAR_ASSOC** info_va;
RCB_INFO* rcb_info;
ST_UINT8* OptFldsData; /* ptr to data part of OptFlds bvstring */
ST_UINT8* InclusionData; /* ptr to Inclusion bstring */
ST_CHAR saveRptID[66];
ALL_RCB_INFO* all_rcb_info;
ST_RET retcode = SD_SUCCESS;
info_ptr = (INFO_REQ_INFO*)event->u.mms.dec_rslt.data_ptr;
va_spec = &info_ptr->va_spec;
va_total = info_ptr->num_of_acc_result;
/* An IEC-61850 or UCA report must be a NamedVariableList named "RPT".
* Ignore any other InformationReport.
*/
if (va_spec->var_acc_tag != VAR_ACC_NAMEDLIST
|| strcmp(va_spec->vl_name.obj_name.vmd_spec, "RPT") != 0)
{
echo_warn("Received InformationReport is not a IEC-61850 Report or UCA Report. Ignored.");
return (SD_FAILURE);
}
//////////////////
//WW 2023-08-29 增加终端类型与报告rcb_info绑定代码
int port; //端口
RCB_INFO *rcb_info1;
ST_CHAR rptID[MVL61850_MAX_RPTID_LEN + 1] = { 0 }; //报告ID 66
ST_ULONG a_ip = get_rem_ip_addr_inline(event->net_info->acse_conn_id, &port); //WW 2023-08-29 获取装置IP、端口号
ST_CHAR *p_ip = _convert_ip_2_char(htonl(a_ip)); //WW 2023-08-29 将IP转为字符串指针 例192.168.1.238
if (gDev_rcb_list.dev_rcb_info_Head == NULL) //全局报告控制块指针 || gDev_rcb_list->rcb_info_list == NULL
{
//SLOGALWAYS0 ("Received InformationReport. No IEC-61850 or UCA RCB enabled. Ignored.");
//LOG_INFO("收到报告未启用IEC-61850或UCA RCB使能。忽略"); //仅调试使用! zl 2019-1-23 09:10:39
return (SD_FAILURE);
}
//逻辑根据装置IP、端口号先找到装置类型再匹配报告信息再解析报告2019-12-24 17:27:29
//装置类型查找判断------------------------------------------------------------------------------------------------------------------------------
Dev_RCB_INFO *dev_rcb = NULL;//装置报告结构指针
Dev_IP_Port_INFO *dev_info = NULL; //装置IP、端口号结构指针
ST_BOOLEAN bFindIpPort = 0; //是否在链表中匹配到装置IP、端口号
for (dev_rcb = gDev_rcb_list.dev_rcb_info_Head; dev_rcb != NULL; dev_rcb = (Dev_RCB_INFO *)list_get_next(gDev_rcb_list.dev_rcb_info_Head, dev_rcb)) //①遍历 全局装置报告控制块链表
{
//LOG_INFO("(报告解析)遍历gDev_rcb_list链表, dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:16:31
//装置IP、端口号查找判断-------------------------------------------------------------------------------------------------------------------------------------------------------------------
for (dev_info = dev_rcb->dev_ip_port_list; dev_info != NULL; dev_info = (Dev_IP_Port_INFO *)list_get_next(dev_rcb->dev_ip_port_list, dev_info)) //②遍历 全局装置IP、端口链表
{
//LOG_INFO("(报告解析)遍历dev_ip_port_list链表, dev_type_name= %s, ip= %s, port= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:16:31
if ((strcmp(dev_info->IP, p_ip) == 0) && (dev_info->Port == port)) //匹配 装置IP && 端口号
{
bFindIpPort = 1; //查找到装置IP && 端口号
//LOG_INFO("(报告解析)匹配到装置dev_type_name= %s, IP= %sPort= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:23:55
//strcpy(dev_rcb->dev_type_name, dev_rcb->dev_type_name); //匹配 装置类型
break;
}
} //遍历 装置IP、端口链表 结束
if (bFindIpPort) //在链表中匹配到装置IP、端口号
break;
} //遍历 全局装置报告控制块链表 结束
if (!bFindIpPort) //未查找到装置IP、端口
{
//LOG_INFO("(报告解析)dev_type_name= %s未匹配到IP= %sPort= %d的装置类型goto CLEANUP跳出", dev_rcb->dev_type_name, p_ip, port); //仅调试使用! zl 2019-12-24 00:23:55
retcode = SD_FAILURE;
goto END; //跳转至 CLEANUP返回retcode结束
}
rcb_info = dev_rcb->rcb_info_list; //根据装置类型,匹配报告控制块信息
//WW 2023-08-29 end
//////////////////////////////
/* Get "all_rcb_info" from "user_info". User must set "user_info" when conn established.*/
//////////////////////
//WW 2023-08-29注释
//all_rcb_info = (ALL_RCB_INFO*)event->net_info->user_info;
///* Check "all_rcb_info" to see if any RCB has been enabled. */
//if (all_rcb_info == NULL || all_rcb_info->rcb_info_list == NULL)
//{
// echo_warn("Received InformationReport. No IEC-61850 or UCA RCB enabled. Ignored.");
// return (SD_FAILURE);
//}
//WW 2023-08-29 end
////////////////////////
/* Create array of (MVL_VAR_ASSOC *) needed for converting the received
* data to local format.
* Use variables created earlier to fill in the array. These variables will
* hold the decoded data.
* NOTE: any return after this must free info_va (see CLEANUP label).
*/
info_va = (MVL_VAR_ASSOC**)chk_calloc(va_total,
sizeof(MVL_VAR_ASSOC*));
//////////////////
//WW 2023-08-29 增加终端类型与报告rcb_info绑定代码
rcb_info = dev_rcb->rcb_info_list; //根据装置类型,匹配报告控制块信息
va_num = 0;
info_va[va_num++] = rcb_info->rcb_var.RptID;
//LOG_INFO("va_num = %d", va_num); //仅调试使用! zl 2019-1-23 09:10:39
all_rcb_info = (ALL_RCB_INFO*)chk_calloc(1, sizeof(ALL_RCB_INFO));
all_rcb_info->rpt_typeids = &g_rpt_typeids;
all_rcb_info->rcb_info_list = dev_rcb->rcb_info_list;
event->net_info->user_info = all_rcb_info;
rcb_info = all_rcb_info->rcb_info_list;
rcb_info->rcb_data.RptID[0] = '\0'; /* start with empty string */
mvl_info_data_to_local(event, va_num, info_va); //将报告数据转换为本地格式
/* NOTE: decoded RptID is now in "rcb_info->rcb_data.RptID". Save it.*/
strcpy(saveRptID, rcb_info->rcb_data.RptID); //装置上送报告ID 例PQM2/LLN0$BR$brcbStatisticData01
//LOG_INFO("装置上送报告saveRptID%s", saveRptID); //仅调试使用! zl 2019-1-23 09:10:39
chk_free(all_rcb_info);
event->net_info->user_info = NULL;
/* Search list of "rcb_info" to find one with matching RptID. If not found, rcb_info will be == NULL. */
//装置报告控制块查找判断-----------------------------------------------------------------------------------------------------------------------------------------------------
for (rcb_info = dev_rcb->rcb_info_list; rcb_info != NULL; rcb_info = (RCB_INFO *)list_get_next(dev_rcb->rcb_info_list, rcb_info)) //遍历 全局报告控制块链表
{
//LOG_INFO("遍历报告控制块链表RptID%ssaveRptID%s", rcb_info->RptID, saveRptID); //仅调试使用! zl 2019-1-23 09:10:39
if (strcmp(rcb_info->RptID, saveRptID) == 0)
break; /* rcb_info now points to right structure */
}
if (!rcb_info) //报告控制块指针为空!
{
//SLOGALWAYS1 ("RptID '%s' not recognized on this connection. Received report ignored.", saveRptID);
//LOG_INFO("(报告解析)报告控制块链表查找不到RptID= '%s'goto CLEANUP跳出", saveRptID); //仅调试使用! zl 2019-12-23 15:09:36
retcode = SD_FAILURE;
goto CLEANUP; //跳转至 CLEANUP返回retcode结束
}
//WW 2023-08-29 end
//////////////////////////////
//////////////////////
//WW 2023-08-29注释
///* Must decode the RptID first to find the correct RCB_INFO. Could decode into
//* any "vstring65" variable. We just use the RptID variable from the first
//* rcb_info on the list.
//*/
//rcb_info = all_rcb_info->rcb_info_list; /* use first rcb_info on list*/
//va_num = 0;
//info_va[va_num++] = rcb_info->rcb_var.RptID;
//rcb_info->rcb_data.RptID[0] = '\0'; /* start with empty string */
//mvl_info_data_to_local(event, va_num, info_va);
///* NOTE: decoded RptID is now in "rcb_info->rcb_data.RptID". Save it.*/
//strcpy(saveRptID, rcb_info->rcb_data.RptID);
///* Search list of "rcb_info" to find one with matching RptID. */
///* If not found, rcb_info will be == NULL. */
//for (rcb_info = all_rcb_info->rcb_info_list;
// rcb_info != NULL;
// rcb_info = (RCB_INFO*)list_get_next(all_rcb_info->rcb_info_list, rcb_info))
//{
// if (strcmp(rcb_info->RptID, saveRptID) == 0)
// break; /* rcb_info now points to right structure */
//}
//if (!rcb_info)
//{
// echo_warn1("RptID '%s' not recognized on this connection. Received report ignored.", saveRptID);
// retcode = SD_FAILURE;
// goto CLEANUP;
//}
//WW 2023-08-29 end
////////////////////////
va_num = 0;
info_va[va_num++] = rcb_info->rcb_var.RptID;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
info_va[va_num++] = rcb_info->rcb_var.OptFlds;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
/* Perform 1st decode (up through "OptFlds"). Need "OptFlds" to figure
* out what comes next.
*/
mvl_info_data_to_local(event, va_num, info_va);
/* Examine "OptFlds", and set up 2nd decode to decode all options */
OptFldsData = rcb_info->rcb_data.OptFlds.data_1; /* use local var */
// printf ("OptFlds = 0x%02x 0x%02x\n", OptFldsData[0],OptFldsData[1]); /* 9 bit bstr (2 bytes) */
/* NOTE: Don't change initial entries in "info_va". Add these right after "OptFlds".*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SQNUM))
info_va[va_num++] = rcb_info->rcb_var.SqNum;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_TIMESTAMP))
info_va[va_num++] = rcb_info->rcb_var.TimeOfEntry;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATSETNAME))
{
info_va[va_num++] = rcb_info->rcb_var.DatSetNa;
///////////////////
//WW 2023-08-29
log_var_to_data(rcb_info->rcb_var.DatSetNa, rptID);
//for (rcb_info1 = all_rcb_info->rcb_info_list;
// rcb_info1 != NULL;
// rcb_info1 = (RCB_INFO *) list_get_next (all_rcb_info->rcb_info_list, rcb_info1)) //遍历 装置报告控制块链表
for (rcb_info1 = dev_rcb->rcb_info_list;
rcb_info1 != NULL;
rcb_info1 = (RCB_INFO *)list_get_next(dev_rcb->rcb_info_list, rcb_info1)) //遍历 报告控制块链表
{
if (strcmp(rcb_info1->ds_Nam, rptID) == 0) //报告ID作为不同报告间的唯一标识符
{
//SLOGALWAYS3 ("Num of var received in RPT (%d) does not match expected (%d)dateSet=%s ", va_total, va_num,rptID);
//LOG_INFO("(报告解析)接收报告RptID= '%s'数据集rptID= %s大小(%d)与预期大小(%d)不匹配brak跳出", saveRptID, rptID, va_total, va_num); //仅调试使用! zl 2019-12-23 15:09:30
rcb_info = rcb_info1;
break;
}
}
//WW 2023-08-29 en
///////////////////////////
}
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
/* The following optional vars are supported by IEC-61850 but they are
* NOT supported by UCA. This client must NOT set these OptFlds bits
* when connected to a UCA server, and these variables will NOT be
* included in a report received from a UCA server.
*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_BUFOVFL))
info_va[va_num++] = rcb_info->rcb_var.BufOvfl;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_ENTRYID))
info_va[va_num++] = rcb_info->rcb_var.EntryID;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_CONFREV))
info_va[va_num++] = rcb_info->rcb_var.ConfRev;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SUBSEQNUM))
{
info_va[va_num++] = rcb_info->rcb_var.SubSeqNum;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
info_va[va_num++] = rcb_info->rcb_var.MoreSegmentsFollow;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
}
info_va[va_num++] = rcb_info->rcb_var.Inclusion;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
assert(va_num < va_total);
/* Perform 2nd decode (up through "Inclusion"). */
mvl_info_data_to_local(event, va_num, info_va);
/* Examine "Inclusion", and set up 3rd decode to decode all data. */
InclusionData = rcb_info->rcb_data.Inclusion; /* use local var */
// printf ("\nThe 1st byte Inclusion = 0x%02X\n", InclusionData[0]); /* Just print 1st byte */
/* NOTE: Don't change initial entries in "info_va". Add these right after "Inclusion".*/
/* If "data-Ref" enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATAREF))
{
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j)) {
info_va[va_num++] = rcb_info->rcb_var.dataRefName[j];
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
}
}
}
/* HERE'S THE DATA. Check "Inclusion" to figure out what is being received.*/
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j)) {
info_va[va_num++] = rcb_info->rcb_var.dataValue[j];
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
}
}
/* If "reason" enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_REASON))
{
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j)) {
info_va[va_num++] = rcb_info->rcb_var.Reason[j];
}
}
}
/* Does num of variables received match expected num.*/
if (va_num != va_total)
{
echo_warn2("Num of var received in RPT (%d) does not match expected (%d). Possibly incorrect OptFlds or inclusion bitstring", va_total, va_num);
// printf ("Num of var received in RPT (%d) does not match expected (%d). Possibly incorrect OptFlds or inclusion bitstring\n", va_total, va_num);
}
else
{
/* Perform 3rd decode (everything). */
mvl_info_data_to_local(event, va_num, info_va);
u_iec_rpt_ind_data_by_devtype(info_va, OptFldsData, InclusionData, rcb_info, va_total, event->net_info);
}
CLEANUP:
chk_free(info_va);
END:
return (retcode);
}
ST_RET u_iec_rpt_ind(MVL_COMM_EVENT* event)
{
INFO_REQ_INFO* info_ptr;
ST_INT j, va_num, va_total;
VAR_ACC_SPEC* va_spec;
MVL_VAR_ASSOC** info_va;
RCB_INFO* rcb_info, * rcb_info1;
ST_UINT8* OptFldsData; /* ptr to data part of OptFlds bvstring */
ST_UINT8* InclusionData; /* ptr to Inclusion bstring */
ST_CHAR saveRptID[66];
ALL_RCB_INFO* all_rcb_info;
ST_RET retcode = SD_SUCCESS;
info_ptr = (INFO_REQ_INFO*)event->u.mms.dec_rslt.data_ptr;
va_spec = &info_ptr->va_spec;
va_total = info_ptr->num_of_acc_result;
/* An IEC-61850 or UCA report must be a NamedVariableList named "RPT".
* Ignore any other InformationReport.
*/
if (va_spec->var_acc_tag != VAR_ACC_NAMEDLIST
|| strcmp(va_spec->vl_name.obj_name.vmd_spec, "RPT") != 0)
{
echo_warn("Received InformationReport is not a IEC-61850 Report or UCA Report. Ignored.");
return (SD_FAILURE);
}
/* Get "all_rcb_info" from "user_info". User must set "user_info" when conn established.*/
all_rcb_info = (ALL_RCB_INFO*)event->net_info->user_info;
/* Check "all_rcb_info" to see if any RCB has been enabled. */
if (all_rcb_info == NULL || all_rcb_info->rcb_info_list == NULL)
{
echo_warn("Received InformationReport. No IEC-61850 or UCA RCB enabled. Ignored.");
return (SD_FAILURE);
}
/* Create array of (MVL_VAR_ASSOC *) needed for converting the received
* data to local format.
* Use variables created earlier to fill in the array. These variables will
* hold the decoded data.
* NOTE: any return after this must free info_va (see CLEANUP label).
*/
info_va = (MVL_VAR_ASSOC**)chk_calloc(va_total,
sizeof(MVL_VAR_ASSOC*));
/* Must decode the RptID first to find the correct RCB_INFO. Could decode into
* any "vstring65" variable. We just use the RptID variable from the first
* rcb_info on the list.
*/
rcb_info = all_rcb_info->rcb_info_list; /* use first rcb_info on list*/
va_num = 0;
info_va[va_num++] = rcb_info->rcb_var.RptID;
rcb_info->rcb_data.RptID[0] = '\0'; /* start with empty string */
mvl_info_data_to_local(event, va_num, info_va);
/* NOTE: decoded RptID is now in "rcb_info->rcb_data.RptID". Save it.*/
strcpy(saveRptID, rcb_info->rcb_data.RptID);
/* Search list of "rcb_info" to find one with matching RptID. */
/* If not found, rcb_info will be == NULL. */
for (rcb_info = all_rcb_info->rcb_info_list;
rcb_info != NULL;
rcb_info = (RCB_INFO*)list_get_next(all_rcb_info->rcb_info_list, rcb_info))
{
if (strcmp(rcb_info->RptID, saveRptID) == 0)
break; /* rcb_info now points to right structure */
}
if (!rcb_info)
{
echo_warn1("RptID '%s' not recognized on this connection. Received report ignored.", saveRptID);
retcode = SD_FAILURE;
goto CLEANUP;
}
va_num = 0;
info_va[va_num++] = rcb_info->rcb_var.RptID;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
info_va[va_num++] = rcb_info->rcb_var.OptFlds;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
/* Perform 1st decode (up through "OptFlds"). Need "OptFlds" to figure
* out what comes next.
*/
mvl_info_data_to_local(event, va_num, info_va);
/* Examine "OptFlds", and set up 2nd decode to decode all options */
OptFldsData = rcb_info->rcb_data.OptFlds.data_1; /* use local var */
// printf ("OptFlds = 0x%02x 0x%02x\n", OptFldsData[0],OptFldsData[1]); /* 9 bit bstr (2 bytes) */
/* NOTE: Don't change initial entries in "info_va". Add these right after "OptFlds".*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SQNUM))
info_va[va_num++] = rcb_info->rcb_var.SqNum;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_TIMESTAMP))
info_va[va_num++] = rcb_info->rcb_var.TimeOfEntry;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
//WW 2024-09-02 数据集名称确认
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATSETNAME))
info_va[va_num++] = rcb_info->rcb_var.DatSetNa;
mvl_info_data_to_local(event, va_num, info_va);
//WW 2024-09-02 endss
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATSETNAME))
{
//info_va[va_num++] = rcb_info->rcb_var.DatSetNa; //WW 2024-09-02 注释
///////////////////
//WW 2023-08-29
log_var_to_data(rcb_info->rcb_var.DatSetNa, saveRptID);
for (rcb_info1 = all_rcb_info->rcb_info_list;
rcb_info1 != NULL;
rcb_info1 = (RCB_INFO*)list_get_next(all_rcb_info->rcb_info_list, rcb_info1)) //遍历 报告控制块链表
{
if (strcmp(rcb_info1->ds_Nam, saveRptID) == 0) //报告ID作为不同报告间的唯一标识符
{
printf("ds_name '%s' ! Recive name %s WWTest \n", rcb_info1->ds_Nam, saveRptID);
//SLOGALWAYS3 ("Num of var received in RPT (%d) does not match expected (%d)dateSet=%s ", va_total, va_num,rptID);
//LOG_INFO("(报告解析)接收报告RptID= '%s'数据集rptID= %s大小(%d)与预期大小(%d)不匹配brak跳出", saveRptID, rptID, va_total, va_num); //仅调试使用! zl 2019-12-23 15:09:30
rcb_info = rcb_info1;
break;
}
}
//WW 2023-08-29 en
///////////////////////////
}
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
/* The following optional vars are supported by IEC-61850 but they are
* NOT supported by UCA. This client must NOT set these OptFlds bits
* when connected to a UCA server, and these variables will NOT be
* included in a report received from a UCA server.
*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_BUFOVFL))
info_va[va_num++] = rcb_info->rcb_var.BufOvfl;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_ENTRYID))
info_va[va_num++] = rcb_info->rcb_var.EntryID;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_CONFREV))
info_va[va_num++] = rcb_info->rcb_var.ConfRev;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_SUBSEQNUM))
{
info_va[va_num++] = rcb_info->rcb_var.SubSeqNum;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
info_va[va_num++] = rcb_info->rcb_var.MoreSegmentsFollow;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
}
info_va[va_num++] = rcb_info->rcb_var.Inclusion;
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
assert(va_num < va_total);
/* Perform 2nd decode (up through "Inclusion"). */
mvl_info_data_to_local(event, va_num, info_va);
/* Examine "Inclusion", and set up 3rd decode to decode all data. */
InclusionData = rcb_info->rcb_data.Inclusion; /* use local var */
// printf ("\nThe 1st byte Inclusion = 0x%02X\n", InclusionData[0]); /* Just print 1st byte */
/* NOTE: Don't change initial entries in "info_va". Add these right after "Inclusion".*/
/* If "data-Ref" enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_DATAREF))
{
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j)) {
info_va[va_num++] = rcb_info->rcb_var.dataRefName[j];
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
}
}
}
/* HERE'S THE DATA. Check "Inclusion" to figure out what is being received.*/
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j)) {
info_va[va_num++] = rcb_info->rcb_var.dataValue[j];
if ((retcode = check_va_count_too_big(va_num, va_total)) == SD_FAILURE) goto CLEANUP;
}
}
/* If "reason" enabled, check "Inclusion" to figure out what is being received.*/
if (BSTR_BIT_GET(OptFldsData, OPTFLD_BITNUM_REASON))
{
for (j = 0; j < rcb_info->numDsVar; ++j)
{
if (BSTR_BIT_GET(InclusionData, j)) {
info_va[va_num++] = rcb_info->rcb_var.Reason[j];
}
}
}
/* Does num of variables received match expected num.*/
if (va_num != va_total)
{
echo_warn2("Num of var received in RPT (%d) does not match expected (%d). Possibly incorrect OptFlds or inclusion bitstring", va_total, va_num);
// printf ("Num of var received in RPT (%d) does not match expected (%d). Possibly incorrect OptFlds or inclusion bitstring\n", va_total, va_num);
}
else
{
/* Perform 3rd decode (everything). */
mvl_info_data_to_local(event, va_num, info_va);
//报告处理加锁lnk20250114
//pthread_mutex_lock(&mtx); printf("rpt hold lock !!!!!!!!!!!");
u_iec_rpt_ind_data(info_va, OptFldsData, InclusionData, rcb_info, va_total, event->net_info);
//pthread_mutex_unlock(&mtx); printf("rpt free lock !!!!!!!!!!!");
}
CLEANUP:
chk_free(info_va);
return (retcode);
}
/************************************************************************/
//61850报告解析为本地数据
/************************************************************************/
void log_var_to_data(MVL_VAR_ASSOC *var, char *pdata)
{
static char text_buf[30000]; /* increase size if ms_local_to_text fails */
// ST_CHAR tdl_buf [500]; /* increase size if complex TDL expected*/
MVL_TYPE_CTRL *type_ctrl;
ST_CHAR *data_text; /* var data converted to text */
text_buf[0] = 0;
type_ctrl = mvl_type_ctrl_find(var->type_id);
if (type_ctrl)
{
//if (ms_runtime_to_tdl(type_ctrl->rt,type_ctrl->num_rt,tdl_buf,sizeof(tdl_buf))>0)
// RTP_PRI (" TYPE: %s\r\n", tdl_buf);
//else RTP_PRI (" TYPE: unknown\r\n");
data_text = ms_local_to_text((char *)var->data, type_ctrl->rt, type_ctrl->num_rt, text_buf, sizeof(text_buf));
if (data_text) { strcpy(pdata, data_text); }
else *pdata = '0';
}
else *pdata = '0';
}
/************************************************************************/
/* LocToTextBs */
/************************************************************************/
#define TEMP_DATA_BUF_SIZE 1024
static ST_RET myLocToTextBs(ST_UCHAR* pSrc, RUNTIME_TYPE* rt, ST_CHAR* text)
{
int i;
int j;
int k;
int numBits;
ST_INT16* sp;
ST_CHAR* destBuf;
ST_UCHAR mask;
//调试用
//printf("pSrc[0]: 0x%X, pSrc[1]: 0x%X, text: %s\n", pSrc[0], pSrc[1], text);
//printf("%s text_len %d %d pSrc %d %d \n", text, strlen(text), rt->u.p.el_len, pSrc[0], pSrc[1]);
text[0] = 0;
numBits = rt->u.p.el_len;
/* We take 1 dest byte per bit, make sure it fits */
if (numBits > TEMP_DATA_BUF_SIZE - 1)
{
MLOG_NERR1("Bit String (%d bits) too long to encode", numBits);
return (SD_FAILURE);
}
if (numBits < 0) /* a variable length bit string */
{
sp = (ST_INT16*)pSrc;
numBits = *sp;
//printf("numBits %d \n", numBits);
if ((numBits > TEMP_DATA_BUF_SIZE - 1) || (numBits <= 0)) {
if (numBits != 0) //add by lzm @2018.11.1,to avoid too many print message!!!
echo_warn1("Bit String (%d bits) too long to encode\n", numBits);
return (SD_FAILURE);
}
k = 2;
}
else
k = 0;
destBuf = text;
for (i = 0; i < numBits; ++k) /* for each byte, while bits remain */
{
mask = 0x80;
for (j = 0; j < 8 && i < numBits; ++i, ++j)
{
if (pSrc[k] & mask)
destBuf[i] = '1';
else
destBuf[i] = '0';
mask >>= 1;
}
}
destBuf[i] = 0;
//调试用
//printf("pSrc[0]: 0x%X, pSrc[1]: 0x%X, text: %s\n", pSrc[0], pSrc[1], text);
return (SD_SUCCESS);
}
/************************************************************************/
/* LocToTextOct */
/************************************************************************/
static ST_RET myLocToTextOct(ST_UCHAR* pSrc, RUNTIME_TYPE* rt, ST_CHAR* text)
{
int i, k;
int numBytes;
ST_INT16* sp;
ST_CHAR* destBuf;
text[0] = 0;
numBytes = rt->u.p.el_len;
if (numBytes < 0) /* a variable length octet string */
{
sp = (ST_INT16*)pSrc;
numBytes = *sp;
k = 2;
}
else
k = 0;
/* We take 3 bytes per octet, make sure it fits */
if (numBytes > TEMP_DATA_BUF_SIZE / 3)
{
MLOG_NERR1("Octet String (%d bytes) too long to encode", numBytes);
return SD_FAILURE;
}
destBuf = text;
for (i = 0; i < numBytes; ++i, ++k)
{
apr_snprintf(destBuf, sizeof(destBuf), "%02x ", (unsigned int)pSrc[k]);
destBuf += 3;
}
/* Eliminate the trailing space */
*(destBuf - 1) = 0;
return (SD_SUCCESS);
}
/************************************************************************/
/* asn1_convert_utc_to_btod */
/* This function converts MMS_UTC_TIME (time relative to 1/1/1970) to */
/* the MMS_BTOD (time relative to 1/1/1984). */
/* The form field in the MMS_BTOD is set to MMS_BTOD6 by this function. */
/* Parameters: */
/* utc pointer to MMS_UTC_TIME struct that should be converted */
/* to the MMS_BTOD */
/* btod pointer to MMS_BTOD struct where the result of the */
/* conversion will be placed */
/* Return: */
/* SD_SUCCESS if function successful */
/* SD_FAILURE otherwise */
/************************************************************************/
ST_RET my_asn1_convert_utc_to_btod(MMS_UTC_TIME* utc, MMS_BTOD* btod)
{
time_t tJan84 = TIME_T_1984_JAN_1;
/* Now compute the MMS_BTOD time */
btod->day = (long)(utc->secs - tJan84) / SECONDS_PER_DAY; /* num of days since 1/1/1984 */
btod->ms = (long)((utc->secs - tJan84) % SECONDS_PER_DAY) * 1000; /* num milliseconds since midnight */
/* NOTE: use 0x01000000 (2**24) in fraction computations. */
// 要四舍五入到毫秒数,比如 28.9999应该是29ms
btod->ms += (ST_INT32)(0.5 + (ST_DOUBLE)utc->fraction * 1000.0 / (ST_DOUBLE)0x01000000);
/* add the milliseconds left in a sec */
btod->form = MMS_BTOD6;
return (SD_SUCCESS);
}
/************************************************************************/
/* ms_local_to_text */
/* NOTE: tmpBuf is passed to most "LocToText.." static functions. These */
/* functions must NOT write past end of tmpBuf. */
/************************************************************************/
void my_local_to_data(ST_CHAR* datptr, SD_CONST RUNTIME_TYPE* rt_head,
ST_INT rt_num, MMS_DECODE_DATA* data)
{
RUNTIME_TYPE* rt_ptr;
RUNTIME_TYPE* rt_end;
ST_RET uDataRet;
ST_INT arr_loop_level = 0;
ST_INT arr_loops[ASN1_MAX_LEVEL];
//ST_CHAR *ret_ptr;
ST_CHAR tmpBuf[TEMP_DATA_BUF_SIZE];
//ST_UINT nStrLen = 0; /* Current text total length */
ST_UINT valid_item_num = 0;
SD_CONST ST_CHAR* comp_name; /* component name *///add by lzm
//ST_INT comp_name_len; /* len of component name*/
ST_UINT deep = 0; // deep of structure
unsigned int jjj;
char attr_str[256];
char comp_str[32][256];
int cur_array_deep = -1;
ST_UINT cur_array_idx;
if (data == NULL) {
echo_warn("error ~~~~~~~ my_local_to_data MMS_DECODE_DATA data is NULL return \n");
return;
}
if (rt_num <= 0) {
echo_warn1("error !!!!!!! my_local_to_data rt_num %d = return \n", rt_num);
return;
}
if (rt_head->el_tag > RT_ARR_END) {
echo_warn2("error @@@@@@@ my_local_to_data rt_head->el_tag %d size %d = return \n", rt_head->el_tag, rt_head->el_size);
return;
}
data->item_num = 0;
rt_ptr = (RUNTIME_TYPE*)rt_head; /* point to head rt_block */
rt_end = rt_ptr + rt_num; /* done when pointer is here */
if (rt_end == NULL) {
echo_warn("error XXXXXX my_local_to_data rt_end \n");
return;
}
// SLOGCALWAYS1(" rt_num = %i",rt_num);
uDataRet = SD_SUCCESS;
while (rt_ptr < rt_end && uDataRet == SD_SUCCESS)
{
if (rt_ptr == NULL) {
echo_warn("error !!!!!!! my_local_to_data rt_ptr is NULL error,return \n");
return;
}
if (valid_item_num >= MAX_DATA_ITEMS_IN_ONE_DATA) {
echo_warn2("my_local_to_data RUNTIME_TYPE valid_item_num % >= %d \n", valid_item_num, MAX_DATA_ITEMS_IN_ONE_DATA);
return;
}
if (rt_ptr->el_tag == RT_ARR_END) /* treat case of array ending */
{
if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */
rt_ptr -= rt_ptr->u.arr.num_rt_blks; /* mv rt_ptr to start of arr */
else
--arr_loop_level;
}
if (rt_ptr->el_tag == RT_ARR_START) /* treat case of array starting */
{
/* initialize the loop counter for the array */
++arr_loop_level;
arr_loops[arr_loop_level] = rt_ptr->u.arr.num_elmnts;
}
comp_name = ms_comp_name_find(rt_ptr);//add by lzm
//printf ("\n %i, comp_name = %s cur_array_deep/deep: %d/%d \n",rt_ptr->el_tag,comp_name,cur_array_deep,deep);
// if (comp_name != NULL && comp_name[0] != 0)
// SLOGCALWAYS2 (" comp_name= %s, rt_ptr->el_tag =%i ",comp_name,rt_ptr->el_tag); // add by lzm
memset(attr_str, 0, sizeof(attr_str));
if (deep == (cur_array_deep + 1))
cur_array_idx++;
for (jjj = 0; jjj < deep; jjj++)
{
if (strcmp(comp_str[jjj], "")) {
strcat(attr_str, comp_str[jjj]);
}
if (jjj == cur_array_deep) {
char tmp_str[8];
apr_snprintf(tmp_str, sizeof(tmp_str), "[%d]", cur_array_idx);
strcat(attr_str, tmp_str);
}
if (strcmp(comp_str[jjj], "")) {
strcat(attr_str, "$");
}
//if (strcmp (comp_str[jjj], "")) {
//}
}
strcat(attr_str, comp_name);
switch (rt_ptr->el_tag)
{
case RT_ARR_START:
strcpy(comp_str[deep], comp_name);
cur_array_deep = deep;
cur_array_idx = -1;
assert(++deep < 32);
break; /* do nothing */
case RT_ARR_END: /* array done */
assert(--deep >= 0);
memset(comp_str[deep], 0, sizeof(comp_str[deep]));
cur_array_deep = -1;
cur_array_idx = -1;
break; /* do nothing */
case RT_STR_START:
strcpy(comp_str[deep], comp_name);
assert(++deep < 32);
//uDataRet = AddString ("{", textBuf, textBufSize, &nStrLen);
break;
case RT_STR_END: /* structure done */
assert(--deep >= 0);
memset(comp_str[deep], 0, sizeof(comp_str[deep]));
//uDataRet = AddString ("}", textBuf, textBufSize, &nStrLen);
break;
case RT_BOOL:
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = 1;
data->data_item[valid_item_num].type = DATA_INT_TYPE;
data->data_item[valid_item_num].u.data_int = *((ST_BOOLEAN*)datptr);
valid_item_num++;
// SLOGCALWAYS2("valid_item_num = %i , value=%i",valid_item_num, *((ST_BOOLEAN *) datptr) );
data->item_num = valid_item_num;
break;
case RT_BIT_STRING:
myLocToTextBs((ST_UCHAR*)datptr, rt_ptr, tmpBuf);//将存储在内存中的比特串转换为对应的文本字符串(由字符 '1' 和 '0' 组成)
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = abs(rt_ptr->u.p.el_len);
data->data_item[valid_item_num].type = DATA_STR_TYPE;
strcpy(data->data_item[valid_item_num].u.data_str, tmpBuf);
valid_item_num++;
// SLOGCALWAYS2("valid_item_num = %i , value=%s",valid_item_num, tmpBuf );
data->item_num = valid_item_num;
break;
case RT_INTEGER:
case RT_BCD:
switch (rt_ptr->u.p.el_len) /* determine length */
{
case 1: /* one byte int */
case 2: /* two byte int */
case 4: /* four byte integer */
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = (unsigned char)rt_ptr->u.p.el_len;
data->data_item[valid_item_num].type = DATA_INT_TYPE;
if (rt_ptr->u.p.el_len == 1)
data->data_item[valid_item_num].u.data_int = *((ST_INT8*)datptr);
else if (rt_ptr->u.p.el_len == 2)
data->data_item[valid_item_num].u.data_int = *((ST_INT16*)datptr);
else if (rt_ptr->u.p.el_len == 4)
data->data_item[valid_item_num].u.data_int = *((ST_INT32*)datptr);
// SLOGCALWAYS1("value=%i",data->data_item[valid_item_num].u.data_int );
valid_item_num++;
// SLOGCALWAYS1("valid_item_num = %i ",valid_item_num );
data->item_num = valid_item_num;
break;
#ifdef INT64_SUPPORT
case 8: /* eight byte integer */
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = (unsigned char)rt_ptr->u.p.el_len;
data->data_item[valid_item_num].type = DATA_INT64_TYPE;
data->data_item[valid_item_num].u.data_int64 = *((ST_INT64*)datptr);
// SLOGCALWAYS1(" value=%lld ",data->data_item[valid_item_num].u.data_int64 );
valid_item_num++;
// SLOGCALWAYS1("valid_item_num = %i ",valid_item_num );
data->item_num = valid_item_num;
break;
#endif
default:
echo_warn1("未处理的RT_INTEGER或RT_BCD 整数 size = %i \n", rt_ptr->u.p.el_len);
break;
}
break;
case RT_UNSIGNED:
switch (rt_ptr->u.p.el_len) /* determine length */
{
case 1: /* one byte int */
case 2: /* two byte int */
case 4: /* four byte integer */
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = (unsigned char)rt_ptr->u.p.el_len;
data->data_item[valid_item_num].type = DATA_UINT_TYPE;
if (rt_ptr->u.p.el_len == 1)
data->data_item[valid_item_num].u.data_uint = *((ST_UCHAR*)datptr);
else if (rt_ptr->u.p.el_len == 2)
data->data_item[valid_item_num].u.data_uint = *((ST_UINT16*)datptr);
else if (rt_ptr->u.p.el_len == 4)
data->data_item[valid_item_num].u.data_uint = *((ST_UINT32*)datptr);
// SLOGCALWAYS1("value=%u",data->data_item[valid_item_num].u.data_uint );
valid_item_num++;
// SLOGCALWAYS1("valid_item_num = %i ",valid_item_num );
data->item_num = valid_item_num;
break;
#ifdef INT64_SUPPORT
case 8: /* eight byte integer */
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = (unsigned char)rt_ptr->u.p.el_len;
data->data_item[valid_item_num].type = DATA_UINT64_TYPE;
data->data_item[valid_item_num].u.data_int64 = *((ST_UINT64*)datptr);
// SLOGCALWAYS1(" value=%llu ",data->data_item[valid_item_num].u.data_uint64 );
valid_item_num++;
// SLOGCALWAYS1("valid_item_num = %i ",valid_item_num );
data->item_num = valid_item_num;
break;
#endif /* INT64_SUPPORT */
default:
echo_warn1("未处理的 无符号整数 size = %i \n", rt_ptr->u.p.el_len);
break;
}
break;
#ifdef FLOAT_DATA_SUPPORT
case RT_FLOATING_POINT:
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = (unsigned char)rt_ptr->u.p.el_len;
data->data_item[valid_item_num].type = DATA_DOUBLE_TYPE;
if (rt_ptr->u.p.el_len != sizeof(ST_FLOAT))
data->data_item[valid_item_num].u.data_double = *((ST_DOUBLE*)datptr);
else
data->data_item[valid_item_num].u.data_double = *((ST_FLOAT*)datptr);
// SLOGCALWAYS1(" value=%.16g ",data->data_item[valid_item_num].u.data_double );
valid_item_num++;
// SLOGCALWAYS1("valid_item_num = %i ",valid_item_num );
data->item_num = valid_item_num;
break;
#endif
case RT_OCTET_STRING:
myLocToTextOct((ST_UCHAR*)datptr, rt_ptr, tmpBuf);
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = abs(rt_ptr->u.p.el_len);
data->data_item[valid_item_num].type = DATA_STR_TYPE;
strcpy(data->data_item[valid_item_num].u.data_str, tmpBuf);
valid_item_num++;
//SLOGCALWAYS2("valid_item_num = %i , value=%s",valid_item_num, tmpBuf );
data->item_num = valid_item_num;
break;
case RT_VISIBLE_STRING: /* No conversion needed. Just add to working text*/
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = abs(rt_ptr->u.p.el_len);
data->data_item[valid_item_num].type = DATA_STR_TYPE;
strcpy(data->data_item[valid_item_num].u.data_str, datptr);
valid_item_num++;
// SLOGCALWAYS2("valid_item_num = %i , value=%s",valid_item_num, datptr );
data->item_num = valid_item_num;
break;
#ifdef TIME_DATA_SUPPORT
case RT_GENERAL_TIME:
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = abs(rt_ptr->u.p.el_len);
data->data_item[valid_item_num].type = DATA_TIME_TYPE;
asn1_convert_timet_to_btime6(*((time_t*)datptr),
&(data->data_item[valid_item_num].u.data_bTime6));
valid_item_num++;
data->item_num = valid_item_num;
break;
#endif
#ifdef BTOD_DATA_SUPPORT
case RT_BINARY_TIME:
switch (rt_ptr->u.p.el_len) /* determine length */
{
MMS_BTIME6 btime6;
case 4:
asn1_convert_timet_to_btime6(time(NULL), &btime6);
btime6.ms = *((ST_INT32*)datptr);
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = 4;
data->data_item[valid_item_num].type = DATA_TIME_TYPE;
data->data_item[valid_item_num].u.data_bTime6 = btime6;
valid_item_num++;
data->item_num = valid_item_num;
break;
case 6:
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = 6;
data->data_item[valid_item_num].type = DATA_TIME_TYPE;
data->data_item[valid_item_num].u.data_bTime6 = *((MMS_BTIME6*)datptr);
valid_item_num++;
data->item_num = valid_item_num;
break;
}
break;
#endif
case RT_UTC_TIME:
{
MMS_BTOD btod;
//cout<<"((MMS_UTC_TIME *) datptr)->fraction = "<<((MMS_UTC_TIME *) datptr)->fraction;
//cout<<"((MMS_UTC_TIME *)datptr)->qflags = "<<((MMS_UTC_TIME *)datptr)->qflags<<endl;
my_asn1_convert_utc_to_btod((MMS_UTC_TIME*)datptr, &btod);
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = 1;
data->data_item[valid_item_num].type = DATA_TIME_TYPE;
data->data_item[valid_item_num].u.data_bTime6.day = btod.day;
data->data_item[valid_item_num].u.data_bTime6.ms = btod.ms;
valid_item_num++;
// SLOGALWAYS3("valid_item_num = %i , UTC TIME seconds=%lu, fraction=%lu",
// valid_item_num, ((MMS_UTC_TIME *) datptr)->fraction,
// ((MMS_UTC_TIME *) datptr)->secs );
data->item_num = valid_item_num;
}
break;
case RT_UTF8_STRING:
strcpy(data->data_item[valid_item_num].comp_name, (const char*)attr_str);
data->data_item[valid_item_num].size = abs(rt_ptr->u.p.el_len);
data->data_item[valid_item_num].type = DATA_STR_TYPE;
strcpy(data->data_item[valid_item_num].u.data_str, datptr);
valid_item_num++;
// SLOGCALWAYS2("valid_item_num = %i , value=%s",valid_item_num, datptr );
data->item_num = valid_item_num;
break;
default: /* should not be any other tag */
MLOG_ERR1("Invalid tag: %d", (int)rt_ptr->el_tag);
uDataRet = SD_FAILURE;
break;
}
assert(strlen(tmpBuf) < sizeof(tmpBuf)); /* Must not exceed buffer*/
datptr += rt_ptr->el_size; /* Adjust data pointer */
rt_ptr++; /* point to next rt element */
}
}