checktools_area.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. package bo
  2. import (
  3. "errors"
  4. "fmt"
  5. "scd_check_tools/logger"
  6. "scd_check_tools/models/enum"
  7. "scd_check_tools/tools"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "github.com/astaxie/beego/orm"
  12. )
  13. //检测时间隔管理
  14. type CheckAreaMgr struct {
  15. DeviceBaseModel
  16. //SCD文件ID
  17. ScdId int64
  18. //电压等级定义
  19. VoltageLevelDef map[string]int
  20. //设备类型定义
  21. DeviceTypeDef map[string]int
  22. CacheAreaID map[string]int64
  23. CacheAreaIDByIedNameNo map[string]int
  24. //检测模型列表
  25. CheckModelList []orm.Params
  26. //模型内装置关系定义
  27. CheckModelDef sync.Map
  28. CacheLock sync.RWMutex
  29. }
  30. type T_data_check_area struct {
  31. Id int64 `orm:"pk"`
  32. AreaName string
  33. ScdId int64
  34. VoltageLevel int
  35. AreaType string
  36. ModelId int
  37. Cr int // '创建人' ,
  38. Ct string `orm:"-"` // '创建时间' ,
  39. Ur int // '更新人' ,
  40. Ut string `orm:"-"` // '更新时间'
  41. }
  42. type t_data_check_area_ied struct {
  43. Id int64 `orm:"pk"`
  44. AreaId int64
  45. IedName string
  46. IedType string
  47. ScdId int64
  48. PType string
  49. Cr int // '创建人' ,
  50. Ct string `orm:"-"` // '创建时间' ,
  51. Ur int // '更新人' ,
  52. Ut string `orm:"-"` // '更新时间'
  53. }
  54. func init() {
  55. orm.RegisterModel(new(T_data_check_area))
  56. orm.RegisterModel(new(t_data_check_area_ied))
  57. }
  58. func (c *CheckAreaMgr) Init(scdid int64) {
  59. c.VoltageLevelDef = map[string]int{}
  60. c.DeviceTypeDef = map[string]int{}
  61. c.CacheAreaIDByIedNameNo = map[string]int{}
  62. c.CacheAreaID = map[string]int64{}
  63. c.CacheLock = sync.RWMutex{}
  64. c.ScdId = scdid
  65. db := orm.NewOrm()
  66. rowset := []orm.Params{}
  67. db.Raw("select * from global_const_code where parentcode=?", "voltage_level").Values(&rowset)
  68. for _, row := range rowset {
  69. vl := strings.ToLower(tools.IsEmpty(row["code"]))
  70. id, _ := strconv.ParseInt(tools.IsEmpty(row["id"]), 10, 32)
  71. c.VoltageLevelDef[strings.ReplaceAll(vl, "v_level_", "")] = int(id)
  72. }
  73. db.Raw("select * from global_const_code where parentcode=?", "device_type").Values(&rowset)
  74. for _, row := range rowset {
  75. vl := tools.IsEmpty(row["code"])
  76. c.DeviceTypeDef[vl] = 1
  77. }
  78. v, _ := GetSysParamValue("OtherIedNameList", "")
  79. otherIedNameList = map[string]bool{}
  80. if v != "" {
  81. vs := strings.Split(v, ",")
  82. for _, vv := range vs {
  83. otherIedNameList[vv] = true
  84. }
  85. }
  86. //先清除ied与间隔关联关系
  87. clearSql := "delete from t_data_check_area_ied where area_id in(select id from t_data_check_area where scd_id=?)"
  88. _, err := db.Raw(clearSql, c.ScdId).Exec()
  89. if err != nil {
  90. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", clearSql, []interface{}{c.ScdId}))
  91. }
  92. clearSql = "delete from t_data_check_area where scd_id=?"
  93. _, err = db.Raw(clearSql, c.ScdId).Exec()
  94. if err != nil {
  95. logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", clearSql, []interface{}{c.ScdId}))
  96. }
  97. //获取当前scd信息中获取到对应的电压等级id
  98. /*
  99. scdMgr := new(ScdMgr)
  100. scdinfo, _ := scdMgr.One(fmt.Sprintf("%d", c.ScdId))
  101. stationid := tools.IsEmpty(scdinfo["station_id"])
  102. volid := 0
  103. if stationid != "" {
  104. basearea := new(BasicArea)
  105. stationonof, _ := basearea.One(stationid)
  106. volid = stationonof.AreaLevel
  107. }
  108. */
  109. c.CheckModelList, _ = new(SysCheckModelMgr).GetModelsByVolid()
  110. }
  111. //保存指定间隔所属的电压等级
  112. func (c *CheckAreaMgr) SetVoltageLevel(id string, voltagelevel int) error {
  113. db := orm.NewOrm()
  114. _, err := db.Raw("update t_data_check_area set voltage_level=? where id=?", voltagelevel, id).Exec()
  115. return err
  116. }
  117. //修改指定间隔的名称
  118. func (c *CheckAreaMgr) UpdateName(scdid int64, area_id int, name string) error {
  119. db := orm.NewOrm()
  120. areaM := T_data_check_area{Id: int64(area_id), ScdId: scdid}
  121. err := db.Read(&areaM)
  122. if err != nil {
  123. logger.Logger.Error(err)
  124. return err
  125. }
  126. areaM.AreaName = name
  127. _, err = db.Update(&areaM)
  128. if err != nil {
  129. logger.Logger.Error(err)
  130. }
  131. return err
  132. }
  133. //修改指定IED的所属间隔
  134. func (c *CheckAreaMgr) UpdateIedArea(scdid int64, iedname string, area_id int) error {
  135. db := orm.NewOrm()
  136. _, err := db.Raw("update t_data_check_area_ied set area_id=? where scd_id=? and ied_name=?", area_id, scdid, iedname).Exec()
  137. return err
  138. }
  139. //获取指定scd的间隔信息
  140. func (c *CheckAreaMgr) GetAreaList(scdid int64) ([]orm.Params, error) {
  141. db := orm.NewOrm()
  142. 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"
  143. rowset := []orm.Params{}
  144. _, err := db.Raw(sql, scdid).Values(&rowset)
  145. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{scdid})
  146. if err != nil {
  147. logger.Logger.Error(err, sqllog)
  148. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  149. } else {
  150. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  151. }
  152. return rowset, nil
  153. }
  154. //获取指定scd和电压等级的间隔信息
  155. func (c *CheckAreaMgr) GetAreaListByVol(scdid int64, vl, linkstyleid int) ([]orm.Params, error) {
  156. db := orm.NewOrm()
  157. 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=? "
  158. params := []interface{}{scdid}
  159. if vl > 0 {
  160. sql = sql + " and t1.vol_id=? "
  161. params = append(params, vl)
  162. }
  163. if linkstyleid > 0 {
  164. sql = sql + " and t1.line_link_style=? "
  165. params = append(params, linkstyleid)
  166. }
  167. rowset := []orm.Params{}
  168. _, err := db.Raw(sql, params).Values(&rowset)
  169. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{scdid, vl})
  170. if err != nil {
  171. logger.Logger.Error(err, sqllog)
  172. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  173. } else {
  174. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  175. }
  176. return rowset, nil
  177. }
  178. //获取指定间隔下的IED列表
  179. func (c *CheckAreaMgr) GetIedList(scdid int64, voltage_level_id, areaid int32, device_type string) ([]orm.Params, error) {
  180. db := orm.NewOrm()
  181. sql := "select * from t_data_check_area t,t_data_check_area_ied t1 where t.scd_id=? and t.id=t1.area_id "
  182. sqlParamters := []interface{}{}
  183. sqlParamters = append(sqlParamters, scdid)
  184. if voltage_level_id > 0 {
  185. sql = sql + " and t.voltage_level=?"
  186. sqlParamters = append(sqlParamters, voltage_level_id)
  187. }
  188. if areaid > 0 {
  189. sql = sql + " and t1.area_id=?"
  190. sqlParamters = append(sqlParamters, areaid)
  191. }
  192. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  193. if serr != nil {
  194. return nil, serr
  195. }
  196. if scdXmlObj == nil {
  197. return nil, errors.New("无效的SCD")
  198. }
  199. rowset := []orm.Params{}
  200. if device_type != "" {
  201. //根据装备类型查询IED
  202. sql = sql + " and t1.ied_type=?"
  203. sqlParamters = append(sqlParamters, device_type)
  204. }
  205. _, err := db.Raw(sql, sqlParamters).Values(&rowset)
  206. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, sqlParamters)
  207. if err != nil {
  208. logger.Logger.Error(err, sqllog)
  209. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  210. } else {
  211. scdNode := new(ScdNode)
  212. for _, row := range rowset {
  213. iedid, _ := strconv.ParseInt(tools.IsEmpty(row["ied_id"]), 10, 64)
  214. iedObj := scdNode.GetIedByID(scdXmlObj, tools.IsEmpty(scdid), iedid)
  215. if iedObj == nil {
  216. continue
  217. }
  218. row["attr_name"] = iedObj.Name
  219. row["attr_desc"] = iedObj.Desc
  220. row["attr_config_version"] = iedObj.ConfigVersion
  221. row["attr_type"] = iedObj.Type
  222. row["attr_manufacturer"] = iedObj.Manufacturer
  223. row["ied_id"] = iedObj.NodeId
  224. }
  225. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  226. }
  227. return rowset, nil
  228. }
  229. //获取指定SCD的IED类型列表
  230. func (c *CheckAreaMgr) GetIedTypeList(scdid int64) ([]orm.Params, error) {
  231. db := orm.NewOrm()
  232. 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 "
  233. sqlParamters := []interface{}{}
  234. rowset := []orm.Params{}
  235. sqlParamters = append(sqlParamters, scdid)
  236. _, err := db.Raw(sql, sqlParamters).Values(&rowset)
  237. sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, sqlParamters)
  238. if err != nil {
  239. logger.Logger.Error(err, sqllog)
  240. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  241. }
  242. return rowset, nil
  243. }
  244. func (c *CheckAreaMgr) One(id string) (interface{}, error) {
  245. db := orm.NewOrm()
  246. idInt, err := strconv.ParseInt(id, 10, 64)
  247. if err != nil {
  248. return nil, err
  249. }
  250. areaM := T_data_check_area{Id: idInt}
  251. err = db.Read(&areaM)
  252. if err == nil {
  253. return areaM, nil
  254. }
  255. return nil, err
  256. }
  257. //重置scd的间隔信息
  258. func (c *CheckAreaMgr) Reset() error {
  259. dbo := orm.NewOrm()
  260. dbo.Raw("delete from t_data_check_area where scd_id=?", c.ScdId).Exec()
  261. dbo.Raw("delete from t_data_check_area_ied where scd_id=?", c.ScdId).Exec()
  262. c.ParseModelArea()
  263. logdesc := fmt.Sprintf("重置SCD[%d]检测模型间隔成功", c.ScdId)
  264. new(SystemLog).Success(enum.AuditType_check_task, enum.LogType_bind, enum.OptEventType_Bus, enum.OptEventLevel_Mid, logdesc, c.GetUserInfo())
  265. return nil
  266. }
  267. //解析模型间隔
  268. func (c *CheckAreaMgr) ParseModelArea() {
  269. c.Init(c.ScdId)
  270. // 取得当前scd所有ied及名称解析结果
  271. dbo := orm.NewOrm()
  272. 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"
  273. iedlst := []orm.Params{}
  274. _, err := dbo.Raw(sql, c.ScdId).Values(&iedlst)
  275. if err != nil {
  276. logger.Logger.Error(err)
  277. return
  278. }
  279. iedMap := map[string]orm.Params{}
  280. for _, r := range iedlst {
  281. iedMap[tools.IsEmpty(r["ied_name"])] = r
  282. }
  283. //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
  284. HasAreaJ := false
  285. for _, row := range c.CheckModelList {
  286. areaCode := tools.IsEmpty(row["area_type_code"])
  287. if areaCode == "J" {
  288. HasAreaJ = true
  289. modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
  290. //modelname := tools.IsEmpty(row["model_name"])
  291. iedtypes := tools.IsEmpty(row["ied_types"])
  292. volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
  293. c.pJ(modelid, volcode, iedtypes, iedMap, "PE")
  294. c.pJ(modelid, volcode, iedtypes, iedMap, "PJ")
  295. c.pJ(modelid, volcode, iedtypes, iedMap, "PK")
  296. c.pJ(modelid, volcode, iedtypes, iedMap, "PF")
  297. }
  298. }
  299. for _, row := range c.CheckModelList {
  300. //逐一分析模型定义
  301. modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
  302. modelname := tools.IsEmpty(row["model_name"])
  303. iedtypes := tools.IsEmpty(row["ied_types"])
  304. //模型对应的间隔代码
  305. /*
  306. S 站用变压器
  307. C 电容器
  308. B 断路器
  309. K 母分
  310. J 母联
  311. M 母线
  312. X 电抗器
  313. L 线路
  314. T 主变压器
  315. */
  316. areaCode := tools.IsEmpty(row["area_type_code"])
  317. //模型对应的电压等级
  318. //10:10KV 35:35KV 66:66KV 11:110KV 22:220KV 50:500KV 75:750KV 33:330KV T0:1000KV
  319. volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
  320. if modelname == "" || iedtypes == "" {
  321. continue
  322. }
  323. //母联间隔已经提前分析,如果没有母联间隔时,主变间隔中不包含母联终端装置
  324. if areaCode == "J" {
  325. continue
  326. }
  327. //获取模型内中装备关系定义
  328. //主变间隔分析:需要查站内该电压等级下的高中低压侧装置或者高低压装置组成一个间隔,以主变保护装置(PT)为起始
  329. if areaCode == "T" {
  330. go c.pT(modelid, iedtypes, iedMap, HasAreaJ)
  331. }
  332. //线路保护间隔分析:以线路保护测控装置(PL)为开始分析
  333. if areaCode == "L" {
  334. go c.pL(modelid, volcode, iedtypes, iedMap)
  335. }
  336. }
  337. }
  338. //变压器间隔分析
  339. func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Params, HasAreaJ bool) {
  340. scdParseMgr := new(ScdParse)
  341. db := orm.NewOrm()
  342. //获取当前站的各电压等级
  343. volRows := []orm.Params{}
  344. _, 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)
  345. if err != nil {
  346. logger.Logger.Error(err)
  347. return
  348. }
  349. if len(volRows) == 0 {
  350. logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
  351. return
  352. }
  353. volMap := map[string]string{}
  354. volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
  355. if len(volRows) == 2 {
  356. volMap["middle"] = ""
  357. volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
  358. } else {
  359. volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
  360. volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
  361. }
  362. for _, row := range ieds {
  363. if tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "T" {
  364. continue
  365. }
  366. //pmIedName := ""
  367. //mmIedName := ""
  368. pl_iedname := tools.IsEmpty(row["ied_name"])
  369. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  370. //添加间隔数据
  371. dbdata := T_data_check_area{
  372. ModelId: modelid,
  373. ScdId: c.ScdId,
  374. AreaType: "T",
  375. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  376. }
  377. newid, err := db.Insert(&dbdata)
  378. if err != nil {
  379. logger.Logger.Error(err)
  380. return
  381. }
  382. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  383. insvalues := []string{}
  384. inAreaIedName := pl_iedname
  385. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "T"))
  386. //合智一体IMT/MIT,分高中低压
  387. h, m, l := c.getIedListByVol("IMT", ieds, volMap)
  388. h = append(h, m...)
  389. h = append(h, l...)
  390. for _, r := range h {
  391. inAreaIedName = tools.IsEmpty(r["ied_name"])
  392. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  393. lastChar := tmpIednameParts[7]
  394. if lastChar == iednameParts[7] {
  395. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "IM", "T"))
  396. }
  397. }
  398. h, m, l = c.getIedListByVol("MIT", ieds, volMap)
  399. h = append(h, m...)
  400. h = append(h, l...)
  401. for _, r := range h {
  402. inAreaIedName = tools.IsEmpty(r["ied_name"])
  403. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  404. lastChar := tmpIednameParts[7]
  405. if lastChar == iednameParts[7] {
  406. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "MI", "T"))
  407. }
  408. }
  409. //母联智能终端IE需要分高中压,无低压侧
  410. if HasAreaJ {
  411. h, m, l = c.getIedListByVol("IE", ieds, volMap)
  412. for _, r := range h {
  413. //高压侧,AB套必须与PT装置相同
  414. inAreaIedName = tools.IsEmpty(r["ied_name"])
  415. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  416. lastChar := tmpIednameParts[7]
  417. if lastChar == iednameParts[7] {
  418. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "E"))
  419. }
  420. }
  421. for _, r := range m {
  422. //中压侧
  423. inAreaIedName = tools.IsEmpty(r["ied_name"])
  424. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  425. lastChar := tmpIednameParts[7]
  426. if lastChar == "" || lastChar == iednameParts[7] {
  427. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "E"))
  428. }
  429. }
  430. }
  431. //合并单元MT分高中低压侧;低压侧无关联母线合并单元MM
  432. h, m, l = c.getIedListByVol("MT", ieds, volMap)
  433. h = append(h, m...)
  434. h = append(h, l...)
  435. for _, r := range h {
  436. inAreaIedName = tools.IsEmpty(r["ied_name"])
  437. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  438. lastChar := tmpIednameParts[7]
  439. if lastChar == iednameParts[7] {
  440. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "T"))
  441. }
  442. }
  443. //测控装置CT分高中低压侧,且可能是多套合并单元MT共用,既不分AB套
  444. h, m, l = c.getIedListByVol("CT", ieds, volMap)
  445. h = append(h, m...)
  446. h = append(h, l...)
  447. for _, r := range h {
  448. inAreaIedName = tools.IsEmpty(r["ied_name"])
  449. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  450. lastChar := tmpIednameParts[7]
  451. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  452. //高中低压电压等级相同的
  453. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  454. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "C", "T"))
  455. }
  456. }
  457. //智能终端(IB:开关\IT:分支\IF:分段)分高中低压侧
  458. h, m, l = c.getIedListByVol("IB", ieds, volMap)
  459. h = append(h, m...)
  460. h = append(h, l...)
  461. for _, r := range h {
  462. inAreaIedName = tools.IsEmpty(r["ied_name"])
  463. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  464. lastChar := tmpIednameParts[7]
  465. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  466. //高中低压电压等级相同的
  467. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  468. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "B"))
  469. }
  470. }
  471. h, m, l = c.getIedListByVol("IT", ieds, volMap)
  472. h = append(h, m...)
  473. h = append(h, l...)
  474. for _, r := range h {
  475. inAreaIedName = tools.IsEmpty(r["ied_name"])
  476. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  477. lastChar := tmpIednameParts[7]
  478. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  479. //高中低压电压等级相同的
  480. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  481. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "T"))
  482. }
  483. }
  484. h, m, l = c.getIedListByVol("IF", ieds, volMap)
  485. h = append(h, m...)
  486. h = append(h, l...)
  487. for _, r := range h {
  488. inAreaIedName = tools.IsEmpty(r["ied_name"])
  489. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  490. lastChar := tmpIednameParts[7]
  491. tmpVol := tmpIednameParts[3] + tmpIednameParts[4]
  492. //高中低压电压等级相同的
  493. if (tmpVol == volMap["low"] || tmpVol == volMap["middle"] || tmpVol == volMap["hight"]) && (lastChar == "" || lastChar == iednameParts[7]) {
  494. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "I", "F"))
  495. }
  496. }
  497. //母线保护PM及母线合并单元MM,可能是多套合并单元MT共用,既不分AB套;低压侧智能终端无关联母线保护
  498. h, m, l = c.getIedListByVol("PM", ieds, volMap)
  499. for _, r := range h {
  500. //高压侧,AB套必须与PT装置相同
  501. inAreaIedName = tools.IsEmpty(r["ied_name"])
  502. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  503. lastChar := tmpIednameParts[7]
  504. if lastChar == iednameParts[7] {
  505. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
  506. //MM装置
  507. mmIedName := c.getMMName(tmpIednameParts, ieds, iednameParts[7])
  508. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, mmIedName, "M", "M"))
  509. break
  510. }
  511. }
  512. for _, r := range m {
  513. //中压侧
  514. inAreaIedName = tools.IsEmpty(r["ied_name"])
  515. tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
  516. lastChar := tmpIednameParts[7]
  517. if lastChar == "" || lastChar == iednameParts[7] {
  518. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
  519. //MM装置
  520. mmIedName := c.getMMName(tmpIednameParts, ieds, iednameParts[7])
  521. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, mmIedName, "M", "M"))
  522. break
  523. }
  524. }
  525. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  526. if err != nil {
  527. logger.Logger.Error(err)
  528. return
  529. }
  530. }
  531. }
  532. //线路间隔分析
  533. //vol:电压等级
  534. func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm.Params) {
  535. scdParseMgr := new(ScdParse)
  536. //scdNodeMgr := new(ScdNode)
  537. db := orm.NewOrm()
  538. //scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  539. for _, row := range ieds {
  540. if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != "L" {
  541. continue
  542. }
  543. pmIedName := ""
  544. mmIedName := ""
  545. pl_iedname := tools.IsEmpty(row["ied_name"])
  546. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  547. //添加间隔数据
  548. dbdata := T_data_check_area{
  549. ModelId: modelid,
  550. ScdId: c.ScdId,
  551. AreaType: "L",
  552. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  553. }
  554. newid, err := db.Insert(&dbdata)
  555. if err != nil {
  556. logger.Logger.Error(err)
  557. return
  558. }
  559. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  560. insvalues := []string{}
  561. for _, ty := range strings.Split(iedtypes, ",") {
  562. inAreaIedName := ""
  563. if ty == "PM" {
  564. //母线保护和母线合并单元装置编号跟随变压器
  565. //查找变压器编号
  566. //1号变压器->2号变压器->3号
  567. inAreaIedName = c.getPMName(iednameParts, ieds)
  568. pmIedName = inAreaIedName
  569. if mmIedName == "" {
  570. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  571. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  572. //使用PM装置的名称去定义MM的名称
  573. ty = "MM"
  574. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  575. mmIedName = inAreaIedName
  576. }
  577. } else if ty == "MM" {
  578. if pmIedName != "" && mmIedName == "" {
  579. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  580. //使用PM装置的名称去定义MM的名称
  581. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  582. mmIedName = inAreaIedName
  583. } else {
  584. continue
  585. }
  586. } else {
  587. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  588. }
  589. if strings.Index("ABCDE", iednameParts[7]) > -1 {
  590. //最后一位是字母则说明是AB套
  591. switch ty {
  592. case "CL":
  593. //测控装置,先判断是否分了AB套,没有标识(ied名称的最后一位是否是字母)则说明是多套共用装置
  594. clIedname := inAreaIedName + iednameParts[7]
  595. iedObj := ieds[inAreaIedName]
  596. if iedObj != nil {
  597. //当前测控装置也分了AB套
  598. inAreaIedName = clIedname
  599. }
  600. break
  601. default:
  602. break
  603. }
  604. }
  605. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  606. }
  607. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  608. if err != nil {
  609. logger.Logger.Error(err)
  610. return
  611. }
  612. //如果mm装置还未确定
  613. if mmIedName == "" {
  614. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  615. inAreaIedName := c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  616. _, err = db.Raw(ins1 + fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "M")).Exec()
  617. if err != nil {
  618. logger.Logger.Error(err)
  619. return
  620. }
  621. }
  622. }
  623. }
  624. //母联间隔分析
  625. func (c *CheckAreaMgr) pJ(modelid int, vol, iedtypes string, ieds map[string]orm.Params, pjIed string) {
  626. scdParseMgr := new(ScdParse)
  627. //scdNodeMgr := new(ScdNode)
  628. db := orm.NewOrm()
  629. //scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
  630. for _, row := range ieds {
  631. if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != "P" || tools.IsEmpty(row["p_type"]) != pjIed[1:2] {
  632. continue
  633. }
  634. pmIedName := ""
  635. mmIedName := ""
  636. pl_iedname := tools.IsEmpty(row["ied_name"])
  637. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  638. //添加间隔数据
  639. dbdata := T_data_check_area{
  640. ModelId: modelid,
  641. ScdId: c.ScdId,
  642. AreaType: "J",
  643. AreaName: tools.IsEmpty(row["area_name"]) + iednameParts[7],
  644. }
  645. newid, err := db.Insert(&dbdata)
  646. if err != nil {
  647. logger.Logger.Error(err)
  648. return
  649. }
  650. ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
  651. insvalues := []string{}
  652. for _, ty := range strings.Split(iedtypes, ",") {
  653. inAreaIedName := ""
  654. if ty == "PM" {
  655. //母线保护和母线合并单元装置编号跟随变压器
  656. //查找变压器编号
  657. //1号变压器->2号变压器->3号
  658. inAreaIedName = c.getPMName(iednameParts, ieds)
  659. pmIedName = inAreaIedName
  660. if mmIedName == "" {
  661. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  662. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  663. //使用PM装置的名称去定义MM的名称
  664. ty = "MM"
  665. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  666. mmIedName = inAreaIedName
  667. }
  668. } else if ty == "MM" {
  669. if pmIedName != "" && mmIedName == "" {
  670. pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
  671. //使用PM装置的名称去定义MM的名称
  672. inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
  673. mmIedName = inAreaIedName
  674. } else {
  675. continue
  676. }
  677. } else {
  678. ty = ty[0:1] + pjIed[1:2]
  679. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  680. //判断与基准保护装置相同套号的装置是否存在
  681. if ieds[inAreaIedName] == nil {
  682. //尝试去除套号
  683. inAreaIedName = ty + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6]
  684. }
  685. }
  686. insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ty[0:1], ty[1:2]))
  687. }
  688. _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
  689. if err != nil {
  690. logger.Logger.Error(err)
  691. return
  692. }
  693. }
  694. }
  695. //根据参考ied name找出应该关联PM装置
  696. func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Params) string {
  697. tmpIedName := "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + "1" + iednameParts[7]
  698. iedObj := ieds[tmpIedName]
  699. if iedObj != nil {
  700. } else {
  701. tmpIedName = "PM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + "2" + iednameParts[7]
  702. iedObj = ieds[tmpIedName]
  703. if iedObj != nil {
  704. return tmpIedName
  705. }
  706. }
  707. return tmpIedName
  708. }
  709. //根据参考ied name找出应该关联MM装置
  710. func (c *CheckAreaMgr) getMMName(iednameParts []string, ieds map[string]orm.Params, ab string) string {
  711. tmpIedName := "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + ab
  712. if ieds[tmpIedName] == nil {
  713. tmpIedName = "MM" + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
  714. }
  715. return tmpIedName
  716. }
  717. //根据当前设备列表,分析出电压等级(高、中、低)的设备列表
  718. // CT测控、IT智能终端、MT合并单元需要判断是否是本体装置,是则将其归为主变高压侧
  719. func (c *CheckAreaMgr) getIedListByVol(iedtype string, ieds map[string]orm.Params, vollevel map[string]string) (hightLst, middleLst, lowLst []orm.Params) {
  720. tmpLst := map[string][]orm.Params{}
  721. for _, v := range vollevel {
  722. tmpLst[v] = []orm.Params{}
  723. }
  724. scdParseMgr := new(ScdParse)
  725. for _, row := range ieds {
  726. pl_iedname := tools.IsEmpty(row["ied_name"])
  727. if pl_iedname[0:len(iedtype)] != iedtype {
  728. continue
  729. }
  730. iednameParts := scdParseMgr.ParseIedName(pl_iedname)
  731. volvalue := iednameParts[3] + iednameParts[4]
  732. if tmpLst[volvalue] == nil {
  733. tmpLst[volvalue] = []orm.Params{row}
  734. } else {
  735. tmpLst[volvalue] = append(tmpLst[volvalue], row)
  736. }
  737. }
  738. return tmpLst[vollevel["hight"]], tmpLst[vollevel["middle"]], tmpLst[vollevel["low"]]
  739. }
  740. //测试
  741. func (c *CheckAreaMgr) TestAppendNode(iedname string) {
  742. //t := t_scd_node_scl{NodeName: iedname}
  743. //c.AppendIedNode(&t)
  744. }