checktools_area.go 29 KB

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