checktools_area.go 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459
  1. package bo
  2. import (
  3. "errors"
  4. "fmt"
  5. "regexp"
  6. "scd_check_tools/logger"
  7. "scd_check_tools/models/enum"
  8. "scd_check_tools/models/node_attr"
  9. "scd_check_tools/tools"
  10. "strconv"
  11. "strings"
  12. "sync"
  13. "github.com/astaxie/beego/orm"
  14. )
  15. //检测时间隔管理
  16. type CheckAreaMgr struct {
  17. DeviceBaseModel
  18. //SCD文件ID
  19. ScdId int64
  20. //电压等级定义
  21. VoltageLevelDef map[string]int
  22. //设备类型定义
  23. DeviceTypeDef map[string]int
  24. CacheAreaID map[string]int64
  25. CacheAreaIDByIedNameNo map[string]int
  26. //检测模型列表
  27. CheckModelList []orm.Params
  28. //模型内装置关系定义
  29. CheckModelDef sync.Map
  30. CacheLock sync.RWMutex
  31. }
  32. type T_data_check_area struct {
  33. Id int64 `orm:"pk"`
  34. AreaName string
  35. ScdId int64
  36. VoltageLevel int
  37. AreaType string
  38. ModelId int
  39. Cr int // '创建人' ,
  40. Ct string `orm:"-"` // '创建时间' ,
  41. Ur int // '更新人' ,
  42. Ut string `orm:"-"` // '更新时间'
  43. }
  44. type t_data_check_area_ied struct {
  45. Id int64 `orm:"pk"`
  46. AreaId int64
  47. IedName string
  48. IedType string
  49. ScdId int64
  50. PType string
  51. Cr int // '创建人' ,
  52. Ct string `orm:"-"` // '创建时间' ,
  53. Ur int // '更新人' ,
  54. Ut string `orm:"-"` // '更新时间'
  55. }
  56. func init() {
  57. orm.RegisterModel(new(T_data_check_area))
  58. orm.RegisterModel(new(t_data_check_area_ied))
  59. }
  60. func (c *CheckAreaMgr) Init(scdid int64) {
  61. c.VoltageLevelDef = map[string]int{}
  62. c.DeviceTypeDef = map[string]int{}
  63. c.CacheAreaIDByIedNameNo = map[string]int{}
  64. c.CacheAreaID = map[string]int64{}
  65. c.CacheLock = sync.RWMutex{}
  66. c.ScdId = scdid
  67. db := orm.NewOrm()
  68. rowset := []orm.Params{}
  69. db.Raw("select * from global_const_code where parentcode=?", "voltage_level").Values(&rowset)
  70. for _, row := range rowset {
  71. vl := strings.ToLower(tools.IsEmpty(row["code"]))
  72. id, _ := strconv.ParseInt(tools.IsEmpty(row["id"]), 10, 32)
  73. c.VoltageLevelDef[strings.ReplaceAll(vl, "v_level_", "")] = int(id)
  74. }
  75. db.Raw("select * from global_const_code where parentcode=?", "device_type").Values(&rowset)
  76. for _, row := range rowset {
  77. vl := tools.IsEmpty(row["code"])
  78. c.DeviceTypeDef[vl] = 1
  79. }
  80. v, _ := GetSysParamValue("OtherIedNameList", "")
  81. otherIedNameList = map[string]bool{}
  82. if v != "" {
  83. vs := strings.Split(v, ",")
  84. for _, vv := range vs {
  85. otherIedNameList[vv] = true
  86. }
  87. }
  88. //先清除ied与间隔关联关系
  89. clearSql := "delete from t_data_check_area_ied where area_id in(select id from t_data_check_area where scd_id=?)"
  90. _, err := db.Raw(clearSql, c.ScdId).Exec()
  91. if err != nil {
  92. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", clearSql, []interface{}{c.ScdId}))
  93. }
  94. clearSql = "delete from t_data_check_area where scd_id=?"
  95. _, err = db.Raw(clearSql, c.ScdId).Exec()
  96. if err != nil {
  97. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", clearSql, []interface{}{c.ScdId}))
  98. }
  99. //获取当前scd信息中获取到对应的电压等级id
  100. /*
  101. scdMgr := new(ScdMgr)
  102. scdinfo, _ := scdMgr.One(fmt.Sprintf("%d", c.ScdId))
  103. stationid := tools.IsEmpty(scdinfo["station_id"])
  104. volid := 0
  105. if stationid != "" {
  106. basearea := new(BasicArea)
  107. stationonof, _ := basearea.One(stationid)
  108. volid = stationonof.AreaLevel
  109. }
  110. */
  111. tmplist, _ := new(SysCheckModelMgr).GetModelsByVolid(2)
  112. scdModels, _, _ := new(TaskMgr).GetModelsByScdID(c.ScdId)
  113. ms := map[string]interface{}{}
  114. for _, row := range scdModels {
  115. ms[tools.IsEmpty(row["model_id"])] = row
  116. }
  117. for _, row := range tmplist {
  118. modelid := tools.IsEmpty(row["id"])
  119. if ms[modelid] != nil {
  120. c.CheckModelList = append(c.CheckModelList, row)
  121. }
  122. }
  123. logger.Logger.Debug(fmt.Sprintf("任务的模型列表:%+v", c.CheckModelList))
  124. ms = nil
  125. tmplist = nil
  126. }
  127. //保存指定间隔所属的电压等级
  128. func (c *CheckAreaMgr) SetVoltageLevel(id string, voltagelevel int) error {
  129. db := orm.NewOrm()
  130. _, err := db.Raw("update t_data_check_area set voltage_level=? where id=?", voltagelevel, id).Exec()
  131. return err
  132. }
  133. //修改指定间隔的名称
  134. func (c *CheckAreaMgr) UpdateName(scdid int64, area_id int, name string) error {
  135. db := orm.NewOrm()
  136. areaM := T_data_check_area{Id: int64(area_id), ScdId: scdid}
  137. err := db.Read(&areaM)
  138. if err != nil {
  139. logger.Logger.Error(err)
  140. return err
  141. }
  142. areaM.AreaName = name
  143. _, err = db.Update(&areaM)
  144. if err != nil {
  145. logger.Logger.Error(err)
  146. }
  147. return err
  148. }
  149. //修改指定IED的所属间隔
  150. func (c *CheckAreaMgr) UpdateIedArea(scdid int64, iedname string, area_id int) error {
  151. db := orm.NewOrm()
  152. _, err := db.Raw("update t_data_check_area_ied set area_id=? where scd_id=? and ied_name=?", area_id, scdid, iedname).Exec()
  153. return err
  154. }
  155. //获取指定scd的间隔信息
  156. func (c *CheckAreaMgr) GetAreaList(scdid int64) ([]orm.Params, error) {
  157. db := orm.NewOrm()
  158. sql := "select t.*,(select count(1) from t_data_check_area_ied where area_id=t.id) iedcount from t_data_check_area t where t.scd_id=? order by t.name"
  159. rowset := []orm.Params{}
  160. _, err := db.Raw(sql, scdid).Values(&rowset)
  161. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{scdid})
  162. if err != nil {
  163. logger.Logger.Error(err, sqllog)
  164. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  165. } else {
  166. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  167. }
  168. return rowset, nil
  169. }
  170. //获取指定scd和电压等级的间隔信息
  171. func (c *CheckAreaMgr) GetAreaListByVol(scdid int64, vl, linkstyleid int) ([]orm.Params, error) {
  172. db := orm.NewOrm()
  173. sql := "select t1.id model_id, t1.model_name,t1.vol_id,g1.name vol_name,t1.line_link_style,ls.name,t.id area_id, t.area_name,t.ut,t.ur from t_data_check_area t right join t_data_model_defualt t1 on t.model_id=t1.id left join t_data_link_style ls on t1.line_link_style=ls.id left join global_const_code g1 on t1.vol_id=g1.id and g1.parentcode='voltage_level' where t.scd_id=? "
  174. params := []interface{}{scdid}
  175. if vl > 0 {
  176. sql = sql + " and t1.vol_id=? "
  177. params = append(params, vl)
  178. }
  179. if linkstyleid > 0 {
  180. sql = sql + " and t1.line_link_style=? "
  181. params = append(params, linkstyleid)
  182. }
  183. rowset := []orm.Params{}
  184. _, err := db.Raw(sql+" order by t1.vol_id,t1.line_link_style,t1.id", params).Values(&rowset)
  185. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{scdid, vl})
  186. if err != nil {
  187. logger.Logger.Error(err, sqllog)
  188. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  189. } else {
  190. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  191. }
  192. return rowset, nil
  193. }
  194. //获取指定间隔下的IED列表
  195. func (c *CheckAreaMgr) GetIedList(scdid int64, areaid int) ([]orm.Params, error) {
  196. db := orm.NewOrm()
  197. sql := "select t1.* from t_data_check_area t,t_data_check_area_ied t1 where t.scd_id=? and t.id=t1.area_id "
  198. sqlParamters := []interface{}{}
  199. sqlParamters = append(sqlParamters, scdid)
  200. if areaid > 0 {
  201. sql = sql + " and t1.area_id=?"
  202. sqlParamters = append(sqlParamters, areaid)
  203. }
  204. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  205. if serr != nil {
  206. return nil, serr
  207. }
  208. if scdXmlObj == nil {
  209. return nil, errors.New("无效的SCD")
  210. }
  211. rowset := []orm.Params{}
  212. _, err := db.Raw(sql, sqlParamters).Values(&rowset)
  213. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, sqlParamters)
  214. if err != nil {
  215. logger.Logger.Error(err, sqllog)
  216. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  217. } else {
  218. scdNode := new(ScdNode)
  219. for i, row := range rowset {
  220. iedObj := scdNode.GetIed(scdXmlObj, tools.IsEmpty(scdid), tools.IsEmpty(row["ied_name"]))
  221. if iedObj == nil {
  222. continue
  223. }
  224. rowset[i]["attr_name"] = iedObj.Name
  225. rowset[i]["attr_desc"] = iedObj.Desc
  226. rowset[i]["attr_config_version"] = iedObj.ConfigVersion
  227. rowset[i]["attr_type"] = iedObj.Type
  228. rowset[i]["attr_manufacturer"] = iedObj.Manufacturer
  229. rowset[i]["ied_id"] = iedObj.NodeId
  230. }
  231. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  232. }
  233. return rowset, nil
  234. }
  235. //更新指定间隔下的装置定义
  236. func (c *CheckAreaMgr) UpdateIeds(scdid int64, areaid int, ieds string) error {
  237. db := orm.NewOrm()
  238. iedlist := strings.Split(ieds, ",")
  239. _, err := db.Raw("delete from t_data_check_area_ied where scd_id=? and area_id=?", scdid, areaid).Exec()
  240. if err != nil {
  241. logger.Logger.Error(err)
  242. return err
  243. }
  244. for _, row := range iedlist {
  245. _, err = db.Raw("insert into t_data_check_area_ied(scd_id,area_id,ied_name)values(?,?,?)", scdid, areaid, row).Exec()
  246. if err != nil {
  247. logger.Logger.Error(err)
  248. break
  249. }
  250. }
  251. return err
  252. }
  253. //获取指定SCD的IED类型列表
  254. func (c *CheckAreaMgr) GetIedTypeList(scdid int64) ([]orm.Params, error) {
  255. db := orm.NewOrm()
  256. sql := "select t2.* from t_data_check_area_ied t1,global_const_code t2 where t1.scd_id=? and t1.ied_type=t2.code and t2.parentcode='device_type' group by t1.ied_type "
  257. sqlParamters := []interface{}{}
  258. rowset := []orm.Params{}
  259. sqlParamters = append(sqlParamters, scdid)
  260. _, err := db.Raw(sql, sqlParamters).Values(&rowset)
  261. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, sqlParamters)
  262. if err != nil {
  263. logger.Logger.Error(err, sqllog)
  264. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  265. }
  266. return rowset, nil
  267. }
  268. func (c *CheckAreaMgr) One(id string) (interface{}, error) {
  269. db := orm.NewOrm()
  270. idInt, err := strconv.ParseInt(id, 10, 64)
  271. if err != nil {
  272. return nil, err
  273. }
  274. areaM := T_data_check_area{Id: idInt}
  275. err = db.Read(&areaM)
  276. if err == nil {
  277. return areaM, nil
  278. }
  279. return nil, err
  280. }
  281. //重置scd的间隔信息
  282. func (c *CheckAreaMgr) Reset() error {
  283. dbo := orm.NewOrm()
  284. dbo.Raw("delete from t_data_check_area where scd_id=?", c.ScdId).Exec()
  285. dbo.Raw("delete from t_data_check_area_ied where scd_id=?", c.ScdId).Exec()
  286. c.ParseModelArea()
  287. logdesc := fmt.Sprintf("重置SCD[%d]检测模型间隔成功", c.ScdId)
  288. new(SystemLog).Success(enum.AuditType_check_task, enum.LogType_bind, enum.OptEventType_Bus, enum.OptEventLevel_Mid, logdesc, c.GetUserInfo())
  289. return nil
  290. }
  291. var areaCheckInfo = sync.Map{}
  292. //获取解析模型需要的基础数据信息
  293. func (c *CheckAreaMgr) getAreaCheckInfo() (*node_attr.SCL, []orm.Params, string, error) {
  294. key := fmt.Sprintf("%d-checkinfo", c.ScdId)
  295. if v, h := areaCheckInfo.Load(key); h {
  296. v1 := v.([]interface{})
  297. return v1[0].(*node_attr.SCL), v1[1].([]orm.Params), v1[2].(string), nil
  298. }
  299. arealist := []orm.Params{}
  300. db := orm.NewOrm()
  301. _, err := db.Raw("select id,area_name,area_type,model_id from t_data_check_area where scd_id=?", c.ScdId).Values(&arealist)
  302. if err != nil {
  303. logger.Logger.Error(err)
  304. return nil, nil, "", err
  305. }
  306. scdNodeRule := new(ScdNodeRule)
  307. area_ruleid := ""
  308. area_ruleList, _, _ := scdNodeRule.GetDefList(map[string]interface{}{"check_name": "间隔装置与检查模型不符"}, 1, 1)
  309. if len(area_ruleList) > 0 {
  310. area_ruleid = tools.IsEmpty(area_ruleList[0]["id"])
  311. }
  312. if area_ruleid == "" {
  313. return nil, nil, "", errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
  314. }
  315. scdParseMgr := new(ScdParse)
  316. scdXmlObj, serr := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  317. if serr != nil {
  318. return nil, nil, "", serr
  319. }
  320. if scdXmlObj == nil {
  321. return nil, nil, "", errors.New("无效的SCD")
  322. }
  323. areaCheckInfo.Store(key, []interface{}{scdXmlObj, arealist, area_ruleid})
  324. return scdXmlObj, arealist, area_ruleid, nil
  325. }
  326. //检测间隔装置关系正确性
  327. func (c *CheckAreaMgr) CheckAreaIedRelation() error {
  328. // 获取当前scd中需要检查的间隔
  329. scdXmlObj, arealist, area_ruleid, err := c.getAreaCheckInfo()
  330. db := orm.NewOrm()
  331. if err != nil {
  332. logger.Logger.Error(err)
  333. return err
  334. }
  335. if area_ruleid == "" {
  336. return errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
  337. }
  338. if scdXmlObj == nil {
  339. return errors.New("无效的SCD")
  340. }
  341. scdNodeRule := new(ScdNodeRule)
  342. scdNode := new(ScdNode)
  343. model_refs := map[string][]orm.Params{} //模型定义的装置关系定义
  344. area_ieds := map[string][]orm.Params{} //间隔下的装置列表
  345. iedRelationMgr := new(SysCheckModelIedRelationMgr)
  346. for _, row := range arealist {
  347. //获取间隔标准装置及关系
  348. modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
  349. //area_name := tools.IsEmpty(row["area_name"])
  350. //area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
  351. area_id := tools.IsEmpty(row["id"])
  352. s, err := iedRelationMgr.GetListByModelid(modelid)
  353. if err != nil {
  354. logger.Logger.Error(err)
  355. return err
  356. }
  357. if len(s) == 0 {
  358. return errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid))
  359. }
  360. model_refs[fmt.Sprintf("%d", modelid)] = s
  361. /*
  362. hasIeds := map[string]bool{}
  363. for _, row1 := range s {
  364. iedname := tools.IsEmpty(row1["from_ied_code"])
  365. if !hasIeds[iedname] {
  366. hasIeds[iedname] = true
  367. }
  368. iedname = tools.IsEmpty(row1["to_ied_code"])
  369. if !hasIeds[iedname] {
  370. hasIeds[iedname] = true
  371. }
  372. }
  373. */
  374. s1 := []orm.Params{}
  375. _, err = db.Raw("select ied_name from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
  376. if err != nil {
  377. logger.Logger.Error(err)
  378. return err
  379. }
  380. if len(s) == 0 {
  381. return errors.New(fmt.Sprintf("间隔%s未发现任何装置", tools.IsEmpty(row["area_name"])))
  382. }
  383. area_ieds[area_id] = s1
  384. /*
  385. curIeds := map[string]string{}
  386. for _, row1 := range s1 {
  387. iedname := strings.Trim(tools.IsEmpty(row1["ied_name"]), " ")
  388. iedParts := scdParseMgr.ParseIedName(iedname)
  389. iedtype := iedParts[0] + iedParts[1] + iedParts[2]
  390. curIeds[iedtype] = iedname
  391. }
  392. for k, _ := range hasIeds {
  393. iedname := curIeds[k]
  394. if iedname == "" {
  395. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, k)
  396. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  397. //检查未通过
  398. scdNodeRule.AppendPaseResult(r)
  399. } else {
  400. //判断装置是否存在
  401. if scdNode.GetIed(scdXmlObj, "", iedname) == nil {
  402. parse_result := fmt.Sprintf("间隔%s内装置%s未定义", area_name, iedname)
  403. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  404. //检查未通过
  405. scdNodeRule.AppendPaseResult(r)
  406. }
  407. }
  408. }*/
  409. }
  410. //装置关联关系分析
  411. //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
  412. HasAreaJ := false
  413. for _, row := range arealist {
  414. area_name := tools.IsEmpty(row["area_name"])
  415. areaCode := tools.IsEmpty(row["area_type"]) //间隔模型类型
  416. area_id := tools.IsEmpty(row["id"])
  417. if areaCode == "J" {
  418. HasAreaJ = true
  419. modelid := tools.IsEmpty(row["model_id"])
  420. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PE", area_ruleid)
  421. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PJ", area_ruleid)
  422. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PK", area_ruleid)
  423. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PF", area_ruleid)
  424. }
  425. }
  426. for _, row := range arealist {
  427. area_name := tools.IsEmpty(row["area_name"])
  428. areaCode := tools.IsEmpty(row["area_type"]) //间隔模型类型
  429. area_id := tools.IsEmpty(row["id"])
  430. modelid := tools.IsEmpty(row["model_id"])
  431. if areaCode == "J" {
  432. continue
  433. }
  434. if areaCode == "L" {
  435. //线路间隔
  436. c.cL(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], area_ruleid)
  437. }
  438. if areaCode == "T" {
  439. //变压器齐间隔
  440. c.cT(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], area_ruleid, HasAreaJ)
  441. }
  442. }
  443. scdNodeRule.CheckFinish()
  444. scdNodeRule.Flush()
  445. return nil
  446. }
  447. //检测装置功能分析
  448. func (c *CheckAreaMgr) CheckIedFunc() error {
  449. return nil
  450. }
  451. //检测装置端子分析
  452. func (c *CheckAreaMgr) CheckIedFcda() error {
  453. scdXmlObj, arealist, area_ruleid, err := c.getAreaCheckInfo()
  454. if err != nil {
  455. logger.Logger.Error(err)
  456. return err
  457. }
  458. if area_ruleid == "" {
  459. return errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
  460. }
  461. if scdXmlObj == nil {
  462. return errors.New("无效的SCD")
  463. }
  464. db := orm.NewOrm()
  465. //获取当前站的各电压等级
  466. volRows := []orm.Params{}
  467. _, err = db.Raw("select t.vol, CAST(REPLACE(UPPER(g.name),'KV','') as SIGNED) volname from t_area_ied_relation t,global_const_code g where g.code=CONCAT('v_level_',t.vol) and g.parentcode='voltage_level' and t.vol!=999 and t.scd_id=? GROUP BY t.vol ORDER BY volname desc", c.ScdId).Values(&volRows)
  468. if err != nil {
  469. logger.Logger.Error(err)
  470. return err
  471. }
  472. if len(volRows) == 0 {
  473. logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
  474. return errors.New("该scd未发现任何电压等级的装置")
  475. }
  476. volMap := map[string]string{}
  477. volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
  478. if len(volRows) == 2 {
  479. volMap["middle"] = ""
  480. volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
  481. } else {
  482. volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
  483. volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
  484. }
  485. scdNodeRule := new(ScdNodeRule)
  486. scdNodeMgr := new(ScdNode)
  487. iedRelationMgr := new(SysCheckModelIedRelationMgr)
  488. for _, row := range arealist {
  489. //获取间隔标准装置及关系
  490. modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
  491. area_name := tools.IsEmpty(row["area_name"])
  492. //area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
  493. area_id := tools.IsEmpty(row["id"])
  494. s, err := iedRelationMgr.GetListByModelid(modelid)
  495. if err != nil {
  496. logger.Logger.Error(err)
  497. return err
  498. }
  499. if len(s) == 0 {
  500. return errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid))
  501. }
  502. //获取该间隔下该类型的装置
  503. s1 := []orm.Params{}
  504. _, err = db.Raw("select ied_name from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
  505. //循环处理关联关系
  506. dealIedType := map[string]int{} //已处理过的装置类型
  507. for _, row2 := range s {
  508. ied_type := tools.IsEmpty(row2["ied_type"])
  509. if dealIedType[ied_type] > 0 {
  510. continue
  511. }
  512. //获取装置类型配置的端子列表
  513. fcdaMgr := new(SysCheckModelIedFuncFcdaMgr)
  514. funcMgr := new(SysCheckModelIedFuncMgr)
  515. funcMgr.Model = T_data_model_func_def{ModelId: modelid}
  516. funclist, _ := funcMgr.GetList(modelid, ied_type)
  517. if funclist == nil || len(funclist) == 0 {
  518. continue
  519. }
  520. tmp := strings.Split(ied_type, "#")
  521. ied_type = tmp[0]
  522. vol := ""
  523. if len(tmp) == 2 {
  524. vol = tmp[1] //电压级别
  525. }
  526. iedlst := []orm.Params{}
  527. if vol == "" {
  528. for _, r := range s1 {
  529. if strings.HasPrefix(tools.IsEmpty(r["ied_name"]), ied_type) {
  530. iedlst = append(iedlst, r)
  531. }
  532. }
  533. } else {
  534. tmpLst := map[string]orm.Params{}
  535. for _, r := range s1 {
  536. iedname := tools.IsEmpty(r["ied_name"])
  537. if strings.HasPrefix(iedname, ied_type) {
  538. tmpLst[iedname] = r
  539. }
  540. }
  541. h, m, l := c.getIedListByVol(ied_type, tmpLst, volMap)
  542. if vol == "H" {
  543. iedlst = h
  544. }
  545. if vol == "M" {
  546. iedlst = m
  547. }
  548. if vol == "L" {
  549. iedlst = l
  550. }
  551. }
  552. for _, ied := range iedlst {
  553. iedname := tools.IsEmpty(ied["ied_name"])
  554. iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
  555. if iedObj == nil {
  556. continue
  557. }
  558. fcdaObjList := []*node_attr.NFCDA{}
  559. for _, t1 := range iedObj.AccessPoint {
  560. if t1.Server == nil || len(t1.Server.LDevice) == 0 {
  561. continue
  562. }
  563. for _, ld := range t1.Server.LDevice {
  564. if ld.LN0 != nil {
  565. for _, t2 := range ld.LN0.DataSet {
  566. for _, t3 := range t2.FCDA {
  567. fcdaObjList = append(fcdaObjList, t3)
  568. }
  569. }
  570. }
  571. }
  572. }
  573. for _, row3 := range funclist {
  574. funcExist := false //设计的功能是否存在
  575. funcid, _ := strconv.Atoi(tools.IsEmpty(row3["id"]))
  576. fcdaMgr.Model = T_data_model_func_fcda{ModelId: modelid, FuncId: funcid}
  577. fcdalist, _ := fcdaMgr.GetList()
  578. if fcdalist != nil && len(fcdalist) > 0 {
  579. //判断端子是否存在
  580. for _, row4 := range fcdalist {
  581. fcda_name_match := tools.IsEmpty(row4["fcda_match_exp"])
  582. fcda_name := tools.IsEmpty(row4["fcda_name"])
  583. if fcda_name_match == "" {
  584. fcda_name_match = fcda_name
  585. }
  586. fcdaExist := false
  587. //获取端子FCDA描述
  588. if len(fcdaObjList) > 0 {
  589. for _, t4 := range fcdaObjList {
  590. re, _ := scdNodeRule.IedFcdaExist(iedname, t4.LdInst, t4.LnClass, t4.LnInst, t4.Prefix, t4.DoName, t4.DaName)
  591. if re == nil {
  592. continue
  593. }
  594. doi := re.(*node_attr.NDOI)
  595. desc := doi.Desc
  596. if fcda_name_match == desc {
  597. //完全匹配
  598. fcdaExist = true
  599. break
  600. }
  601. //正则匹配
  602. //fcda_name_match = strings.ReplaceAll(fcda_name_match)
  603. rexp := regexp.MustCompile(fcda_name_match)
  604. if rexp.FindString(desc) != "" {
  605. fcdaExist = true
  606. break
  607. }
  608. }
  609. }
  610. if fcdaExist {
  611. funcExist = true
  612. } else {
  613. parse_result := fmt.Sprintf("间隔%s的装置%s缺失虚端子%s", area_name, iedname, fcda_name)
  614. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  615. //检查未通过
  616. scdNodeRule.AppendPaseResult(r)
  617. }
  618. }
  619. }
  620. if !funcExist {
  621. parse_result := fmt.Sprintf("间隔%s的装置%s缺失功能%s", area_name, iedname, tools.IsEmpty(row3["func_name"]))
  622. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  623. //检查未通过
  624. scdNodeRule.AppendPaseResult(r)
  625. }
  626. }
  627. }
  628. dealIedType[ied_type] = 1
  629. }
  630. }
  631. scdNodeRule.CheckFinish()
  632. scdNodeRule.Flush()
  633. return nil
  634. }
  635. //解析模型间隔
  636. func (c *CheckAreaMgr) ParseModelArea() {
  637. c.Init(c.ScdId)
  638. key := fmt.Sprintf("%d-checkinfo", c.ScdId)
  639. areaCheckInfo.Delete(key)
  640. // 取得当前scd所有ied及名称解析结果
  641. dbo := orm.NewOrm()
  642. sql := "select t.*,t1.name area_name from t_area_ied_relation t,t_substation_area t1 where t.area_id=t1.id and t.scd_id=? order by t.p_type"
  643. iedlst := []orm.Params{}
  644. _, err := dbo.Raw(sql, c.ScdId).Values(&iedlst)
  645. if err != nil {
  646. logger.Logger.Error(err)
  647. return
  648. }
  649. logger.Logger.Debug(fmt.Sprintf("=====总装置数:%d", len(iedlst)))
  650. iedMap := map[string]orm.Params{}
  651. for _, r := range iedlst {
  652. iedMap[tools.IsEmpty(r["ied_name"])] = r
  653. }
  654. //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
  655. HasAreaJ := false
  656. for _, row := range c.CheckModelList {
  657. areaCode := tools.IsEmpty(row["area_type_code"])
  658. if areaCode == "J" {
  659. HasAreaJ = true
  660. modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
  661. //modelname := tools.IsEmpty(row["model_name"])
  662. iedtypes := tools.IsEmpty(row["ied_types"])
  663. volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
  664. c.pJ(modelid, volcode, iedtypes, iedMap, "PE")
  665. c.pJ(modelid, volcode, iedtypes, iedMap, "PJ")
  666. c.pJ(modelid, volcode, iedtypes, iedMap, "PK")
  667. c.pJ(modelid, volcode, iedtypes, iedMap, "PF")
  668. }
  669. }
  670. for _, row := range c.CheckModelList {
  671. //逐一分析模型定义
  672. modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
  673. modelname := tools.IsEmpty(row["model_name"])
  674. iedtypes := tools.IsEmpty(row["ied_types"])
  675. //模型对应的间隔代码
  676. /*
  677. S 站用变压器
  678. C 电容器
  679. B 断路器
  680. K 母分
  681. J 母联
  682. M 母线
  683. X 电抗器
  684. L 线路
  685. T 主变压器
  686. */
  687. areaCode := tools.IsEmpty(row["area_type_code"])
  688. //模型对应的电压等级
  689. //10:10KV 35:35KV 66:66KV 11:110KV 22:220KV 50:500KV 75:750KV 33:330KV T0:1000KV
  690. volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
  691. if modelname == "" || iedtypes == "" {
  692. continue
  693. }
  694. //母联间隔已经提前分析,如果没有母联间隔时,主变间隔中不包含母联终端装置
  695. if areaCode == "J" {
  696. continue
  697. }
  698. //获取模型内中装备关系定义
  699. //主变间隔分析:需要查站内该电压等级下的高中低压侧装置或者高低压装置组成一个间隔,以主变保护装置(PT)为起始
  700. if areaCode == "T" {
  701. c.pT(modelid, iedtypes, iedMap, HasAreaJ)
  702. }
  703. //线路保护间隔分析:以线路保护测控装置(PL)为开始分析
  704. if areaCode == "L" {
  705. c.pL(modelid, volcode, iedtypes, iedMap)
  706. }
  707. }
  708. }
  709. //变压器间隔分析
  710. func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Params, HasAreaJ bool) {
  711. scdParseMgr := new(ScdParse)
  712. db := orm.NewOrm()
  713. //获取当前站的各电压等级
  714. volRows := []orm.Params{}
  715. _, err := db.Raw("select t.vol, CAST(REPLACE(UPPER(g.name),'KV','') as SIGNED) volname from t_area_ied_relation t,global_const_code g where g.code=CONCAT('v_level_',t.vol) and g.parentcode='voltage_level' and t.vol!=999 and t.scd_id=? GROUP BY t.vol ORDER BY volname desc", c.ScdId).Values(&volRows)
  716. if err != nil {
  717. logger.Logger.Error(err)
  718. return
  719. }
  720. if len(volRows) == 0 {
  721. logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
  722. return
  723. }
  724. volMap := map[string]string{}
  725. volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
  726. if len(volRows) == 2 {
  727. volMap["middle"] = ""
  728. volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
  729. } else {
  730. volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
  731. volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
  732. }
  733. for _, row := range ieds {
  734. if tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "T" {
  735. continue
  736. }
  737. //pmIedName := ""
  738. //mmIedName := ""
  739. pl_iedname := tools.IsEmpty(row["ied_name"])
  740. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  741. //添加间隔数据
  742. dbdata := T_data_check_area{
  743. ModelId: modelid,
  744. ScdId: c.ScdId,
  745. AreaType: "T",
  746. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  747. }
  748. newid, err := db.Insert(&dbdata)
  749. if err != nil {
  750. logger.Logger.Error(err)
  751. return
  752. }
  753. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  754. insvalues := []string{}
  755. inAreaIedName := pl_iedname
  756. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "T"))
  757. //合智一体IMT/MIT,分高中低压
  758. h, m, l := c.getIedListByVol("IMT", ieds, volMap)
  759. h = append(h, m...)
  760. h = append(h, l...)
  761. for _, r := range h {
  762. inAreaIedName = tools.IsEmpty(r["ied_name"])
  763. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  764. lastChar := tmpIednameParts[7]
  765. if lastChar == iednameParts[7] {
  766. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "IM", "T"))
  767. }
  768. }
  769. h, m, l = c.getIedListByVol("MIT", ieds, volMap)
  770. h = append(h, m...)
  771. h = append(h, l...)
  772. for _, r := range h {
  773. inAreaIedName = tools.IsEmpty(r["ied_name"])
  774. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  775. lastChar := tmpIednameParts[7]
  776. if lastChar == iednameParts[7] {
  777. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "MI", "T"))
  778. }
  779. }
  780. //母联智能终端IE需要分高中压,无低压侧
  781. if HasAreaJ {
  782. h, m, l = c.getIedListByVol("IE", ieds, volMap)
  783. for _, r := range h {
  784. //高压侧,AB套必须与PT装置相同
  785. inAreaIedName = tools.IsEmpty(r["ied_name"])
  786. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  787. lastChar := tmpIednameParts[7]
  788. if lastChar == iednameParts[7] {
  789. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "E"))
  790. }
  791. }
  792. for _, r := range m {
  793. //中压侧
  794. inAreaIedName = tools.IsEmpty(r["ied_name"])
  795. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  796. lastChar := tmpIednameParts[7]
  797. if lastChar == "" || lastChar == iednameParts[7] {
  798. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "E"))
  799. }
  800. }
  801. }
  802. //合并单元MT分高中低压侧;低压侧无关联母线合并单元MM
  803. h, m, l = c.getIedListByVol("MT", ieds, volMap)
  804. h = append(h, m...)
  805. h = append(h, l...)
  806. for _, r := range h {
  807. inAreaIedName = tools.IsEmpty(r["ied_name"])
  808. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  809. lastChar := tmpIednameParts[7]
  810. if lastChar == iednameParts[7] {
  811. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "T"))
  812. }
  813. }
  814. //测控装置CT分高中低压侧,且可能是多套合并单元MT共用,既不分AB套
  815. h, m, l = c.getIedListByVol("CT", ieds, volMap)
  816. h = append(h, m...)
  817. h = append(h, l...)
  818. for _, r := range h {
  819. inAreaIedName = tools.IsEmpty(r["ied_name"])
  820. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  821. lastChar := tmpIednameParts[7]
  822. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  823. //高中低压电压等级相同的
  824. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  825. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "C", "T"))
  826. }
  827. }
  828. //智能终端(IB:开关\IT:分支\IF:分段)分高中低压侧
  829. h, m, l = c.getIedListByVol("IB", ieds, volMap)
  830. h = append(h, m...)
  831. h = append(h, l...)
  832. for _, r := range h {
  833. inAreaIedName = tools.IsEmpty(r["ied_name"])
  834. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  835. lastChar := tmpIednameParts[7]
  836. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  837. //高中低压电压等级相同的
  838. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  839. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "B"))
  840. }
  841. }
  842. h, m, l = c.getIedListByVol("IT", ieds, volMap)
  843. h = append(h, m...)
  844. h = append(h, l...)
  845. for _, r := range h {
  846. inAreaIedName = tools.IsEmpty(r["ied_name"])
  847. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  848. lastChar := tmpIednameParts[7]
  849. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  850. //高中低压电压等级相同的
  851. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  852. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "T"))
  853. }
  854. }
  855. h, m, l = c.getIedListByVol("IF", ieds, volMap)
  856. h = append(h, m...)
  857. h = append(h, l...)
  858. for _, r := range h {
  859. inAreaIedName = tools.IsEmpty(r["ied_name"])
  860. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  861. lastChar := tmpIednameParts[7]
  862. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  863. //高中低压电压等级相同的
  864. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  865. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "F"))
  866. }
  867. }
  868. //母线保护PM及母线合并单元MM,可能是多套合并单元MT共用,既不分AB套;低压侧智能终端无关联母线保护
  869. h, m, l = c.getIedListByVol("PM", ieds, volMap)
  870. for _, r := range h {
  871. //高压侧,AB套必须与PT装置相同
  872. inAreaIedName = tools.IsEmpty(r["ied_name"])
  873. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  874. lastChar := tmpIednameParts[7]
  875. if lastChar == iednameParts[7] {
  876. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
  877. //MM装置
  878. mmIedName := c.getMMName(tmpIednameParts, ieds, iednameParts[7])
  879. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, mmIedName, "M", "M"))
  880. break
  881. }
  882. }
  883. for _, r := range m {
  884. //中压侧
  885. inAreaIedName = tools.IsEmpty(r["ied_name"])
  886. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  887. lastChar := tmpIednameParts[7]
  888. if lastChar == "" || lastChar == iednameParts[7] {
  889. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
  890. //MM装置
  891. mmIedName := c.getMMName(tmpIednameParts, ieds, iednameParts[7])
  892. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, mmIedName, "M", "M"))
  893. break
  894. }
  895. }
  896. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  897. if err != nil {
  898. logger.Logger.Error(err)
  899. return
  900. }
  901. }
  902. }
  903. //线路间隔分析
  904. //vol:电压等级
  905. func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm.Params) {
  906. scdParseMgr := new(ScdParse)
  907. //scdNodeMgr := new(ScdNode)
  908. db := orm.NewOrm()
  909. //scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  910. for _, row := range ieds {
  911. if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "L" {
  912. continue
  913. }
  914. pmIedName := ""
  915. mmIedName := ""
  916. pl_iedname := tools.IsEmpty(row["ied_name"])
  917. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  918. //添加间隔数据
  919. dbdata := T_data_check_area{
  920. ModelId: modelid,
  921. ScdId: c.ScdId,
  922. AreaType: "L",
  923. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  924. }
  925. newid, err := db.Insert(&dbdata)
  926. if err != nil {
  927. logger.Logger.Error(err)
  928. return
  929. }
  930. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  931. insvalues := []string{}
  932. for _, ty := range strings.Split(iedtypes, ",") {
  933. inAreaIedName := ""
  934. if ty == "PM" {
  935. //母线保护和母线合并单元装置编号跟随变压器
  936. //查找变压器编号
  937. //1号变压器->2号变压器->3号
  938. inAreaIedName = c.getPMName(iednameParts, ieds)
  939. pmIedName = inAreaIedName
  940. if mmIedName == "" {
  941. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  942. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  943. //使用PM装置的名称去定义MM的名称
  944. ty = "MM"
  945. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  946. mmIedName = inAreaIedName
  947. }
  948. } else if ty == "MM" {
  949. if pmIedName != "" && mmIedName == "" {
  950. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  951. //使用PM装置的名称去定义MM的名称
  952. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  953. mmIedName = inAreaIedName
  954. } else {
  955. continue
  956. }
  957. } else {
  958. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  959. }
  960. if strings.Index("ABCDE", iednameParts[7]) > -1 {
  961. //最后一位是字母则说明是AB套
  962. switch ty {
  963. case "CL":
  964. //测控装置,先判断是否分了AB套,没有标识(ied名称的最后一位是否是字母)则说明是多套共用装置
  965. clIedname := inAreaIedName + iednameParts[7]
  966. iedObj := ieds[inAreaIedName]
  967. if iedObj != nil {
  968. //当前测控装置也分了AB套
  969. inAreaIedName = clIedname
  970. }
  971. break
  972. default:
  973. break
  974. }
  975. }
  976. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  977. }
  978. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  979. if err != nil {
  980. logger.Logger.Error(err)
  981. return
  982. }
  983. //如果mm装置还未确定
  984. if mmIedName == "" {
  985. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  986. inAreaIedName := c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  987. _, err = db.Raw(ins1 + fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "M")).Exec()
  988. if err != nil {
  989. logger.Logger.Error(err)
  990. return
  991. }
  992. }
  993. }
  994. }
  995. //母联间隔分析
  996. func (c *CheckAreaMgr) pJ(modelid int, vol, iedtypes string, ieds map[string]orm.Params, pjIed string) {
  997. scdParseMgr := new(ScdParse)
  998. //scdNodeMgr := new(ScdNode)
  999. db := orm.NewOrm()
  1000. //scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  1001. for _, row := range ieds {
  1002. if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != pjIed[1:2] {
  1003. continue
  1004. }
  1005. pmIedName := ""
  1006. mmIedName := ""
  1007. pl_iedname := tools.IsEmpty(row["ied_name"])
  1008. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  1009. //添加间隔数据
  1010. dbdata := T_data_check_area{
  1011. ModelId: modelid,
  1012. ScdId: c.ScdId,
  1013. AreaType: "J",
  1014. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  1015. }
  1016. newid, err := db.Insert(&dbdata)
  1017. if err != nil {
  1018. logger.Logger.Error(err)
  1019. return
  1020. }
  1021. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  1022. insvalues := []string{}
  1023. for _, ty := range strings.Split(iedtypes, ",") {
  1024. inAreaIedName := ""
  1025. if ty == "PM" {
  1026. //母线保护和母线合并单元装置编号跟随变压器
  1027. //查找变压器编号
  1028. //1号变压器->2号变压器->3号
  1029. inAreaIedName = c.getPMName(iednameParts, ieds)
  1030. pmIedName = inAreaIedName
  1031. if mmIedName == "" {
  1032. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  1033. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  1034. //使用PM装置的名称去定义MM的名称
  1035. ty = "MM"
  1036. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  1037. mmIedName = inAreaIedName
  1038. }
  1039. } else if ty == "MM" {
  1040. if pmIedName != "" && mmIedName == "" {
  1041. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  1042. //使用PM装置的名称去定义MM的名称
  1043. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  1044. mmIedName = inAreaIedName
  1045. } else {
  1046. continue
  1047. }
  1048. } else {
  1049. ty = ty[0:1] + pjIed[1:2]
  1050. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  1051. //判断与基准保护装置相同套号的装置是否存在
  1052. if ieds[inAreaIedName] == nil {
  1053. //尝试去除套号
  1054. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6]
  1055. }
  1056. }
  1057. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  1058. }
  1059. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  1060. if err != nil {
  1061. logger.Logger.Error(err)
  1062. return
  1063. }
  1064. }
  1065. }
  1066. //母联间隔装置关系检查
  1067. func (c *CheckAreaMgr) cJ(scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, pjIed, area_ruleid string) {
  1068. masterIed := new(node_attr.NIED)
  1069. findIedName := ""
  1070. for _, row2 := range area_ieds {
  1071. findIedName = tools.IsEmpty(row2["ied_name"])
  1072. if strings.HasPrefix(findIedName, pjIed) {
  1073. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1074. break
  1075. }
  1076. }
  1077. if masterIed == nil {
  1078. return
  1079. }
  1080. dealFromIed := map[string]int{}
  1081. for _, row := range ied_refs {
  1082. fromiedtype := tools.IsEmpty(row["from_ied_code"])
  1083. toiedtype := tools.IsEmpty(row["to_ied_code"])
  1084. reftype := tools.IsEmpty(row["in_type"])
  1085. tmpFromAreaIeds := []orm.Params{}
  1086. tmpToAreaIeds := []orm.Params{}
  1087. for _, row2 := range area_ieds {
  1088. findIedName = tools.IsEmpty(row2["ied_name"])
  1089. if strings.HasPrefix(findIedName, fromiedtype) {
  1090. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1091. if masterIed != nil {
  1092. tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
  1093. } else {
  1094. if dealFromIed[findIedName] == 0 {
  1095. parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
  1096. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1097. //检查未通过
  1098. scdNodeRule.AppendPaseResult(r)
  1099. }
  1100. dealFromIed[findIedName] = 1
  1101. }
  1102. }
  1103. if strings.HasPrefix(findIedName, toiedtype) {
  1104. tmpToAreaIeds = append(tmpToAreaIeds, row2)
  1105. }
  1106. }
  1107. if len(tmpFromAreaIeds) == 0 {
  1108. continue
  1109. }
  1110. if len(tmpToAreaIeds) == 0 {
  1111. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
  1112. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1113. //检查未通过
  1114. scdNodeRule.AppendPaseResult(r, masterIed)
  1115. continue
  1116. }
  1117. toIedname := ""
  1118. for _, row2 := range tmpFromAreaIeds {
  1119. findIedName = tools.IsEmpty(row2["ied_name"])
  1120. hasToIedRef := false
  1121. hasToIed := false
  1122. for _, row3 := range tmpToAreaIeds {
  1123. toIedname = tools.IsEmpty(row3["ied_name"])
  1124. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", toIedname)
  1125. if masterIed != nil {
  1126. hasToIed = true
  1127. // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
  1128. inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
  1129. logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
  1130. if inout != nil {
  1131. outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
  1132. for _, ieditem := range outiedlist {
  1133. outiedname := ieditem["ref_ied_name"].(string)
  1134. if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
  1135. hasToIedRef = true
  1136. break
  1137. }
  1138. }
  1139. }
  1140. if !hasToIedRef {
  1141. parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
  1142. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1143. //检查未通过
  1144. scdNodeRule.AppendPaseResult(r, masterIed)
  1145. }
  1146. }
  1147. }
  1148. if !hasToIed {
  1149. parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
  1150. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1151. //检查未通过
  1152. scdNodeRule.AppendPaseResult(r, masterIed)
  1153. }
  1154. }
  1155. }
  1156. }
  1157. //线路间隔装置关系检查
  1158. func (c *CheckAreaMgr) cL(scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, area_ruleid string) {
  1159. masterIed := new(node_attr.NIED)
  1160. findIedName := ""
  1161. for _, row2 := range area_ieds {
  1162. findIedName = tools.IsEmpty(row2["ied_name"])
  1163. if strings.HasPrefix(findIedName, "PL") {
  1164. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1165. break
  1166. }
  1167. }
  1168. if masterIed == nil {
  1169. return
  1170. }
  1171. dealFromIed := map[string]int{}
  1172. for _, row := range ied_refs {
  1173. fromiedtype := tools.IsEmpty(row["from_ied_code"])
  1174. toiedtype := tools.IsEmpty(row["to_ied_code"])
  1175. reftype := tools.IsEmpty(row["in_type"])
  1176. tmpFromAreaIeds := []orm.Params{}
  1177. tmpToAreaIeds := []orm.Params{}
  1178. for _, row2 := range area_ieds {
  1179. findIedName = tools.IsEmpty(row2["ied_name"])
  1180. if strings.HasPrefix(findIedName, fromiedtype) {
  1181. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1182. if masterIed != nil {
  1183. tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
  1184. } else {
  1185. if dealFromIed[findIedName] == 0 {
  1186. parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
  1187. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1188. //检查未通过
  1189. scdNodeRule.AppendPaseResult(r)
  1190. }
  1191. dealFromIed[findIedName] = 1
  1192. }
  1193. }
  1194. if strings.HasPrefix(findIedName, toiedtype) {
  1195. tmpToAreaIeds = append(tmpToAreaIeds, row2)
  1196. }
  1197. }
  1198. if len(tmpFromAreaIeds) == 0 {
  1199. continue
  1200. }
  1201. if len(tmpToAreaIeds) == 0 {
  1202. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
  1203. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1204. //检查未通过
  1205. scdNodeRule.AppendPaseResult(r, masterIed)
  1206. continue
  1207. }
  1208. toIedname := ""
  1209. for _, row2 := range tmpFromAreaIeds {
  1210. findIedName = tools.IsEmpty(row2["ied_name"])
  1211. hasToIedRef := false
  1212. hasToIed := false
  1213. for _, row3 := range tmpToAreaIeds {
  1214. toIedname = tools.IsEmpty(row3["ied_name"])
  1215. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", toIedname)
  1216. if masterIed != nil {
  1217. hasToIed = true
  1218. // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
  1219. inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
  1220. logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
  1221. if inout != nil {
  1222. outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
  1223. for _, ieditem := range outiedlist {
  1224. outiedname := ieditem["ref_ied_name"].(string)
  1225. if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
  1226. hasToIedRef = true
  1227. break
  1228. }
  1229. }
  1230. }
  1231. if !hasToIedRef {
  1232. parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
  1233. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1234. //检查未通过
  1235. scdNodeRule.AppendPaseResult(r, masterIed)
  1236. }
  1237. }
  1238. }
  1239. if !hasToIed {
  1240. parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
  1241. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1242. //检查未通过
  1243. scdNodeRule.AppendPaseResult(r, masterIed)
  1244. }
  1245. }
  1246. }
  1247. }
  1248. //变压器间隔装置关系检查
  1249. func (c *CheckAreaMgr) cT(scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, area_ruleid string, HasAreaJ bool) {
  1250. masterIed := new(node_attr.NIED)
  1251. findIedName := ""
  1252. for _, row2 := range area_ieds {
  1253. findIedName = tools.IsEmpty(row2["ied_name"])
  1254. if strings.HasPrefix(findIedName, "PT") {
  1255. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1256. break
  1257. }
  1258. }
  1259. if masterIed == nil {
  1260. return
  1261. }
  1262. scdParseMgr := new(ScdParse)
  1263. dealFromIed := map[string]int{}
  1264. for _, row := range ied_refs {
  1265. fromiedtype := tools.IsEmpty(row["from_ied_code"])
  1266. fromiedtype = strings.Split(fromiedtype, "#")[0] //去除后面的电压级别标识
  1267. toiedtype := strings.Split(tools.IsEmpty(row["to_ied_code"]), "#")[0] //去除后面的电压级别标识
  1268. reftype := tools.IsEmpty(row["in_type"])
  1269. tmpFromAreaIeds := []orm.Params{}
  1270. tmpToAreaIeds := []orm.Params{}
  1271. for _, row2 := range area_ieds {
  1272. findIedName = tools.IsEmpty(row2["ied_name"])
  1273. if strings.HasPrefix(findIedName, fromiedtype) {
  1274. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1275. if masterIed != nil {
  1276. tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
  1277. } else {
  1278. if dealFromIed[findIedName] == 0 {
  1279. parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
  1280. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1281. //检查未通过
  1282. scdNodeRule.AppendPaseResult(r)
  1283. }
  1284. dealFromIed[findIedName] = 1
  1285. }
  1286. }
  1287. if strings.HasPrefix(findIedName, toiedtype) {
  1288. tmpToAreaIeds = append(tmpToAreaIeds, row2)
  1289. }
  1290. }
  1291. if len(tmpFromAreaIeds) == 0 {
  1292. continue
  1293. }
  1294. if len(tmpToAreaIeds) == 0 {
  1295. logger.Logger.Debug(fmt.Sprintf("缺失类型关联装置 :%+v", row))
  1296. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
  1297. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1298. //检查未通过
  1299. scdNodeRule.AppendPaseResult(r, masterIed)
  1300. continue
  1301. }
  1302. toIedname := ""
  1303. for _, row2 := range tmpFromAreaIeds {
  1304. findIedName = tools.IsEmpty(row2["ied_name"])
  1305. hasToIedRef := false
  1306. hasToIed := false
  1307. t1 := fromiedtype + "->" + toiedtype
  1308. volLevel := "" //电压等级
  1309. if t1 == "CT->IT" || t1 == "IT->CT" || t1 == "CT->IB" || t1 == "IB->CT" || t1 == "MM->MT" || t1 == "PM->IB" || t1 == "IB->PM" || t1 == "PM->IT" || t1 == "IT->PM" {
  1310. ps := scdParseMgr.ParseIedName(findIedName)
  1311. volLevel = ps[3] + ps[4]
  1312. }
  1313. hasSameVolIed := false
  1314. for _, row3 := range tmpToAreaIeds {
  1315. toIedname = tools.IsEmpty(row3["ied_name"])
  1316. if volLevel != "" {
  1317. ps := scdParseMgr.ParseIedName(toIedname)
  1318. if volLevel != ps[3]+ps[4] {
  1319. //排除不是同一电压等级的装置
  1320. continue
  1321. }
  1322. hasSameVolIed = true
  1323. }
  1324. if scdNodeMgr.GetIed(scdXmlObj, "", toIedname) != nil {
  1325. hasToIed = true
  1326. // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
  1327. inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
  1328. logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
  1329. if inout != nil {
  1330. outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
  1331. for _, ieditem := range outiedlist {
  1332. outiedname := ieditem["ref_ied_name"].(string)
  1333. if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
  1334. hasToIedRef = true
  1335. break
  1336. }
  1337. }
  1338. }
  1339. if !hasToIedRef {
  1340. parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
  1341. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1342. //检查未通过
  1343. scdNodeRule.AppendPaseResult(r, masterIed)
  1344. }
  1345. }
  1346. if hasSameVolIed {
  1347. break
  1348. }
  1349. }
  1350. if toiedtype != "PT" {
  1351. if volLevel != "" && !hasSameVolIed {
  1352. parse_result := fmt.Sprintf("间隔%s的装置%s缺失同电压等级的关联类型%s装置", area_name, findIedName, toiedtype)
  1353. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1354. //检查未通过
  1355. scdNodeRule.AppendPaseResult(r, masterIed)
  1356. } else if !hasToIed {
  1357. parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
  1358. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1359. //检查未通过
  1360. scdNodeRule.AppendPaseResult(r, masterIed)
  1361. }
  1362. }
  1363. }
  1364. }
  1365. }
  1366. //根据参考ied name找出应该关联PM装置
  1367. func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Params) string {
  1368. tmpIedName := "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + "1" + iednameParts[7]
  1369. iedObj := ieds[tmpIedName]
  1370. if iedObj != nil {
  1371. } else {
  1372. tmpIedName = "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + "2" + iednameParts[7]
  1373. iedObj = ieds[tmpIedName]
  1374. if iedObj != nil {
  1375. return tmpIedName
  1376. }
  1377. }
  1378. return tmpIedName
  1379. }
  1380. //根据参考ied name找出应该关联MM装置
  1381. func (c *CheckAreaMgr) getMMName(iednameParts []string, ieds map[string]orm.Params, ab string) string {
  1382. tmpIedName := "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + ab
  1383. if ieds[tmpIedName] == nil {
  1384. tmpIedName = "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  1385. }
  1386. return tmpIedName
  1387. }
  1388. //根据当前设备列表,分析出电压等级(高、中、低)的设备列表
  1389. // CT测控、IT智能终端、MT合并单元需要判断是否是本体装置,是则将其归为主变高压侧
  1390. func (c *CheckAreaMgr) getIedListByVol(iedtype string, ieds map[string]orm.Params, vollevel map[string]string) (hightLst, middleLst, lowLst []orm.Params) {
  1391. tmpLst := map[string][]orm.Params{}
  1392. for _, v := range vollevel {
  1393. tmpLst[v] = []orm.Params{}
  1394. }
  1395. scdParseMgr := new(ScdParse)
  1396. for _, row := range ieds {
  1397. pl_iedname := tools.IsEmpty(row["ied_name"])
  1398. if pl_iedname[0:len(iedtype)] != iedtype {
  1399. continue
  1400. }
  1401. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  1402. volvalue := iednameParts[3] + iednameParts[4]
  1403. if tmpLst[volvalue] == nil {
  1404. tmpLst[volvalue] = []orm.Params{row}
  1405. } else {
  1406. tmpLst[volvalue] = append(tmpLst[volvalue], row)
  1407. }
  1408. }
  1409. return tmpLst[vollevel["hight"]], tmpLst[vollevel["middle"]], tmpLst[vollevel["low"]]
  1410. }
  1411. //测试
  1412. func (c *CheckAreaMgr) TestAppendNode(iedname string) {
  1413. //t := t_scd_node_scl{NodeName: iedname}
  1414. //c.AppendIedNode(&t)
  1415. }