checktools_area.go 28 KB

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