checktools_area.go 45 KB

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