|
@@ -636,9 +636,17 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
|
|
|
iedname := tools.IsEmpty(ied["ied_name"])
|
|
|
extreflist := getIedExtRefs(iedname)
|
|
|
for outiedname, refrow := range outiedlist {
|
|
|
+ iedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), iedname)
|
|
|
+ outIedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), outiedname)
|
|
|
outiedFcdaList := getIedFcdas(outiedname) //输入装置的信号输出端子
|
|
|
//检查是否有错误和缺失的端子
|
|
|
+ hasYaoXinFunc := false //是否具备遥信功能
|
|
|
for _, r := range refrow {
|
|
|
+ //判断装置是否具备遥信功能,具备时需要单独处理遥信类端子
|
|
|
+ //遥信类端子处理规则:以scd中实际配置为准,通过检查装置双方的端子名称是否完全一致,以及是否有缺失和多余的遥信端子
|
|
|
+ if strings.Contains(tools.IsEmpty(r["to_func_name"]), "遥信") || strings.Contains(tools.IsEmpty(r["from_func_name"]), "遥信") {
|
|
|
+ hasYaoXinFunc = true
|
|
|
+ }
|
|
|
extref_name := tools.IsEmpty(r["to_fcda_name"])
|
|
|
fcda_name := tools.IsEmpty(r["from_fcda_name"])
|
|
|
extref_name_exp := tools.IsEmpty(r["to_fcda_match_exp"])
|
|
@@ -728,6 +736,9 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
|
|
|
fcda_name := ""
|
|
|
isHave := false
|
|
|
for _, r1 := range refrow { //设计的端子关系
|
|
|
+ if strings.Contains(tools.IsEmpty(r1["to_func_name"]), "遥信") || strings.Contains(tools.IsEmpty(r1["from_func_name"]), "遥信") {
|
|
|
+ hasYaoXinFunc = true
|
|
|
+ }
|
|
|
extref_name_exp := tools.IsEmpty(r1["to_fcda_match_exp"])
|
|
|
rex, err := regexp.Compile(extref_name_exp)
|
|
|
if err != nil {
|
|
@@ -741,8 +752,6 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
|
|
|
}
|
|
|
}
|
|
|
if !isHave {
|
|
|
- iedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), iedname)
|
|
|
- outIedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), outiedname)
|
|
|
parse_result := fmt.Sprintf("间隔%s的装置%s端子%s在设计中不存在", area_name, iedname, extref_name)
|
|
|
daname := ""
|
|
|
if r.DaName != "" {
|
|
@@ -771,6 +780,58 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
|
|
|
scdNodeRule.AppendFcdaCheckResult(re)
|
|
|
}
|
|
|
}
|
|
|
+ if hasYaoXinFunc {
|
|
|
+ //遥信端子检查:仅根据scd实际配置检查其双方端子的doi名称是否相同
|
|
|
+ scdMgr := new(ScdMgr)
|
|
|
+ yx := scdMgr.GetYxExtref(scdXmlObj, c.ScdId, iedname)
|
|
|
+ if len(yx) > 0 {
|
|
|
+ for extref, doiDesc := range yx {
|
|
|
+ if extref.IedName != outiedname {
|
|
|
+ //非当前输入装置的,不处理
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ daname := ""
|
|
|
+ if extref.DaName != "" {
|
|
|
+ daname = "." + extref.DaName
|
|
|
+ }
|
|
|
+ //获取输出端端子名称
|
|
|
+ outFcdaDoi, _ := scdNodeRule.IedFcdaExist(extref.IedName, extref.LdInst, extref.LnClass, extref.LnInst, extref.Prefix, extref.DoName, extref.DaName)
|
|
|
+ if outFcdaDoi == nil {
|
|
|
+ //端子缺失
|
|
|
+ parse_result := fmt.Sprintf("间隔%s的装置%s端子%s的关联端子不存在", area_name, iedname, doiDesc)
|
|
|
+ re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
|
|
|
+ "ied_name": iedname,
|
|
|
+ "ied_desc": iedObj.Desc,
|
|
|
+ "out_ied_name": outiedname,
|
|
|
+ "out_ied_desc": outIedObj.Desc,
|
|
|
+ "fcda_desc": doiDesc,
|
|
|
+ "fcda_addr": extref.IntAddr,
|
|
|
+ "out_fcda_desc": "",
|
|
|
+ "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extref.LdInst, extref.Prefix, extref.LnClass, extref.LnInst, extref.DoName, daname),
|
|
|
+ "error_type": "3",
|
|
|
+ }
|
|
|
+ //检查未通过
|
|
|
+ scdNodeRule.AppendFcdaCheckResult(re)
|
|
|
+ } else if outFcdaDoi.(*node_attr.NDOI).Desc != doiDesc {
|
|
|
+ //关联错误
|
|
|
+ parse_result := fmt.Sprintf("间隔%s的装置%s端子%s与装置%s端子%s名称不匹配", area_name, iedname, doiDesc, outiedname, outFcdaDoi.(*node_attr.NDOI).Desc)
|
|
|
+ re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
|
|
|
+ "ied_name": iedname,
|
|
|
+ "ied_desc": iedObj.Desc,
|
|
|
+ "out_ied_name": outiedname,
|
|
|
+ "out_ied_desc": outIedObj.Desc,
|
|
|
+ "fcda_desc": doiDesc,
|
|
|
+ "fcda_addr": extref.IntAddr,
|
|
|
+ "out_fcda_desc": outFcdaDoi.(*node_attr.NDOI).Desc,
|
|
|
+ "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extref.LdInst, extref.Prefix, extref.LnClass, extref.LnInst, extref.DoName, daname),
|
|
|
+ "error_type": "2",
|
|
|
+ }
|
|
|
+ //检查未通过
|
|
|
+ scdNodeRule.AppendFcdaCheckResult(re)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -879,6 +940,29 @@ func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Para
|
|
|
volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
|
|
|
volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
|
|
|
}
|
|
|
+
|
|
|
+ var getIedByDesc = func(iedinfo map[string]orm.Params, desc string) (string, string) {
|
|
|
+ scdParseMgr := new(ScdParse)
|
|
|
+ scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
|
|
|
+ for vn, row := range iedinfo {
|
|
|
+ v := tools.IsEmpty(row["ied_desc"])
|
|
|
+ if v == "" {
|
|
|
+ if scdXmlObj == nil {
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
+ scdNode := new(ScdNode)
|
|
|
+ ied := scdNode.GetIed(scdXmlObj, "", vn)
|
|
|
+ if ied == nil {
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
+ v = ied.Desc
|
|
|
+ }
|
|
|
+ if strings.Contains(v, desc) {
|
|
|
+ return v, vn
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "", ""
|
|
|
+ }
|
|
|
//判断是否将各电压等级的保护装置合并还是分开的间隔
|
|
|
//如果存在高中低压的保护装置,则说明是分开的主变间隔
|
|
|
//isMarge := true // 默认为合并的主变间隔
|
|
@@ -887,6 +971,14 @@ func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Para
|
|
|
if tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "T" {
|
|
|
continue
|
|
|
}
|
|
|
+ //判断主变保护是否是按电压等级分开配置的模型
|
|
|
+ /*
|
|
|
+ if strings.Contains(iedtypes, "PT#H") || strings.Contains(iedtypes, "PT#M") || strings.Contains(iedtypes, "PT#L") {
|
|
|
+ h, m, l := c.getIedListByVol("PT", ieds, volMap)
|
|
|
+ } else {
|
|
|
+ pl_iedname := tools.IsEmpty(row["ied_name"])
|
|
|
+ }
|
|
|
+ */
|
|
|
//pmIedName := ""
|
|
|
//mmIedName := ""
|
|
|
pl_iedname := tools.IsEmpty(row["ied_name"])
|
|
@@ -907,6 +999,20 @@ func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Para
|
|
|
insvalues := []string{}
|
|
|
inAreaIedName := pl_iedname
|
|
|
insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "T"))
|
|
|
+ //判断间隔是否需要包含差动装置
|
|
|
+ if strings.Contains(iedtypes, "PT#C") {
|
|
|
+ ieddesc, iedname := getIedByDesc(ieds, "差动")
|
|
|
+ if strings.Contains(ieddesc, "差动") {
|
|
|
+ insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, iedname, "P", "TC"))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //判断间隔是否需要包含本体保护装置
|
|
|
+ if strings.Contains(iedtypes, "PT#0") {
|
|
|
+ ieddesc, iedname := getIedByDesc(ieds, "本体")
|
|
|
+ if strings.Contains(ieddesc, "本体") {
|
|
|
+ insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, iedname, "P", "T0"))
|
|
|
+ }
|
|
|
+ }
|
|
|
//合智一体IMT/MIT,分高中低压
|
|
|
h, m, l := c.getIedListByVol("IMT", ieds, volMap)
|
|
|
h = append(h, m...)
|