Эх сурвалжийг харах

开发端子检查业务逻辑

liling 1 жил өмнө
parent
commit
7cb15eb3a1

+ 34 - 0
service/models/bo/check_sysmodel_ied_fcda_relation.go

@@ -4,6 +4,8 @@ import (
 	"fmt"
 	"scd_check_tools/logger"
 	"scd_check_tools/models/enum"
+	"scd_check_tools/tools"
+	"strings"
 
 	"github.com/astaxie/beego/orm"
 )
@@ -121,3 +123,35 @@ func (c *SysCheckModelFcdaRalationMgr) GetList() ([]orm.Params, error) {
 	}
 	return rowset, err
 }
+
+func (c *SysCheckModelFcdaRalationMgr) GetModelAllFcdaRef() (map[string][]orm.Params, error) {
+	db := orm.NewOrm()
+	sql := "select r1.*,f1.fcda_name from_fcda_name,f1.fcda_match_exp from_fcda_match_exp,f2.fcda_name to_fcda_name,f2.fcda_match_exp to_fcda_match_exp from t_data_model_fcda_ref r1 left join t_data_model_func_fcda f1 on r1.from_fcda_id=f1.id left join t_data_model_func_fcda f2 on r1.to_fcda_id=f2.id where r1.model_id=? "
+	rowset := []orm.Params{}
+	sqlParamters := []interface{}{c.Model.ModelId}
+	_, err := db.Raw(sql, sqlParamters).Values(&rowset)
+	if err != nil {
+		logger.Logger.Error(err)
+		return nil, err
+	}
+	result := map[string][]orm.Params{}
+	for _, row := range rowset {
+		toiedcode := tools.IsEmpty(row["to_ied_code"])
+		extref_name_exp := strings.ReplaceAll(tools.IsEmpty(row["to_fcda_match_exp"]), "/", "|")
+		if extref_name_exp == "" {
+			extref_name_exp = tools.IsEmpty(row["to_fcda_name"])
+		}
+		row["to_fcda_match_exp"] = extref_name_exp
+		fcda_name_exp := strings.ReplaceAll(tools.IsEmpty(row["from_fcda_match_exp"]), "/", "|")
+		if fcda_name_exp == "" {
+			fcda_name_exp = tools.IsEmpty(row["from_fcda_name"])
+		}
+		row["from_fcda_match_exp"] = fcda_name_exp
+		if result[toiedcode] == nil {
+			result[toiedcode] = []orm.Params{}
+		}
+		result[toiedcode] = append(result[toiedcode], row)
+	}
+	logger.Logger.Debug(fmt.Sprintf("=====模型%d所有的端子关联关系=====\n%+v", c.Model.ModelId, result))
+	return result, err
+}

+ 17 - 2
service/models/bo/check_sysmodel_ied_func.go

