checktools_area.go 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  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. //装置关联关系分析
  386. //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
  387. HasAreaJ := false
  388. for _, row := range arealist {
  389. area_name := tools.IsEmpty(row["area_name"])
  390. areaCode := tools.IsEmpty(row["area_type"]) //间隔模型类型
  391. area_id := tools.IsEmpty(row["id"])
  392. if areaCode == "J" {
  393. HasAreaJ = true
  394. modelid := tools.IsEmpty(row["model_id"])
  395. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PE", area_ruleid)
  396. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PJ", area_ruleid)
  397. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PK", area_ruleid)
  398. c.cJ(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PF", area_ruleid)
  399. }
  400. }
  401. for _, row := range arealist {
  402. area_name := tools.IsEmpty(row["area_name"])
  403. areaCode := tools.IsEmpty(row["area_type"]) //间隔模型类型
  404. area_id := tools.IsEmpty(row["id"])
  405. modelid := tools.IsEmpty(row["model_id"])
  406. if areaCode == "J" {
  407. continue
  408. }
  409. if areaCode == "L" {
  410. //线路间隔
  411. c.cL(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], area_ruleid)
  412. }
  413. if areaCode == "T" {
  414. //变压器齐间隔
  415. c.cT(scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], area_ruleid, HasAreaJ)
  416. }
  417. }
  418. scdNodeRule.CheckFinish()
  419. scdNodeRule.Flush()
  420. return nil
  421. }
  422. //检测装置功能分析
  423. func (c *CheckAreaMgr) CheckIedFunc() error {
  424. return nil
  425. }
  426. //检测装置端子分析
  427. func (c *CheckAreaMgr) CheckIedFcda() error {
  428. scdXmlObj, arealist, area_ruleid, err := c.getAreaCheckInfo()
  429. if err != nil {
  430. logger.Logger.Error(err)
  431. return err
  432. }
  433. if area_ruleid == "" {
  434. return errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
  435. }
  436. if scdXmlObj == nil {
  437. return errors.New("无效的SCD")
  438. }
  439. db := orm.NewOrm()
  440. //获取当前站的各电压等级
  441. volRows := []orm.Params{}
  442. _, 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)
  443. if err != nil {
  444. logger.Logger.Error(err)
  445. return err
  446. }
  447. if len(volRows) == 0 {
  448. logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
  449. return errors.New("该scd未发现任何电压等级的装置")
  450. }
  451. volMap := map[string]string{}
  452. volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
  453. if len(volRows) == 2 {
  454. volMap["middle"] = ""
  455. volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
  456. } else {
  457. volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
  458. volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
  459. }
  460. scdNodeRule := new(ScdNodeRule)
  461. scdNodeMgr := new(ScdNode)
  462. iedRelationMgr := new(SysCheckModelIedRelationMgr)
  463. for _, row := range arealist {
  464. //获取间隔标准装置及关系
  465. modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
  466. area_name := tools.IsEmpty(row["area_name"])
  467. //area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
  468. area_id := tools.IsEmpty(row["id"])
  469. s, err := iedRelationMgr.GetListByModelid(modelid)
  470. if err != nil {
  471. logger.Logger.Error(err)
  472. return err
  473. }
  474. if len(s) == 0 {
  475. return errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid))
  476. }
  477. //获取该间隔下该类型的装置
  478. s1 := []orm.Params{}
  479. _, err = db.Raw("select ied_name from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
  480. //循环处理关联关系
  481. dealIedType := map[string]int{} //已处理过的装置类型
  482. for _, row2 := range s {
  483. ied_type := tools.IsEmpty(row2["ied_type"])
  484. if dealIedType[ied_type] > 0 {
  485. continue
  486. }
  487. //获取装置类型配置的端子列表
  488. fcdaMgr := new(SysCheckModelIedFuncFcdaMgr)
  489. funcMgr := new(SysCheckModelIedFuncMgr)
  490. funcMgr.Model = T_data_model_func_def{ModelId: modelid}
  491. funclist, _ := funcMgr.GetList(modelid, ied_type)
  492. if funclist == nil || len(funclist) == 0 {
  493. continue
  494. }
  495. tmp := strings.Split(ied_type, "#")
  496. ied_type = tmp[0]
  497. vol := ""
  498. if len(tmp) == 2 {
  499. vol = tmp[1] //电压级别
  500. }
  501. iedlst := []orm.Params{}
  502. if vol == "" {
  503. for _, r := range s1 {
  504. if strings.HasPrefix(tools.IsEmpty(r["ied_name"]), ied_type) {
  505. iedlst = append(iedlst, r)
  506. }
  507. }
  508. } else {
  509. tmpLst := map[string]orm.Params{}
  510. for _, r := range s1 {
  511. iedname := tools.IsEmpty(r["ied_name"])
  512. if strings.HasPrefix(iedname, ied_type) {
  513. tmpLst[iedname] = r
  514. }
  515. }
  516. h, m, l := c.getIedListByVol(ied_type, tmpLst, volMap)
  517. if vol == "H" {
  518. iedlst = h
  519. }
  520. if vol == "M" {
  521. iedlst = m
  522. }
  523. if vol == "L" {
  524. iedlst = l
  525. }
  526. }
  527. for _, ied := range iedlst {
  528. iedname := tools.IsEmpty(ied["ied_name"])
  529. iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
  530. if iedObj == nil {
  531. continue
  532. }
  533. fcdaObjList := []*node_attr.NFCDA{}
  534. for _, t1 := range iedObj.AccessPoint {
  535. if t1.Server == nil || len(t1.Server.LDevice) == 0 {
  536. continue
  537. }
  538. for _, ld := range t1.Server.LDevice {
  539. if ld.LN0 != nil {
  540. for _, t2 := range ld.LN0.DataSet {
  541. for _, t3 := range t2.FCDA {
  542. fcdaObjList = append(fcdaObjList, t3)
  543. }
  544. }
  545. }
  546. }
  547. }
  548. for _, row3 := range funclist {
  549. funcExist := false //设计的功能是否存在
  550. funcid, _ := strconv.Atoi(tools.IsEmpty(row3["id"]))
  551. fcdaMgr.Model = T_data_model_func_fcda{ModelId: modelid, FuncId: funcid}
  552. fcdalist, _ := fcdaMgr.GetList()
  553. if fcdalist != nil && len(fcdalist) > 0 {
  554. //判断端子是否存在
  555. for _, row4 := range fcdalist {
  556. fcda_name_match := tools.IsEmpty(row4["fcda_match_exp"])
  557. fcda_name := tools.IsEmpty(row4["fcda_name"])
  558. if fcda_name_match == "" {
  559. fcda_name_match = fcda_name
  560. }
  561. fcdaExist := false
  562. //获取端子FCDA描述
  563. if len(fcdaObjList) > 0 {
  564. for _, t4 := range fcdaObjList {
  565. re, _ := scdNodeRule.IedFcdaExist(iedname, t4.LdInst, t4.LnClass, t4.LnInst, t4.Prefix, t4.DoName, t4.DaName)
  566. if re == nil {
  567. continue
  568. }
  569. doi := re.(*node_attr.NDOI)
  570. desc := doi.Desc
  571. if fcda_name_match == desc {
  572. //完全匹配
  573. fcdaExist = true
  574. break
  575. }
  576. //正则匹配
  577. //fcda_name_match = strings.ReplaceAll(fcda_name_match)
  578. rexp := regexp.MustCompile(fcda_name_match)
  579. if rexp.FindString(desc) != "" {
  580. fcdaExist = true
  581. break
  582. }
  583. }
  584. }
  585. if fcdaExist {
  586. funcExist = true
  587. } else {
  588. parse_result := fmt.Sprintf("间隔%s的装置%s缺失虚端子%s", area_name, iedname, fcda_name)
  589. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  590. //检查未通过
  591. scdNodeRule.AppendFcdaCheckResult(r)
  592. }
  593. }
  594. }
  595. if !funcExist {
  596. parse_result := fmt.Sprintf("间隔%s的装置%s缺失功能%s", area_name, iedname, tools.IsEmpty(row3["func_name"]))
  597. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  598. //检查未通过
  599. scdNodeRule.AppendFcdaCheckResult(r)
  600. }
  601. }
  602. }
  603. dealIedType[ied_type] = 1
  604. }
  605. }
  606. scdNodeRule.CheckFinish()
  607. scdNodeRule.Flush()
  608. return nil
  609. }
  610. //解析模型间隔
  611. func (c *CheckAreaMgr) ParseModelArea() {
  612. c.Init(c.ScdId)
  613. key := fmt.Sprintf("%d-checkinfo", c.ScdId)
  614. areaCheckInfo.Delete(key)
  615. // 取得当前scd所有ied及名称解析结果
  616. dbo := orm.NewOrm()
  617. 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"
  618. iedlst := []orm.Params{}
  619. _, err := dbo.Raw(sql, c.ScdId).Values(&iedlst)
  620. if err != nil {
  621. logger.Logger.Error(err)
  622. return
  623. }
  624. logger.Logger.Debug(fmt.Sprintf("=====总装置数:%d", len(iedlst)))
  625. iedMap := map[string]orm.Params{}
  626. for _, r := range iedlst {
  627. iedMap[tools.IsEmpty(r["ied_name"])] = r
  628. }
  629. //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
  630. HasAreaJ := false
  631. for _, row := range c.CheckModelList {
  632. areaCode := tools.IsEmpty(row["area_type_code"])
  633. if areaCode == "J" {
  634. HasAreaJ = true
  635. modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
  636. //modelname := tools.IsEmpty(row["model_name"])
  637. iedtypes := tools.IsEmpty(row["ied_types"])
  638. volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
  639. c.pJ(modelid, volcode, iedtypes, iedMap, "PE")
  640. c.pJ(modelid, volcode, iedtypes, iedMap, "PJ")
  641. c.pJ(modelid, volcode, iedtypes, iedMap, "PK")
  642. c.pJ(modelid, volcode, iedtypes, iedMap, "PF")
  643. }
  644. }
  645. for _, row := range c.CheckModelList {
  646. //逐一分析模型定义
  647. modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
  648. modelname := tools.IsEmpty(row["model_name"])
  649. iedtypes := tools.IsEmpty(row["ied_types"])
  650. //模型对应的间隔代码
  651. /*
  652. S 站用变压器
  653. C 电容器
  654. B 断路器
  655. K 母分
  656. J 母联
  657. M 母线
  658. X 电抗器
  659. L 线路
  660. T 主变压器
  661. */
  662. areaCode := tools.IsEmpty(row["area_type_code"])
  663. //模型对应的电压等级
  664. //10:10KV 35:35KV 66:66KV 11:110KV 22:220KV 50:500KV 75:750KV 33:330KV T0:1000KV
  665. volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
  666. if modelname == "" || iedtypes == "" {
  667. continue
  668. }
  669. //母联间隔已经提前分析,如果没有母联间隔时,主变间隔中不包含母联终端装置
  670. if areaCode == "J" {
  671. continue
  672. }
  673. //获取模型内中装备关系定义
  674. //主变间隔分析:需要查站内该电压等级下的高中低压侧装置或者高低压装置组成一个间隔,以主变保护装置(PT)为起始
  675. if areaCode == "T" {
  676. c.pT(modelid, iedtypes, iedMap, HasAreaJ)
  677. }
  678. //线路保护间隔分析:以线路保护测控装置(PL)为开始分析
  679. if areaCode == "L" {
  680. c.pL(modelid, volcode, iedtypes, iedMap)
  681. }
  682. }
  683. }
  684. //变压器间隔分析
  685. func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Params, HasAreaJ bool) {
  686. scdParseMgr := new(ScdParse)
  687. db := orm.NewOrm()
  688. //获取当前站的各电压等级
  689. volRows := []orm.Params{}
  690. _, 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)
  691. if err != nil {
  692. logger.Logger.Error(err)
  693. return
  694. }
  695. if len(volRows) == 0 {
  696. logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
  697. return
  698. }
  699. volMap := map[string]string{}
  700. volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
  701. if len(volRows) == 2 {
  702. volMap["middle"] = ""
  703. volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
  704. } else {
  705. volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
  706. volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
  707. }
  708. //判断是否将各电压等级的保护装置合并还是分开的间隔
  709. //如果存在高中低压的保护装置,则说明是分开的主变间隔
  710. //isMarge := true // 默认为合并的主变间隔
  711. for _, row := range ieds {
  712. if tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "T" {
  713. continue
  714. }
  715. //pmIedName := ""
  716. //mmIedName := ""
  717. pl_iedname := tools.IsEmpty(row["ied_name"])
  718. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  719. //添加间隔数据
  720. dbdata := T_data_check_area{
  721. ModelId: modelid,
  722. ScdId: c.ScdId,
  723. AreaType: "T",
  724. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  725. }
  726. newid, err := db.Insert(&dbdata)
  727. if err != nil {
  728. logger.Logger.Error(err)
  729. return
  730. }
  731. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  732. insvalues := []string{}
  733. inAreaIedName := pl_iedname
  734. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "T"))
  735. //合智一体IMT/MIT,分高中低压
  736. h, m, l := c.getIedListByVol("IMT", ieds, volMap)
  737. h = append(h, m...)
  738. h = append(h, l...)
  739. for _, r := range h {
  740. inAreaIedName = tools.IsEmpty(r["ied_name"])
  741. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  742. lastChar := tmpIednameParts[7]
  743. if lastChar == iednameParts[7] {
  744. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "IM", "T"))
  745. }
  746. }
  747. h, m, l = c.getIedListByVol("MIT", ieds, volMap)
  748. h = append(h, m...)
  749. h = append(h, l...)
  750. for _, r := range h {
  751. inAreaIedName = tools.IsEmpty(r["ied_name"])
  752. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  753. lastChar := tmpIednameParts[7]
  754. if lastChar == iednameParts[7] {
  755. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "MI", "T"))
  756. }
  757. }
  758. //母联智能终端IE需要分高中压,无低压侧
  759. if HasAreaJ {
  760. h, m, l = c.getIedListByVol("IE", ieds, volMap)
  761. for _, r := range h {
  762. //高压侧,AB套必须与PT装置相同
  763. inAreaIedName = tools.IsEmpty(r["ied_name"])
  764. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  765. lastChar := tmpIednameParts[7]
  766. if lastChar == iednameParts[7] {
  767. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "E"))
  768. }
  769. }
  770. for _, r := range m {
  771. //中压侧
  772. inAreaIedName = tools.IsEmpty(r["ied_name"])
  773. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  774. lastChar := tmpIednameParts[7]
  775. if lastChar == "" || lastChar == iednameParts[7] {
  776. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "E"))
  777. }
  778. }
  779. }
  780. //合并单元MT分高中低压侧;低压侧无关联母线合并单元MM
  781. h, m, l = c.getIedListByVol("MT", ieds, volMap)
  782. h = append(h, m...)
  783. h = append(h, l...)
  784. for _, r := range h {
  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, "M", "T"))
  790. }
  791. }
  792. //测控装置CT分高中低压侧,且可能是多套合并单元MT共用,既不分AB套
  793. h, m, l = c.getIedListByVol("CT", ieds, volMap)
  794. h = append(h, m...)
  795. h = append(h, l...)
  796. for _, r := range h {
  797. inAreaIedName = tools.IsEmpty(r["ied_name"])
  798. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  799. lastChar := tmpIednameParts[7]
  800. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  801. //高中低压电压等级相同的
  802. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  803. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "C", "T"))
  804. }
  805. }
  806. //智能终端(IB:开关\IT:分支\IF:分段)分高中低压侧
  807. h, m, l = c.getIedListByVol("IB", ieds, volMap)
  808. h = append(h, m...)
  809. h = append(h, l...)
  810. for _, r := range h {
  811. inAreaIedName = tools.IsEmpty(r["ied_name"])
  812. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  813. lastChar := tmpIednameParts[7]
  814. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  815. //高中低压电压等级相同的
  816. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  817. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "B"))
  818. }
  819. }
  820. h, m, l = c.getIedListByVol("IT", ieds, volMap)
  821. h = append(h, m...)
  822. h = append(h, l...)
  823. for _, r := range h {
  824. inAreaIedName = tools.IsEmpty(r["ied_name"])
  825. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  826. lastChar := tmpIednameParts[7]
  827. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  828. //高中低压电压等级相同的
  829. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  830. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "T"))
  831. }
  832. }
  833. h, m, l = c.getIedListByVol("IF", ieds, volMap)
  834. h = append(h, m...)
  835. h = append(h, l...)
  836. for _, r := range h {
  837. inAreaIedName = tools.IsEmpty(r["ied_name"])
  838. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  839. lastChar := tmpIednameParts[7]
  840. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  841. //高中低压电压等级相同的
  842. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  843. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "F"))
  844. }
  845. }
  846. //母线保护PM及母线合并单元MM,可能是多套合并单元MT共用,既不分AB套;低压侧智能终端无关联母线保护
  847. h, m, l = c.getIedListByVol("PM", ieds, volMap)
  848. for _, r := range h {
  849. //高压侧,AB套必须与PT装置相同
  850. inAreaIedName = tools.IsEmpty(r["ied_name"])
  851. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  852. lastChar := tmpIednameParts[7]
  853. if lastChar == iednameParts[7] {
  854. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
  855. //MM装置
  856. mmIedName := c.getMMName(tmpIednameParts, ieds, iednameParts[7])
  857. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, mmIedName, "M", "M"))
  858. break
  859. }
  860. }
  861. for _, r := range m {
  862. //中压侧
  863. inAreaIedName = tools.IsEmpty(r["ied_name"])
  864. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  865. lastChar := tmpIednameParts[7]
  866. if lastChar == "" || lastChar == iednameParts[7] {
  867. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
  868. //MM装置
  869. mmIedName := c.getMMName(tmpIednameParts, ieds, iednameParts[7])
  870. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, mmIedName, "M", "M"))
  871. break
  872. }
  873. }
  874. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  875. if err != nil {
  876. logger.Logger.Error(err)
  877. return
  878. }
  879. }
  880. }
  881. //线路间隔分析
  882. //vol:电压等级
  883. func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm.Params) {
  884. scdParseMgr := new(ScdParse)
  885. //scdNodeMgr := new(ScdNode)
  886. db := orm.NewOrm()
  887. //scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  888. for _, row := range ieds {
  889. if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "L" {
  890. continue
  891. }
  892. pmIedName := ""
  893. mmIedName := ""
  894. pl_iedname := tools.IsEmpty(row["ied_name"])
  895. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  896. //添加间隔数据
  897. dbdata := T_data_check_area{
  898. ModelId: modelid,
  899. ScdId: c.ScdId,
  900. AreaType: "L",
  901. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  902. }
  903. newid, err := db.Insert(&dbdata)
  904. if err != nil {
  905. logger.Logger.Error(err)
  906. return
  907. }
  908. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  909. insvalues := []string{}
  910. for _, ty := range strings.Split(iedtypes, ",") {
  911. inAreaIedName := ""
  912. if ty == "PM" {
  913. //母线保护和母线合并单元装置编号跟随变压器
  914. //查找变压器编号
  915. //1号变压器->2号变压器->3号
  916. inAreaIedName = c.getPMName(iednameParts, ieds)
  917. pmIedName = inAreaIedName
  918. if mmIedName == "" {
  919. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  920. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  921. //使用PM装置的名称去定义MM的名称
  922. ty = "MM"
  923. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  924. mmIedName = inAreaIedName
  925. }
  926. } else if ty == "MM" {
  927. if pmIedName != "" && mmIedName == "" {
  928. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  929. //使用PM装置的名称去定义MM的名称
  930. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  931. mmIedName = inAreaIedName
  932. } else {
  933. continue
  934. }
  935. } else {
  936. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  937. }
  938. if strings.Index("ABCDE", iednameParts[7]) > -1 {
  939. //最后一位是字母则说明是AB套
  940. switch ty {
  941. case "CL":
  942. //测控装置,先判断是否分了AB套,没有标识(ied名称的最后一位是否是字母)则说明是多套共用装置
  943. clIedname := inAreaIedName + iednameParts[7]
  944. iedObj := ieds[inAreaIedName]
  945. if iedObj != nil {
  946. //当前测控装置也分了AB套
  947. inAreaIedName = clIedname
  948. }
  949. break
  950. default:
  951. break
  952. }
  953. }
  954. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  955. }
  956. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  957. if err != nil {
  958. logger.Logger.Error(err)
  959. return
  960. }
  961. //如果mm装置还未确定
  962. if mmIedName == "" {
  963. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  964. inAreaIedName := c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  965. _, err = db.Raw(ins1 + fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "M")).Exec()
  966. if err != nil {
  967. logger.Logger.Error(err)
  968. return
  969. }
  970. }
  971. }
  972. }
  973. //母联间隔分析
  974. func (c *CheckAreaMgr) pJ(modelid int, vol, iedtypes string, ieds map[string]orm.Params, pjIed string) {
  975. scdParseMgr := new(ScdParse)
  976. //scdNodeMgr := new(ScdNode)
  977. db := orm.NewOrm()
  978. //scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  979. for _, row := range ieds {
  980. if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != pjIed[1:2] {
  981. continue
  982. }
  983. pmIedName := ""
  984. mmIedName := ""
  985. pl_iedname := tools.IsEmpty(row["ied_name"])
  986. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  987. //添加间隔数据
  988. dbdata := T_data_check_area{
  989. ModelId: modelid,
  990. ScdId: c.ScdId,
  991. AreaType: "J",
  992. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  993. }
  994. newid, err := db.Insert(&dbdata)
  995. if err != nil {
  996. logger.Logger.Error(err)
  997. return
  998. }
  999. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  1000. insvalues := []string{}
  1001. for _, ty := range strings.Split(iedtypes, ",") {
  1002. inAreaIedName := ""
  1003. if ty == "PM" {
  1004. //母线保护和母线合并单元装置编号跟随变压器
  1005. //查找变压器编号
  1006. //1号变压器->2号变压器->3号
  1007. inAreaIedName = c.getPMName(iednameParts, ieds)
  1008. pmIedName = inAreaIedName
  1009. if mmIedName == "" {
  1010. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  1011. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  1012. //使用PM装置的名称去定义MM的名称
  1013. ty = "MM"
  1014. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  1015. mmIedName = inAreaIedName
  1016. }
  1017. } else if ty == "MM" {
  1018. if pmIedName != "" && mmIedName == "" {
  1019. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  1020. //使用PM装置的名称去定义MM的名称
  1021. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  1022. mmIedName = inAreaIedName
  1023. } else {
  1024. continue
  1025. }
  1026. } else {
  1027. ty = ty[0:1] + pjIed[1:2]
  1028. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  1029. //判断与基准保护装置相同套号的装置是否存在
  1030. if ieds[inAreaIedName] == nil {
  1031. //尝试去除套号
  1032. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6]
  1033. }
  1034. }
  1035. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  1036. }
  1037. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  1038. if err != nil {
  1039. logger.Logger.Error(err)
  1040. return
  1041. }
  1042. }
  1043. }
  1044. //母联间隔装置关系检查
  1045. 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) {
  1046. masterIed := new(node_attr.NIED)
  1047. findIedName := ""
  1048. for _, row2 := range area_ieds {
  1049. findIedName = tools.IsEmpty(row2["ied_name"])
  1050. if strings.HasPrefix(findIedName, pjIed) {
  1051. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1052. break
  1053. }
  1054. }
  1055. if masterIed == nil {
  1056. return
  1057. }
  1058. dealFromIed := map[string]int{}
  1059. for _, row := range ied_refs {
  1060. fromiedtype := tools.IsEmpty(row["from_ied_code"])
  1061. toiedtype := tools.IsEmpty(row["to_ied_code"])
  1062. reftype := tools.IsEmpty(row["in_type"])
  1063. tmpFromAreaIeds := []orm.Params{}
  1064. tmpToAreaIeds := []orm.Params{}
  1065. for _, row2 := range area_ieds {
  1066. findIedName = tools.IsEmpty(row2["ied_name"])
  1067. if strings.HasPrefix(findIedName, fromiedtype) {
  1068. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1069. if masterIed != nil {
  1070. tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
  1071. } else {
  1072. if dealFromIed[findIedName] == 0 {
  1073. parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
  1074. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1075. //检查未通过
  1076. scdNodeRule.AppendFcdaCheckResult(r)
  1077. }
  1078. dealFromIed[findIedName] = 1
  1079. }
  1080. }
  1081. if strings.HasPrefix(findIedName, toiedtype) {
  1082. tmpToAreaIeds = append(tmpToAreaIeds, row2)
  1083. }
  1084. }
  1085. if len(tmpFromAreaIeds) == 0 {
  1086. continue
  1087. }
  1088. if len(tmpToAreaIeds) == 0 {
  1089. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
  1090. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1091. //检查未通过
  1092. scdNodeRule.AppendFcdaCheckResult(r)
  1093. continue
  1094. }
  1095. toIedname := ""
  1096. for _, row2 := range tmpFromAreaIeds {
  1097. findIedName = tools.IsEmpty(row2["ied_name"])
  1098. hasToIedRef := false
  1099. hasToIed := false
  1100. for _, row3 := range tmpToAreaIeds {
  1101. toIedname = tools.IsEmpty(row3["ied_name"])
  1102. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", toIedname)
  1103. if masterIed != nil {
  1104. hasToIed = true
  1105. // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
  1106. inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
  1107. logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
  1108. if inout != nil {
  1109. outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
  1110. for _, ieditem := range outiedlist {
  1111. outiedname := ieditem["ref_ied_name"].(string)
  1112. if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
  1113. hasToIedRef = true
  1114. break
  1115. }
  1116. }
  1117. }
  1118. if !hasToIedRef {
  1119. parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
  1120. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1121. //检查未通过
  1122. scdNodeRule.AppendFcdaCheckResult(r)
  1123. }
  1124. }
  1125. }
  1126. if !hasToIed {
  1127. parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
  1128. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1129. //检查未通过
  1130. scdNodeRule.AppendFcdaCheckResult(r)
  1131. }
  1132. }
  1133. }
  1134. }
  1135. //线路间隔装置关系检查
  1136. 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) {
  1137. masterIed := new(node_attr.NIED)
  1138. findIedName := ""
  1139. for _, row2 := range area_ieds {
  1140. findIedName = tools.IsEmpty(row2["ied_name"])
  1141. if strings.HasPrefix(findIedName, "PL") {
  1142. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1143. break
  1144. }
  1145. }
  1146. if masterIed == nil {
  1147. return
  1148. }
  1149. dealFromIed := map[string]int{}
  1150. for _, row := range ied_refs {
  1151. fromiedtype := tools.IsEmpty(row["from_ied_code"])
  1152. toiedtype := tools.IsEmpty(row["to_ied_code"])
  1153. reftype := tools.IsEmpty(row["in_type"])
  1154. tmpFromAreaIeds := []orm.Params{}
  1155. tmpToAreaIeds := []orm.Params{}
  1156. for _, row2 := range area_ieds {
  1157. findIedName = tools.IsEmpty(row2["ied_name"])
  1158. if strings.HasPrefix(findIedName, fromiedtype) {
  1159. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1160. if masterIed != nil {
  1161. tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
  1162. } else {
  1163. if dealFromIed[findIedName] == 0 {
  1164. parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
  1165. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1166. //检查未通过
  1167. scdNodeRule.AppendFcdaCheckResult(r)
  1168. }
  1169. dealFromIed[findIedName] = 1
  1170. }
  1171. }
  1172. if strings.HasPrefix(findIedName, toiedtype) {
  1173. tmpToAreaIeds = append(tmpToAreaIeds, row2)
  1174. }
  1175. }
  1176. if len(tmpFromAreaIeds) == 0 {
  1177. continue
  1178. }
  1179. if len(tmpToAreaIeds) == 0 {
  1180. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
  1181. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1182. //检查未通过
  1183. scdNodeRule.AppendFcdaCheckResult(r)
  1184. continue
  1185. }
  1186. toIedname := ""
  1187. for _, row2 := range tmpFromAreaIeds {
  1188. findIedName = tools.IsEmpty(row2["ied_name"])
  1189. hasToIedRef := false
  1190. hasToIed := false
  1191. for _, row3 := range tmpToAreaIeds {
  1192. toIedname = tools.IsEmpty(row3["ied_name"])
  1193. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", toIedname)
  1194. if masterIed != nil {
  1195. hasToIed = true
  1196. // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
  1197. inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
  1198. logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
  1199. if inout != nil {
  1200. outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
  1201. for _, ieditem := range outiedlist {
  1202. outiedname := ieditem["ref_ied_name"].(string)
  1203. if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
  1204. hasToIedRef = true
  1205. break
  1206. }
  1207. }
  1208. }
  1209. if !hasToIedRef {
  1210. parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
  1211. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1212. //检查未通过
  1213. scdNodeRule.AppendFcdaCheckResult(r)
  1214. }
  1215. }
  1216. }
  1217. if !hasToIed {
  1218. parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
  1219. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1220. //检查未通过
  1221. scdNodeRule.AppendFcdaCheckResult(r)
  1222. }
  1223. }
  1224. }
  1225. }
  1226. //变压器间隔装置关系检查
  1227. 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) {
  1228. masterIed := new(node_attr.NIED)
  1229. findIedName := ""
  1230. for _, row2 := range area_ieds {
  1231. findIedName = tools.IsEmpty(row2["ied_name"])
  1232. if strings.HasPrefix(findIedName, "PT") {
  1233. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1234. break
  1235. }
  1236. }
  1237. if masterIed == nil {
  1238. return
  1239. }
  1240. scdParseMgr := new(ScdParse)
  1241. dealFromIed := map[string]int{}
  1242. for _, row := range ied_refs {
  1243. fromiedtype := tools.IsEmpty(row["from_ied_code"])
  1244. fromiedtype = strings.Split(fromiedtype, "#")[0] //去除后面的电压级别标识
  1245. toiedtype := strings.Split(tools.IsEmpty(row["to_ied_code"]), "#")[0] //去除后面的电压级别标识
  1246. reftype := tools.IsEmpty(row["in_type"])
  1247. tmpFromAreaIeds := []orm.Params{}
  1248. tmpToAreaIeds := []orm.Params{}
  1249. for _, row2 := range area_ieds {
  1250. findIedName = tools.IsEmpty(row2["ied_name"])
  1251. if strings.HasPrefix(findIedName, fromiedtype) {
  1252. masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
  1253. if masterIed != nil {
  1254. tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
  1255. } else {
  1256. if dealFromIed[findIedName] == 0 {
  1257. parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
  1258. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1259. //检查未通过
  1260. scdNodeRule.AppendFcdaCheckResult(r)
  1261. }
  1262. dealFromIed[findIedName] = 1
  1263. }
  1264. }
  1265. if strings.HasPrefix(findIedName, toiedtype) {
  1266. tmpToAreaIeds = append(tmpToAreaIeds, row2)
  1267. }
  1268. }
  1269. if len(tmpFromAreaIeds) == 0 {
  1270. continue
  1271. }
  1272. if len(tmpToAreaIeds) == 0 {
  1273. logger.Logger.Debug(fmt.Sprintf("缺失类型关联装置 :%+v", row))
  1274. parse_result := fmt.Sprintf("间隔%s缺失类型为%s的%s信号装置", area_name, toiedtype, reftype)
  1275. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1276. //检查未通过
  1277. scdNodeRule.AppendFcdaCheckResult(r)
  1278. continue
  1279. }
  1280. toIedname := ""
  1281. for _, row2 := range tmpFromAreaIeds {
  1282. findIedName = tools.IsEmpty(row2["ied_name"])
  1283. hasToIedRef := false
  1284. hasToIed := false
  1285. t1 := fromiedtype + "->" + toiedtype
  1286. volLevel := "" //电压等级
  1287. 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" {
  1288. ps := scdParseMgr.ParseIedName(findIedName)
  1289. volLevel = ps[3] + ps[4]
  1290. }
  1291. hasSameVolIed := false
  1292. for _, row3 := range tmpToAreaIeds {
  1293. toIedname = tools.IsEmpty(row3["ied_name"])
  1294. if volLevel != "" {
  1295. ps := scdParseMgr.ParseIedName(toIedname)
  1296. if volLevel != ps[3]+ps[4] {
  1297. //排除不是同一电压等级的装置
  1298. continue
  1299. }
  1300. hasSameVolIed = true
  1301. }
  1302. if scdNodeMgr.GetIed(scdXmlObj, "", toIedname) != nil {
  1303. hasToIed = true
  1304. // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
  1305. inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
  1306. logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
  1307. if inout != nil {
  1308. outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
  1309. for _, ieditem := range outiedlist {
  1310. outiedname := ieditem["ref_ied_name"].(string)
  1311. if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
  1312. hasToIedRef = true
  1313. break
  1314. }
  1315. }
  1316. }
  1317. if !hasToIedRef {
  1318. parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
  1319. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1320. //检查未通过
  1321. scdNodeRule.AppendFcdaCheckResult(r)
  1322. }
  1323. }
  1324. if hasSameVolIed {
  1325. break
  1326. }
  1327. }
  1328. if toiedtype != "PT" {
  1329. if volLevel != "" && !hasSameVolIed {
  1330. parse_result := fmt.Sprintf("间隔%s的装置%s缺失同电压等级的关联类型%s装置", area_name, findIedName, toiedtype)
  1331. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1332. //检查未通过
  1333. scdNodeRule.AppendFcdaCheckResult(r)
  1334. } else if !hasToIed {
  1335. parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
  1336. r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
  1337. //检查未通过
  1338. scdNodeRule.AppendFcdaCheckResult(r)
  1339. }
  1340. }
  1341. }
  1342. }
  1343. }
  1344. //根据参考ied name找出应该关联PM装置
  1345. func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Params) string {
  1346. tmpIedName := "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + "1" + iednameParts[7]
  1347. iedObj := ieds[tmpIedName]
  1348. if iedObj != nil {
  1349. } else {
  1350. tmpIedName = "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + "2" + iednameParts[7]
  1351. iedObj = ieds[tmpIedName]
  1352. if iedObj != nil {
  1353. return tmpIedName
  1354. }
  1355. }
  1356. return tmpIedName
  1357. }
  1358. //根据参考ied name找出应该关联MM装置
  1359. func (c *CheckAreaMgr) getMMName(iednameParts []string, ieds map[string]orm.Params, ab string) string {
  1360. tmpIedName := "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + ab
  1361. if ieds[tmpIedName] == nil {
  1362. tmpIedName = "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  1363. }
  1364. return tmpIedName
  1365. }
  1366. //根据当前设备列表,分析出电压等级(高、中、低)的设备列表
  1367. // CT测控、IT智能终端、MT合并单元需要判断是否是本体装置,是则将其归为主变高压侧
  1368. func (c *CheckAreaMgr) getIedListByVol(iedtype string, ieds map[string]orm.Params, vollevel map[string]string) (hightLst, middleLst, lowLst []orm.Params) {
  1369. tmpLst := map[string][]orm.Params{}
  1370. for _, v := range vollevel {
  1371. tmpLst[v] = []orm.Params{}
  1372. }
  1373. scdParseMgr := new(ScdParse)
  1374. for _, row := range ieds {
  1375. pl_iedname := tools.IsEmpty(row["ied_name"])
  1376. if pl_iedname[0:len(iedtype)] != iedtype {
  1377. continue
  1378. }
  1379. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  1380. volvalue := iednameParts[3] + iednameParts[4]
  1381. if tmpLst[volvalue] == nil {
  1382. tmpLst[volvalue] = []orm.Params{row}
  1383. } else {
  1384. tmpLst[volvalue] = append(tmpLst[volvalue], row)
  1385. }
  1386. }
  1387. return tmpLst[vollevel["hight"]], tmpLst[vollevel["middle"]], tmpLst[vollevel["low"]]
  1388. }
  1389. //测试
  1390. func (c *CheckAreaMgr) TestAppendNode(iedname string) {
  1391. //t := t_scd_node_scl{NodeName: iedname}
  1392. //c.AppendIedNode(&t)
  1393. }