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