@@ -232,6 +232,9 @@ func (c *SysCheckModelIedFuncMgr) Imp(param map[string]interface{}) (bool, error
 	func_id := 0
 	fcda_id := 0
 	funcMap := map[string]int{} //已处理的功能
+	fcdaMap := map[string]int{}
+	fcdaMgr := new(SysCheckModelIedFuncFcdaMgr)
+	fcdaMgr.Model.ModelId = modelId
 	for _, row := range datalist {
 		ied_type := tools.IsEmpty(row[2])
 		if ied_type == "" {
@@ -249,11 +252,22 @@ func (c *SysCheckModelIedFuncMgr) Imp(param map[string]interface{}) (bool, error
 		if fcda_match_exp == "" {
 			return false, errors.New(fmt.Sprintf("第%d行:端子关键词不能为空", i))
 		}
-		if funcMap[func_name] == 0 {
+		func_id = funcMap[func_name]
+		if func_id == 0 {
 			//获取功能id
 			func_id, _ = c.GetFuncId(modelId, ied_type, func_name)
 			funcMap[func_name] = func_id
 		}
+		if func_id > 0 {
+			fcdaKey := fmt.Sprintf("%d%s", func_id, fcda_name)
+			fcda_id = fcdaMap[fcdaKey]
+			if fcda_id == 0 {
+				fcdaMgr.Model.FuncId = func_id
+				fcdaMgr.Model.FcdaName = fcda_name
+				_, fcda_id, _ := fcdaMgr.Exist()
+				fcdaMap[fcdaKey] = fcda_id
+			}
+		}
 		mod := T_data_model_func_def{}
 		mod.Id = func_id
 		mod.ModelId = modelId
@@ -262,9 +276,10 @@ func (c *SysCheckModelIedFuncMgr) Imp(param map[string]interface{}) (bool, error
 		mod.FuncName = func_name
 		mod.FcdaName = fcda_name
 		mod.FcdaMatchExp = fcda_match_exp
+		c.Model = mod
 		err := c.Save()
 		if err != nil {
-			return false, err
+			return false, errors.New(fmt.Sprintf("第%d行:%s", i, err.Error()))
 		}
 		i = i + 1
 	}

+ 10 - 8
service/models/bo/check_sysmodel_ied_func_fcda.go

@@ -45,12 +45,12 @@ func (c *SysCheckModelIedFuncFcdaMgr) Save() (err error) {
 	dblog.Eventtype = enum.OptEventType_Bus
 	dblog.Eventlevel = enum.OptEventLevel_Hight
 	db := orm.NewOrm()
-	hasName, err := c.Exist()
+	hasName, _, err := c.Exist()
 	if err != nil {
 		return err
 	}
 	if hasName {
-		return errors.New("端子名称已存在")
+		return errors.New("端子名称[" + c.Model.FcdaName + "]已存在")
 	}
 	if c.Model.Id > 0 {
 		//编辑
@@ -70,22 +70,24 @@ func (c *SysCheckModelIedFuncFcdaMgr) Save() (err error) {
 	return err
 }
 
-func (c *SysCheckModelIedFuncFcdaMgr) Exist() (bool, error) {
+func (c *SysCheckModelIedFuncFcdaMgr) Exist() (bool, int, error) {
 	db := orm.NewOrm()
 	if c.Model.FcdaName == "" {
-		return false, errors.New("端子设计名称不能为空")
+		return false, 0, errors.New("端子设计名称不能为空")
 	}
 	rowset := []orm.Params{}
 	_, err := db.Raw("select id from t_data_model_func_fcda where model_id=? and func_id=? and fcda_name=?", c.Model.ModelId, c.Model.FuncId, c.Model.FcdaName).Values(&rowset)
 	if len(rowset) > 0 {
-		if tools.IsEmpty(c.Model.Id) != tools.IsEmpty(rowset[0]["id"]) {
+		findId := tools.IsEmpty(rowset[0]["id"])
+		findIdint, _ := strconv.Atoi(findId)
+		if tools.IsEmpty(c.Model.Id) != findId {
 			//端子名称重复
-			return true, nil
+			return true, c.Model.Id, nil
 		} else {
-			return false, nil
+			return false, findIdint, nil
 		}
 	}
-	return false, err
+	return false, 0, err
 }
 func (c *SysCheckModelIedFuncFcdaMgr) Copy(oldFuncId, newModelId, newFuncId int) error {
 	db := orm.NewOrm()

+ 260 - 113
service/models/bo/checktools_area.go

@@ -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()

+ 23 - 15
service/models/bo/scd_node_rule.go

@@ -2381,7 +2381,7 @@ func (c *ScdNodeRule) IedFcdaExist(iedname, ldinst, lnclass, lninst, prefix, don
 	return nil, ""
 }
 
-func (c *ScdNodeRule) iedIntAddrExist(iedname, intAddr string) (obj interface{}) {
+func (c *ScdNodeRule) IedIntAddrExist(iedname, intAddr string) (obj interface{}) {
 	if c.scdXmlObject == nil {
 		return nil
 	}
@@ -2403,14 +2403,14 @@ func (c *ScdNodeRule) iedIntAddrExist(iedname, intAddr string) (obj interface{})
 		return nil
 	}
 	doda := v_tmpAry[1:]
-	//doname := ""
-	daname := ""
+	doname := ""
+	//daname := ""
 	if len(doda) == 1 {
 		//只有do
-		//doname = doda[0]
+		doname = doda[0]
 	} else {
-		//doname = doda[0]
-		daname = strings.Join(doda[1:], ".") //还原da
+		doname = doda[0]
+		//daname = strings.Join(doda[1:], ".") //还原da
 	}
 	for _, iedObj := range c.scdXmlObject.IED {
 		if iedObj.Name != iedname {
@@ -2419,19 +2419,25 @@ func (c *ScdNodeRule) iedIntAddrExist(iedname, intAddr string) (obj interface{})
 		for _, ap := range iedObj.AccessPoint {
 			if ap.Server != nil {
 				for _, ld := range ap.Server.LDevice {
-					if ld.Inst == ldinst && ld.LN0 != nil {
-						for _, ln := range ld.LN0.DataSet {
-							for _, fcda := range ln.FCDA {
-								str := fmt.Sprintf("%s%s%s.%s", fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName)
-								if daname != "" {
-									str = str + "." + fcda.DaName
+					if ld.Inst == ldinst {
+						if ld.LN0 != nil {
+							if strings.HasPrefix(lnstr, fmt.Sprintf("%s/%s%s%s", ld.Inst, ld.LN0.Prefix, ld.LN0.LnClass, ld.LN0.Inst)) {
+								for _, item := range ld.LN0.DOI {
+									if item.Name == doname {
+										return item
+									}
 								}
-								if str == lnstr {
-									return fcda
+							}
+						}
+						for _, item := range ld.LN {
+							if strings.HasPrefix(lnstr, fmt.Sprintf("%s/%s%s%s", ld.Inst, item.Prefix, item.LnClass, item.Inst)) {
+								for _, item := range item.DOI {
+									if item.Name == doname {
+										return item
+									}
 								}
 							}
 						}
-						return nil
 					}
 				}
 			}
@@ -2587,6 +2593,8 @@ func (c *ScdNodeRule) AppendPaseResult(r map[string]interface{}, ied ...*node_at
 }
 
 //添加端子检查结果
+//需要数据:ied_name,ied_desc,fcda_desc,fcda_addr,out_ied_name,out_ied_desc,out_fcda_desc,out_fcda_addr,error_type
+//其中error_type值为以下之一:1 多余端子 2 错误端子 3 缺失
 func (c *ScdNodeRule) AppendFcdaCheckResult(r map[string]interface{}) {
 	r["check_type"] = "fcda"
 	c.checkFailListLock.Lock()

+ 31 - 5
service/models/bo/task.go

@@ -41,6 +41,9 @@ var TaskSCD = sync.Map{}
 
 var modelDesc = "检测任务"
 
+//已终止的任务
+var stopedTaskMap = sync.Map{}
+
 func init() {
 	orm.RegisterModel(new(T_data_task))
 }
@@ -126,15 +129,31 @@ func (c *TaskMgr) start(task T_data_task) error {
 	db.Raw("delete from t_scd_node_rule_parse where scd_id=?", task.ScdId).Exec()
 	//生成新的步骤
 	db.Raw("insert into t_data_task_check_step(task_id,task_step_id,state) select ?,id,0 from global_const_code where parentcode='CHECK_STEP' order by id", task.Id).Exec()
-	go func() {
+	var isStop = func(taskid int) bool {
+		v, r := stopedTaskMap.Load(taskid)
+		if r {
+			return v.(bool)
+		}
+		return false
+	}
+	go func(task T_data_task, scdInfo orm.Params) {
 		_, err = scdParse.XmlIEDParse(tools.IsEmpty(scdInfo["station_id"]), tools.IsEmpty(scdInfo["path"]), tools.IsEmpty(scdInfo["scd_name"]))
+		if isStop(task.Id) {
+			return
+		}
 		if err == nil {
 			scdParse.XmlCheckParse(task.ScdId)
+			if isStop(task.Id) {
+				return
+			}
 			//模型分析
 			c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_model_parse.Code(), 1)
 			checkAreaMgr := new(CheckAreaMgr)
 			checkAreaMgr.ScdId = task.ScdId
 			err = checkAreaMgr.CheckAreaIedRelation()
+			if isStop(task.Id) {
+				return
+			}
 			if err != nil {
 				c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_model_parse.Code(), 3, err.Error())
 				c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_func_parse.Code(), 3, "终止")
@@ -143,6 +162,9 @@ func (c *TaskMgr) start(task T_data_task) error {
 				c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_model_parse.Code(), 2)
 				//功能分析
 				err = checkAreaMgr.CheckAreaIedRelation()
+				if isStop(task.Id) {
+					return
+				}
 				c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_func_parse.Code(), 1)
 				if err != nil {
 					c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_func_parse.Code(), 3, err.Error())
@@ -152,6 +174,9 @@ func (c *TaskMgr) start(task T_data_task) error {
 					//端子分析
 					c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_fcda_parse.Code(), 1)
 					err = checkAreaMgr.CheckIedFcda()
+					if isStop(task.Id) {
+						return
+					}
 					if err != nil {
 						c.SetStep(tools.IsEmpty(task.ScdId), enum.TaskStep_SCD_fcda_parse.Code(), 3, err.Error())
 					} else {
@@ -160,15 +185,16 @@ func (c *TaskMgr) start(task T_data_task) error {
 				}
 			}
 		}
-	}()
+	}(task, scdInfo)
 	return err
 }
 
 //取消/终止检测
 func (c *TaskMgr) stop(task T_data_task) error {
 	TaskSCD.Delete(task.ScdId)
+	stopedTaskMap.Store(task.Id, true)
 	db := orm.NewOrm()
-	_, err := db.Raw("update t_data_task_check_step set state=3,ut=now() where task_id=? and state=0", task.Id).Exec()
+	_, err := db.Raw("update t_data_task_check_step set state=3,ut=now() where task_id=? and state<2", task.Id).Exec()
 	return err
 }
 
@@ -374,11 +400,11 @@ func (c *TaskMgr) List(pageno, pagesize int) ([]orm.Params, int, error) {
 		sqlParamters = append(sqlParamters, c.Model.State)
 	}
 	if c.Model.StartTime != "" {
-		sql += " and t.start_time>=?"
+		sql += " and t.ct>=?"
 		sqlParamters = append(sqlParamters, c.Model.StartTime+" 00:00:00")
 	}
 	if c.Model.EndTime != "" {
-		sql += " and t.end_time<=?"
+		sql += " and t.ct<=?"
 		sqlParamters = append(sqlParamters, c.Model.EndTime+" 23:59:59")
 	}
 	limit := fmt.Sprintf(" order by t.ct desc limit %d,%d", (pageno-1)*pagesize, pagesize)