?? sclproc.c
字號:
return (retcode); /* NOTE: may have returned sooner on some errors*/
} /* end tdladd_go_or_gs */
/************************************************************************/
/* tdladd_ms_or_us */
/* RETURNS: SD_SUCCESS or error code */
/* Add the TDL for special FC=MS or FC=US at the current pointer */
/* (tdl_ctxt->tdlptr). */
/* Increase (tdl_ctxt->tdlptr) by the number of bytes added. */
/* Decrease (tdl_ctxt->len_avail) by the number of bytes added. */
/************************************************************************/
ST_CHAR *mscb_tdl = "{\
(SvEna)Bool,\
(MsvID)Vstring65,\
(DatSet)Vstring65,\
(ConfRev)Ulong,\
(SmpRate)Ushort,\
(OptFlds)BVstring3,\
(DstAddress){\
(Addr)Ostring6,\
(PRIORITY)Ubyte,\
(VID)Ushort,\
(APPID)Ushort,\
},\
},\n"; /* TDL for MsvCB (Sampled Value Control Block) */
ST_CHAR *uscb_tdl = "{\
(SvEna)Bool,\
(Resv)Bool,\
(UsvID)Vstring65,\
(DatSet)Vstring65,\
(ConfRev)Ulong,\
(SmpRate)Ushort,\
(OptFlds)BVstring3,\
},\n"; /* TDL for UsvCB (Sampled Value Control Block) */
static ST_RET tdladd_ms_or_us (
TDLADD_CTXT *tdl_ctxt,
SCL_INFO *scl_info,
SCL_LNTYPE *scl_lntype,
SCL_LN *scl_ln,
ST_BOOLEAN multicast) /* SD_TRUE to add GOOSE (FC=GO) */
/* SD_FALSE to add GSSE (FC=GS) */
/* CRITICAL: no other values allowed */
{
SCL_SVCB *scl_svcb;
SCL_DATASET *scl_dataset;
ST_RET retcode = SD_SUCCESS;
ST_INT count = 0;
for (scl_svcb = (SCL_SVCB *) list_find_last ((DBL_LNK *) scl_ln->svcbHead);
scl_svcb != NULL;
scl_svcb = (SCL_SVCB *) list_find_prev ((DBL_LNK *) scl_ln->svcbHead, (DBL_LNK *) scl_svcb))
{
/* If RCB doesn't match the kind we're looking for, ignore it. */
if (scl_svcb->multicast != multicast)
continue;
/*Find dataset now. */
scl_dataset = scl_find_dataset (scl_ln, scl_svcb->datSet);
if (scl_dataset == NULL)
{
SXLOG_ERR1 ("tdladd_vs_or_us: datSet='%s' not found", scl_svcb->datSet);
return (SD_FAILURE);
}
if (scl_svcb->multicast)
{
if (count==0)
retcode = tdladd_string (tdl_ctxt, "(MS){\n("); /* first one needs (GO) */
else
retcode = tdladd_string (tdl_ctxt, "(");
}
else
{
if (count==0)
retcode = tdladd_string (tdl_ctxt, "(US){\n("); /* first one needs (GS) */
else
retcode = tdladd_string (tdl_ctxt, "(");
}
if (retcode) /* if error, stop */
return (retcode);
/* Add svcb name as component name.*/
if (tdladd_string (tdl_ctxt, scl_svcb->name)!=SD_SUCCESS)
return (SD_FAILURE); /* error (already logged) */
if (tdladd_string (tdl_ctxt, ")")!=SD_SUCCESS) /* add end of comp name */
return (SD_FAILURE); /* error (already logged) */
/* NOTE: if NOT the type we're looking for, never get here (see 'continue' above)*/
if (scl_svcb->multicast) /* looking for MSV & this is MSV */
retcode = tdladd_string (tdl_ctxt, mscb_tdl);
else /* looking for USV & this is USV */
retcode = tdladd_string (tdl_ctxt, uscb_tdl);
if (retcode) /* if error, stop */
return (retcode);
count++; /* increment count of svcb */
} /* end loop */
/* If any found, add ending text. */
if (count>0)
retcode = tdladd_string (tdl_ctxt, "},\n");
return (retcode); /* NOTE: may have returned sooner on some errors*/
} /* end tdladd_ms_or_us */
/************************************************************************/
/* scl2_datatype_create */
/* Create MMS Data type for one Logical Node Type (LNodeType) */
/* defined in SCL. */
/* This function needs a user buffer for constructing TDL strings. */
/* TDL is generated by calling "tdladd_*" functions. A ptr to a */
/* TDLADD_CTXT structure is passed to each "tdladd_*" function. */
/* The structure is used to keep track of the current ptr in the TDL */
/* buffer and the space remaining in the buffer. */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
static ST_RET scl2_datatype_create (
SCL_INFO *scl_info, /* main struct where all SCL info stored*/
SCL_LNTYPE *scl_lntype, /* info for this LNType */
ST_CHAR *tdlbuf, /* buffer to use for constructing TDL */
/* reused for each LNType in list */
size_t tdlbuflen, /* len of tdlbuf buffer in bytes */
SCL_LD *scl_ld_special, /* LD containing LN with "special stuff"*/
/* (i.e. ReportControl, LogControl, etc)*/
/* NULL if nothing special in LN. */
SCL_LN *scl_ln_special) /* LN with "special stuff" */
/* NULL if nothing special in LN. */
{
ST_RET retcode;
ST_INT type_id;
TDLADD_CTXT tdl_ctxt;
MVL_TYPE_CTRL *type_ctrl;
ST_CHAR type_name[MAX_IDENT_LEN+2]; /* one extra byte for NULL, another to catch if limit exceeded*/
/* Generate type_name. */
if (scl_ln_special)
{ /* Create unique type name for this LN. */
unique_type_name (scl_ld_special, scl_ln_special, type_name, sizeof(type_name));
}
else
strcpy (type_name, scl_lntype->id); /* no RCBs. Use LNType "id".*/
/* Go through all linked lists and create COMPLETE TDL. */
/* NOTE: order of FC specified in 61850-8-1 (section 6.1.3). */
/* Initialize tdl_ctxt struct. */
tdl_ctxt.tdlptr = tdlbuf;
tdl_ctxt.len_avail = tdlbuflen;
tdl_ctxt.errflag = SD_FALSE;
/* NOTE: SCL only allows "ST" "MX" "CO" "SG" "SE" "SV" "CF" "DC" "EX".*/
/* "RP", "LG", "GO", "GS", "SP", and "BR" are special cases. */
do
{ /* "do-while" loop: only needed so we can break on first error. */
/* if any tdladd_* call fails, break and return error. */
if ((retcode = tdladd_string (&tdl_ctxt, "{\n")) != SD_SUCCESS)
break;
if ((retcode = tdladd_fc (&tdl_ctxt, "MX", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if ((retcode = tdladd_fc (&tdl_ctxt, "ST", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if ((retcode = tdladd_fc (&tdl_ctxt, "CO", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if ((retcode = tdladd_fc (&tdl_ctxt, "CF", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if ((retcode = tdladd_fc (&tdl_ctxt, "DC", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if (scl_ln_special)
{
/* FC=SP is special case. Call special function (last arg SD_TRUE). */
if ((retcode = tdladd_sp (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS)
break;
}
if ((retcode = tdladd_fc (&tdl_ctxt, "SG", scl_info, scl_lntype)) != SD_SUCCESS)
break;
/* FC=RP is special case. Call special function. */
if (scl_ln_special)
{ /* special type for LN containing RCBs */
if ((retcode = tdladd_rp_or_br (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS)
break;
}
/* FC=LG is special case. Call special function. */
if (scl_ln_special)
{
if ((retcode = tdladd_lg (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS)
break;
}
/* FC=BR is special case. Call special function. */
if (scl_ln_special)
{ /* special type for LN containing RCBs */
if ((retcode = tdladd_rp_or_br (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS)
break;
}
if (scl_ln_special)
{
/* FC=GO is special case. Call special function (last arg SD_TRUE). */
if ((retcode = tdladd_go_or_gs (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS)
break;
/* FC=GS is special case. Call special function (last arg SD_FALSE). */
if ((retcode = tdladd_go_or_gs (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS)
break;
}
if ((retcode = tdladd_fc (&tdl_ctxt, "SV", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if ((retcode = tdladd_fc (&tdl_ctxt, "SE", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if (scl_ln_special)
{
/* FC=MS is special case. Call special function (last arg SD_TRUE). */
if ((retcode = tdladd_ms_or_us (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS)
break;
}
/* DEBUG: add something here for "SC" someday.*/
if (scl_ln_special)
{
/* FC=US is special case. Call special function (last arg SD_TRUE). */
if ((retcode = tdladd_ms_or_us (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS)
break;
}
if ((retcode = tdladd_fc (&tdl_ctxt, "EX", scl_info, scl_lntype)) != SD_SUCCESS)
break;
if ((retcode = tdladd_string (&tdl_ctxt, "}")) != SD_SUCCESS)
break;
} while (0); /* end of "do-while" loop: only needed so we can break on first error. */
assert (tdlbuf + strlen(tdlbuf) == tdl_ctxt.tdlptr);
assert (strlen(tdlbuf) < tdlbuflen); /* memory already corrupted */
assert (strlen(tdlbuf) + tdl_ctxt.len_avail == tdlbuflen);
/* If retcode==SD_SUCCESS, ALL "tdladd_fc" calls were successful, so create type here */
if (retcode == SD_SUCCESS)
{
/* NOTE: if generated type_name is > MAX_IDENT_LEN, this will fail. */
type_id = mvl_type_id_create_from_tdl (type_name, tdlbuf);
if (type_id < 0)
retcode = SD_FAILURE;
else
{
type_ctrl = mvl_type_ctrl_find (type_id);
/* CRITICAL: we want the same leaf function for every leaf, so */
/* set leaf functions now in every RUNTIME_TYPE element. */
/* NOTE: leaf functions never used for RT_STR_START, RT_ARR_START,*/
/* etc. but they're set anyway because it's easier to set all.*/
/* NOTE: this function may be customized for each application. */
/* It should be placed in a "user" module. */
retcode = u_set_all_leaf_functions (type_ctrl->rt_ctrl,scl_lntype->lnClass,scl_lntype->id);
}
}
/* NOTE: these may not log entire TDL unless default "sl_max_msg_size" is increased.*/
if (retcode)
SXLOG_ERR3 ("scl2_datatype_create FAILED for type_name=%s\nTDL len=%u\nTDL=%s",
type_name, strlen(tdlbuf), tdlbuf);
else
SXLOG_FLOW3 ("scl2_datatype_create SUCCESSFUL for type_name=%s\nTDL len=%u\nTDL=%s",
type_name, strlen(tdlbuf), tdlbuf);
/* Don't need to save or return type_id. Use "mvl_typename_to_typeid" later to find it.*/
return (retcode);
}
/************************************************************************/
/* scl2_datatype_create_all */
/* Create MMS Data types for all Logical Node Types (LNodeType) */
/* defined in SCL. */
/* This function needs a user buffer for constructing TDL strings. */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
ST_RET scl2_datatype_create_all (
SCL_INFO *scl_info, /* main struct where all SCL info stored*/
ST_CHAR *tdlbuf, /* buffer to use for constructing TDL */
/* reused for each LNType in list */
size_t tdlbuflen) /* len of tdlbuf buffer in bytes */
{
ST_RET retcode;
SCL_LNTYPE *scl_lntype;
SCL_LD *scl_ld;
SCL_LN *scl_ln;
/* NOTE: linked list is in reverse order from data in SCL file, */
/* so get off list in reverse order. */
for (scl_lntype = (SCL_LNTYPE *) list_find_last ((DBL_LNK *) scl_info->lnTypeHead);
scl_lntype != NULL;
scl_lntype = (SCL_LNTYPE *) list_find_prev ((DBL_LNK *) scl_info->lnTypeHead, (DBL_LNK *) scl_lntype))
{
retcode = scl2_datatype_create (scl_info, scl_lntype, tdlbuf, tdlbuflen, NULL, NULL);
if (retcode) /* error (already logged) */
break; /* if one fails, stop processing */
/* Find all Logical Nodes that use this type. For each one that
* contains "special stuff" (i.e. ReportControl, LogControl, GSEControl),
* create a special type that includes the "special stuff".
* Must check all Logical Nodes (scl_ln) in all Logical Devices (scl_ld).
*/
for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead);
scl_ld != NULL;
scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld))
{
for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead);
scl_ln != NULL;
scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln))
{
/* If rcbHead!=NULL, this LN contains ReportControl. */
/* If lcbHead!=NULL, this LN contains LogControl. */
/* If gcbHead!=NULL, this LN contains GSEControl. */
/* If sgcbHead!=NULL, this LN contains SGControl. */
/* NOTE: do nothing if it fails. Detected later when rcb created.*/
if ((scl_ln->rcbHead || scl_ln->lcbHead || scl_ln->gcbHead || scl_ln->sgcbHead || scl_ln->svcbHead) &&
strcmp (scl_ln->lnType, scl_lntype->id) == 0)
{
/* Last 2 args point to LD & LN containing special info (rcb, gcb, etc.).*/
scl2_datatype_create (scl_info, scl_lntype, tdlbuf, tdlbuflen, scl_ld, scl_ln);
}
}
}
}
return (retcode);
}
/************************************************************************/
/* scl2_ln_create */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
static ST_RET scl2_ln_create (
SCL_INFO *scl_info, /* main struct where all SCL info stored*/
SCL_LD *scl_ld,
SCL_LN *scl_ln)
{
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -