checktools_area.go 52 KB

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