|
|
@@ -484,148 +484,295 @@ func (c *CheckAreaMgr) CheckIedFcda() error {
|
|
|
}
|
|
|
scdNodeRule := new(ScdNodeRule)
|
|
|
scdNodeMgr := new(ScdNode)
|
|
|
- iedRelationMgr := new(SysCheckModelIedRelationMgr)
|
|
|
+ //当前装置的所有信号接收端子列表
|
|
|
+ var getIedExtRefs = func(iedname string) map[string]*node_attr.NExtRef {
|
|
|
+ iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
|
|
|
+ if iedObj == nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ fcdaObjList := map[string]*node_attr.NExtRef{}
|
|
|
+ for _, t1 := range iedObj.AccessPoint {
|
|
|
+ if t1.Server == nil || len(t1.Server.LDevice) == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ for _, ld := range t1.Server.LDevice {
|
|
|
+ if ld.LN0 != nil && ld.LN0.Inputs != nil {
|
|
|
+ for _, t2 := range ld.LN0.Inputs.ExtRef {
|
|
|
+ doi := scdNodeRule.IedIntAddrExist(iedname, t2.IntAddr)
|
|
|
+ if doi == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ fcdaObjList[doi.(*node_attr.NDOI).Desc] = t2
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for _, ln := range ld.LN {
|
|
|
+ if ln.Inputs == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ for _, t2 := range ln.Inputs.ExtRef {
|
|
|
+ doi := scdNodeRule.IedIntAddrExist(iedname, t2.IntAddr)
|
|
|
+ if doi == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ fcdaObjList[doi.(*node_attr.NDOI).Desc] = t2
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fcdaObjList
|
|
|
+ }
|
|
|
+ //当前装置的所有信号发送端子列表
|
|
|
+ var getIedFcdas = func(iedname string) map[string]*node_attr.NFCDA {
|
|
|
+ iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
|
|
|
+ if iedObj == nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ fcdaObjList := map[string]*node_attr.NFCDA{}
|
|
|
+ for _, t1 := range iedObj.AccessPoint {
|
|
|
+ if t1.Server == nil || len(t1.Server.LDevice) == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ for _, ld := range t1.Server.LDevice {
|
|
|
+ if ld.LN0 != nil && len(ld.LN0.DataSet) > 0 {
|
|
|
+ for _, t2 := range ld.LN0.DataSet {
|
|
|
+ for _, t3 := range t2.FCDA {
|
|
|
+ re, _ := scdNodeRule.IedFcdaExist(iedname, t3.LdInst, t3.LnClass, t3.LnInst, t3.Prefix, t3.DoName, t3.DaName)
|
|
|
+ if re == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ doi := re.(*node_attr.NDOI)
|
|
|
+ fcdaObjList[doi.Desc] = t3
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fcdaObjList
|
|
|
+ }
|
|
|
+ //从装置类型code中解析出类型代码和电压等级
|
|
|
+ var getIedTypeAndVolCode = func(ied_type string) (string, string) {
|
|
|
+ tmp := strings.Split(ied_type, "#")
|
|
|
+ ied_type = tmp[0]
|
|
|
+ vol := ""
|
|
|
+ if len(tmp) == 2 {
|
|
|
+ vol = tmp[1] //电压级别
|
|
|
+ }
|
|
|
+ return ied_type, vol
|
|
|
+ }
|
|
|
+ //从间隔装置中过滤出指定类型的IED
|
|
|
+ var filterAreaIeds = func(ied_type, volLevelCode string, s1 []orm.Params) []orm.Params {
|
|
|
+ iedlst := []orm.Params{}
|
|
|
+ if volLevelCode == "" {
|
|
|
+ for _, r := range s1 {
|
|
|
+ if strings.HasPrefix(tools.IsEmpty(r["ied_name"]), ied_type) {
|
|
|
+ iedlst = append(iedlst, r)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ tmpLst := map[string]orm.Params{}
|
|
|
+ for _, r := range s1 {
|
|
|
+ iedname := tools.IsEmpty(r["ied_name"])
|
|
|
+ if strings.HasPrefix(iedname, ied_type) {
|
|
|
+ tmpLst[iedname] = r
|
|
|
+ }
|
|
|
+ }
|
|
|
+ h, m, l := c.getIedListByVol(ied_type, tmpLst, volMap)
|
|
|
+ if volLevelCode == "H" {
|
|
|
+ iedlst = h
|
|
|
+ }
|
|
|
+ if volLevelCode == "M" {
|
|
|
+ iedlst = m
|
|
|
+ }
|
|
|
+ if volLevelCode == "L" {
|
|
|
+ iedlst = l
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return iedlst
|
|
|
+ }
|
|
|
+
|
|
|
+ //iedRelationMgr := new(SysCheckModelIedRelationMgr)
|
|
|
for _, row := range arealist {
|
|
|
//获取间隔标准装置及关系
|
|
|
modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
|
|
|
area_name := tools.IsEmpty(row["area_name"])
|
|
|
//area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
|
|
|
area_id := tools.IsEmpty(row["id"])
|
|
|
- s, err := iedRelationMgr.GetListByModelid(modelid)
|
|
|
- if err != nil {
|
|
|
- logger.Logger.Error(err)
|
|
|
- return err
|
|
|
+ //获取该间隔模型配置的所有端子关系列表
|
|
|
+ tmpMgr := new(SysCheckModelFcdaRalationMgr)
|
|
|
+ tmpMgr.Model.ModelId = modelid
|
|
|
+ funclist, _ := tmpMgr.GetModelAllFcdaRef()
|
|
|
+ if funclist == nil {
|
|
|
+ continue
|
|
|
}
|
|
|
- if len(s) == 0 {
|
|
|
- return errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid))
|
|
|
+ if len(funclist) == 0 {
|
|
|
+ logger.Logger.Error(errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid)))
|
|
|
+ continue
|
|
|
}
|
|
|
//获取该间隔下该类型的装置
|
|
|
s1 := []orm.Params{}
|
|
|
_, err = db.Raw("select ied_name from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
|
|
|
//循环处理关联关系
|
|
|
- dealIedType := map[string]int{} //已处理过的装置类型
|
|
|
- for _, row2 := range s {
|
|
|
- ied_type := tools.IsEmpty(row2["ied_type"])
|
|
|
- if dealIedType[ied_type] > 0 {
|
|
|
- continue
|
|
|
- }
|
|
|
- //获取装置类型配置的端子列表
|
|
|
- fcdaMgr := new(SysCheckModelIedFuncFcdaMgr)
|
|
|
- funcMgr := new(SysCheckModelIedFuncMgr)
|
|
|
- funcMgr.Model = T_data_model_func_def{ModelId: modelid}
|
|
|
- funclist, _ := funcMgr.GetList(modelid, ied_type)
|
|
|
- if funclist == nil || len(funclist) == 0 {
|
|
|
- continue
|
|
|
- }
|
|
|
- tmp := strings.Split(ied_type, "#")
|
|
|
- ied_type = tmp[0]
|
|
|
- vol := ""
|
|
|
- if len(tmp) == 2 {
|
|
|
- vol = tmp[1] //电压级别
|
|
|
- }
|
|
|
- iedlst := []orm.Params{}
|
|
|
- if vol == "" {
|
|
|
- for _, r := range s1 {
|
|
|
- if strings.HasPrefix(tools.IsEmpty(r["ied_name"]), ied_type) {
|
|
|
- iedlst = append(iedlst, r)
|
|
|
+ for ied_type, fromrowlist := range funclist {
|
|
|
+ //找出信号输出装置
|
|
|
+ outiedlist := map[string][]orm.Params{}
|
|
|
+ for _, r := range fromrowlist {
|
|
|
+ fromiedcode := tools.IsEmpty(r["from_ied_code"])
|
|
|
+ ied_type, vol := getIedTypeAndVolCode(fromiedcode)
|
|
|
+ outiedlist2 := filterAreaIeds(ied_type, vol, s1)
|
|
|
+ for _, iedrow := range outiedlist2 {
|
|
|
+ iedname := tools.IsEmpty(iedrow["ied_name"])
|
|
|
+ if outiedlist[iedname] == nil {
|
|
|
+ outiedlist[iedname] = []orm.Params{}
|
|
|
}
|
|
|
+ outiedlist[iedname] = append(outiedlist[iedname], r)
|
|
|
}
|
|
|
- } else {
|
|
|
- tmpLst := map[string]orm.Params{}
|
|
|
- for _, r := range s1 {
|
|
|
- iedname := tools.IsEmpty(r["ied_name"])
|
|
|
- if strings.HasPrefix(iedname, ied_type) {
|
|
|
- tmpLst[iedname] = r
|
|
|
- }
|
|
|
- }
|
|
|
- h, m, l := c.getIedListByVol(ied_type, tmpLst, volMap)
|
|
|
- if vol == "H" {
|
|
|
- iedlst = h
|
|
|
- }
|
|
|
- if vol == "M" {
|
|
|
- iedlst = m
|
|
|
- }
|
|
|
- if vol == "L" {
|
|
|
- iedlst = l
|
|
|
- }
|
|
|
}
|
|
|
+ if len(outiedlist) == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ ied_type, vol := getIedTypeAndVolCode(ied_type)
|
|
|
+ iedlst := filterAreaIeds(ied_type, vol, s1)
|
|
|
for _, ied := range iedlst {
|
|
|
iedname := tools.IsEmpty(ied["ied_name"])
|
|
|
- iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
|
|
|
- if iedObj == nil {
|
|
|
- continue
|
|
|
- }
|
|
|
- fcdaObjList := []*node_attr.NFCDA{}
|
|
|
- for _, t1 := range iedObj.AccessPoint {
|
|
|
- if t1.Server == nil || len(t1.Server.LDevice) == 0 {
|
|
|
- continue
|
|
|
- }
|
|
|
- for _, ld := range t1.Server.LDevice {
|
|
|
- if ld.LN0 != nil {
|
|
|
- for _, t2 := range ld.LN0.DataSet {
|
|
|
- for _, t3 := range t2.FCDA {
|
|
|
- fcdaObjList = append(fcdaObjList, t3)
|
|
|
- }
|
|
|
+ extreflist := getIedExtRefs(iedname)
|
|
|
+ for outiedname, refrow := range outiedlist {
|
|
|
+ outiedFcdaList := getIedFcdas(outiedname) //输入装置的信号输出端子
|
|
|
+ //检查是否有错误和缺失的端子
|
|
|
+ for _, r := range refrow {
|
|
|
+ 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"])
|
|
|
+ fcda_name_exp := tools.IsEmpty(r["from_fcda_match_exp"])
|
|
|
+ funcExist := false //设计的功能是否存在
|
|
|
+ extrefObj := new(node_attr.NExtRef)
|
|
|
+ for desc, item := range extreflist {
|
|
|
+ rex, err := regexp.Compile(extref_name_exp)
|
|
|
+ if err != nil {
|
|
|
+ logger.Logger.Error(err, "无效的正则表达式:"+extref_name_exp)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if rex.MatchString(desc) {
|
|
|
+ funcExist = true
|
|
|
+ extrefObj = item
|
|
|
+ break
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
- for _, row3 := range funclist {
|
|
|
- funcExist := false //设计的功能是否存在
|
|
|
- funcid, _ := strconv.Atoi(tools.IsEmpty(row3["id"]))
|
|
|
- fcdaMgr.Model = T_data_model_func_fcda{ModelId: modelid, FuncId: funcid}
|
|
|
- fcdalist, _ := fcdaMgr.GetList()
|
|
|
- if fcdalist != nil && len(fcdalist) > 0 {
|
|
|
- //判断端子是否存在
|
|
|
- for _, row4 := range fcdalist {
|
|
|
- fcda_name_match := tools.IsEmpty(row4["fcda_match_exp"])
|
|
|
- fcda_name := tools.IsEmpty(row4["fcda_name"])
|
|
|
- if fcda_name_match == "" {
|
|
|
- fcda_name_match = fcda_name
|
|
|
+ if !funcExist {
|
|
|
+ iedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), iedname)
|
|
|
+ outIedObj := scdNodeMgr.GetIed(scdXmlObj, fmt.Sprintf("%d", c.ScdId), outiedname)
|
|
|
+ parse_result := ""
|
|
|
+ if !funcExist {
|
|
|
+ parse_result = fmt.Sprintf("间隔%s的装置%s缺失端子%s", area_name, iedname, extref_name)
|
|
|
}
|
|
|
- fcdaExist := false
|
|
|
- //获取端子FCDA描述
|
|
|
- if len(fcdaObjList) > 0 {
|
|
|
- for _, t4 := range fcdaObjList {
|
|
|
- re, _ := scdNodeRule.IedFcdaExist(iedname, t4.LdInst, t4.LnClass, t4.LnInst, t4.Prefix, t4.DoName, t4.DaName)
|
|
|
- if re == nil {
|
|
|
- continue
|
|
|
- }
|
|
|
- doi := re.(*node_attr.NDOI)
|
|
|
- desc := doi.Desc
|
|
|
- if fcda_name_match == desc {
|
|
|
- //完全匹配
|
|
|
- fcdaExist = true
|
|
|
- break
|
|
|
- }
|
|
|
- //正则匹配
|
|
|
- //fcda_name_match = strings.ReplaceAll(fcda_name_match)
|
|
|
- rexp := regexp.MustCompile(fcda_name_match)
|
|
|
- if rexp.FindString(desc) != "" {
|
|
|
- fcdaExist = true
|
|
|
- break
|
|
|
- }
|
|
|
+ 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": extref_name,
|
|
|
+ "fcda_addr": "",
|
|
|
+ "out_fcda_desc": fcda_name,
|
|
|
+ "out_fcda_addr": "",
|
|
|
+ "error_type": "3",
|
|
|
+ }
|
|
|
+ //检查未通过
|
|
|
+ scdNodeRule.AppendFcdaCheckResult(re)
|
|
|
+ } else {
|
|
|
+ //检查端子是否关联正确
|
|
|
+ fcda2Exist := false
|
|
|
+ fcdaObj := new(node_attr.NFCDA)
|
|
|
+ for desc, item := range outiedFcdaList {
|
|
|
+ rex, err := regexp.Compile(fcda_name_exp)
|
|
|
+ if err != nil {
|
|
|
+ logger.Logger.Error(err, "无效的正则表达式:"+fcda_name_exp)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if rex.MatchString(desc) {
|
|
|
+ fcda2Exist = true
|
|
|
+ fcdaObj = item
|
|
|
+ break
|
|
|
}
|
|
|
}
|
|
|
- if fcdaExist {
|
|
|
- funcExist = true
|
|
|
- } else {
|
|
|
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失虚端子%s", area_name, iedname, fcda_name)
|
|
|
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
|
|
|
+ if fcda2Exist && (extrefObj.LdInst != fcdaObj.LdInst ||
|
|
|
+ extrefObj.LnInst != fcdaObj.LnInst ||
|
|
|
+ extrefObj.LnClass != fcdaObj.LnClass ||
|
|
|
+ extrefObj.Prefix != fcdaObj.Prefix ||
|
|
|
+ extrefObj.DoName != fcdaObj.DoName) {
|
|
|
+ //不正确
|
|
|
+ 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与装置%s端子%s关联错误", area_name, iedname, extref_name, outiedname, fcda_name)
|
|
|
+ daname := ""
|
|
|
+ if fcdaObj.DaName != "" {
|
|
|
+ daname = "." + fcdaObj.DaName
|
|
|
+ }
|
|
|
+ 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": extref_name,
|
|
|
+ "fcda_addr": extrefObj.IntAddr,
|
|
|
+ "out_fcda_desc": fcda_name,
|
|
|
+ "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", fcdaObj.LdInst, fcdaObj.Prefix, fcdaObj.LnClass, fcdaObj.LnInst, fcdaObj.DoName, daname),
|
|
|
+ "error_type": "2",
|
|
|
+ }
|
|
|
//检查未通过
|
|
|
- scdNodeRule.AppendFcdaCheckResult(r)
|
|
|
+ scdNodeRule.AppendFcdaCheckResult(re)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if !funcExist {
|
|
|
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失功能%s", area_name, iedname, tools.IsEmpty(row3["func_name"]))
|
|
|
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
|
|
|
- //检查未通过
|
|
|
- scdNodeRule.AppendFcdaCheckResult(r)
|
|
|
+ //检查是否有多余(SCD中有不存在于设计中)的端子
|
|
|
+ for extrefdesc, r := range extreflist { //scd中的端子关系
|
|
|
+ extref_name := ""
|
|
|
+ fcda_name := ""
|
|
|
+ isHave := false
|
|
|
+ for _, r1 := range refrow { //设计的端子关系
|
|
|
+ extref_name_exp := tools.IsEmpty(r1["to_fcda_match_exp"])
|
|
|
+ rex, err := regexp.Compile(extref_name_exp)
|
|
|
+ if err != nil {
|
|
|
+ logger.Logger.Error(err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if rex.MatchString(extrefdesc) {
|
|
|
+ //端子存在
|
|
|
+ isHave = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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 != "" {
|
|
|
+ daname = "." + r.DaName
|
|
|
+ }
|
|
|
+ doi := scdNodeRule.IedIntAddrExist(iedname, r.IntAddr)
|
|
|
+ if doi != nil {
|
|
|
+ extref_name = doi.(*node_attr.NDOI).Desc
|
|
|
+ }
|
|
|
+ doi, _ = scdNodeRule.IedFcdaExist(outiedname, r.LdInst, r.LnClass, r.LnInst, r.Prefix, r.DoName, "")
|
|
|
+ if doi != nil {
|
|
|
+ fcda_name = doi.(*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": extref_name,
|
|
|
+ "fcda_addr": r.IntAddr,
|
|
|
+ "out_fcda_desc": fcda_name,
|
|
|
+ "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", r.LdInst, r.Prefix, r.LnClass, r.LnInst, r.DoName, daname),
|
|
|
+ "error_type": "1",
|
|
|
+ }
|
|
|
+ //检查未通过
|
|
|
+ scdNodeRule.AppendFcdaCheckResult(re)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- dealIedType[ied_type] = 1
|
|
|
}
|
|
|
}
|
|
|
scdNodeRule.CheckFinish()
|