scd_node_mgr.go 97 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103
  1. package bo
  2. import (
  3. "bufio"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "log"
  9. "os"
  10. "runtime"
  11. "scd_check_tools/global"
  12. "scd_check_tools/logger"
  13. "scd_check_tools/models/enum"
  14. "scd_check_tools/models/node_attr"
  15. "scd_check_tools/mqtt"
  16. "scd_check_tools/tools"
  17. "strconv"
  18. "strings"
  19. "time"
  20. "github.com/astaxie/beego/orm"
  21. )
  22. type ScdNode struct {
  23. RootID int64
  24. ScdName string
  25. ScdPath string
  26. Name string
  27. DeviceBaseModel
  28. //未结束的XML标签列表
  29. NotEndNodeIdList []int64
  30. //节点队列
  31. NodeQue map[int64]*t_scd_node_scl
  32. //节点属性入库队列
  33. NodeAttrQue []interface{}
  34. //节点验证规则定义
  35. NodeRuleList map[string][]orm.Params
  36. //节点属性验证规则定义
  37. NodeAttrRuleList map[string][]orm.Params
  38. //节点属性唯一性验证规则定义
  39. NodeAttrUniqueRuleList []orm.Params
  40. //节点验证规则列表:内置验证程序实现
  41. NodeRuleFunctionList []orm.Params
  42. //间隔管理对象
  43. AreaMgr *ScdAreaMgr
  44. //解析完后自动比对的scdID,如果未设置 ,则解析后不做比对
  45. AutoCompScdID int64
  46. StationID int
  47. //是否默认为在运版。当签入流程只有一个节点时,需要设备该属性为1,此时在解析完文件后将该scd设置为在运版本
  48. IsDefaultRunVersion int
  49. //间隔解析方式.分为Bay方式和自定义解析方式(根据name和des进行分词解析),默认为自定义解析方式解析
  50. IsBay bool
  51. }
  52. type t_scd_node_scl struct {
  53. Id int64 `orm:"pk"`
  54. ScdId int64
  55. ParentNodeId int64
  56. NodeName string
  57. NodeValue string
  58. LineNo int64
  59. CreatedBy int
  60. CreatedTime string
  61. }
  62. type t_scd_scl struct {
  63. Id int64 `orm:"pk"`
  64. ScdName string
  65. Path string
  66. Version string
  67. Enable int
  68. StationId int
  69. //签出锁定
  70. CheckoutLock int
  71. //是否是管控SCD,true为管控SCD,false为非管控SCD
  72. IsCheckinScd int
  73. CreatedBy int
  74. CreatedTime string
  75. }
  76. type t_ied_ctrl_relation struct {
  77. Id int `orm:"pk"`
  78. ScdId int64
  79. MasterIedId int64
  80. MasterIedName string
  81. RefType int
  82. SourceIedId int64
  83. SourceIedName string
  84. TargetIedId int64
  85. TargetIedName string
  86. OutLdId int64
  87. OutLdInst string
  88. OutLdDesc string
  89. LdId int64
  90. LdInst string
  91. LdDesc string
  92. CtrlId int64
  93. CtrlType string
  94. CtrlName string
  95. DatsetId int64
  96. DatsetName string
  97. DatsetDesc string
  98. Cnt int
  99. }
  100. func init() {
  101. orm.RegisterModel(new(t_scd_scl))
  102. orm.RegisterModel(new(t_scd_node_scl))
  103. orm.RegisterModel(new(t_ied_ctrl_relation))
  104. }
  105. func (c *ScdNode) GetCheckToolsTreeRoot(id, pid int64, datatype string) ([]orm.Params, error) {
  106. sclObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(c.RootID))
  107. if serr != nil {
  108. return nil, serr
  109. }
  110. if sclObj == nil {
  111. return nil, errors.New("无效的SCD编号")
  112. }
  113. alertDef := map[string]int{
  114. "": 0,
  115. "hint": 1,
  116. "waring": 2,
  117. "error": 3,
  118. }
  119. noderuleObj := new(ScdNodeRule)
  120. noderuleObj.ScdID = c.RootID
  121. ruleHintLevel, _ := noderuleObj.SumCheckResult()
  122. alertlevelMap := map[string]string{}
  123. for _, levelrow := range ruleHintLevel {
  124. key := fmt.Sprintf("%s%s", levelrow["object_name"], levelrow["ied_name"])
  125. if v, h := alertlevelMap[key]; h {
  126. level := tools.IsEmpty(levelrow["alert_level"])
  127. if alertDef[level] > alertDef[v] {
  128. alertlevelMap[key] = level
  129. }
  130. } else {
  131. alertlevelMap[key] = tools.IsEmpty(levelrow["alert_level"])
  132. }
  133. }
  134. db := orm.NewOrm()
  135. reuslt := []orm.Params{}
  136. areaMgr := new(ScdAreaMgr)
  137. if id == 0 {
  138. sclAlertLevel := ""
  139. if alertDef[alertlevelMap["Header"]] > alertDef[sclAlertLevel] {
  140. sclAlertLevel = alertlevelMap["Header"]
  141. }
  142. if alertDef[alertlevelMap["Substation"]] > alertDef[sclAlertLevel] {
  143. sclAlertLevel = alertlevelMap["Substation"]
  144. }
  145. reuslt = append(reuslt, orm.Params{
  146. "id": "9999",
  147. "title": "基本语法校验结果",
  148. "pid": sclObj.NodeId,
  149. "isParent": "false",
  150. "datatype": "SCLSyntax",
  151. "alert_level": alertlevelMap["SCLSyntax"],
  152. })
  153. sclAlertLevel = alertlevelMap["SCLSyntax"]
  154. //添加通信节点
  155. reuslt = append(reuslt, orm.Params{
  156. "id": sclObj.Communication.NodeId,
  157. "title": "Communication",
  158. "pid": sclObj.NodeId,
  159. "isParent": "false",
  160. "datatype": "Communication",
  161. "alert_level": alertlevelMap["Communication"],
  162. })
  163. if alertDef[alertlevelMap["Communication"]] > alertDef[sclAlertLevel] {
  164. sclAlertLevel = alertlevelMap["Communication"]
  165. }
  166. //添加数据模板节点
  167. reuslt = append(reuslt, orm.Params{
  168. "id": sclObj.DataTypeTemplates.NodeId,
  169. "title": "DataTypeTemplates",
  170. "pid": sclObj.NodeId,
  171. "isParent": "false",
  172. "datatype": "DataTypeTemplates",
  173. "alert_level": alertlevelMap["DataTypeTemplates"],
  174. })
  175. if alertDef[alertlevelMap["DataTypeTemplates"]] > alertDef[sclAlertLevel] {
  176. sclAlertLevel = alertlevelMap["DataTypeTemplates"]
  177. }
  178. //获取间隔列表
  179. areaList, err := areaMgr.GetAreaList(c.RootID)
  180. if err != nil {
  181. return reuslt, err
  182. }
  183. voltageLevel := map[string]string{} //电压等级的告警级别
  184. //获取该电压等级下的间隔列表
  185. for _, ararow := range areaList {
  186. ararow["title"] = ararow["name"]
  187. ararow["datatype"] = "area"
  188. ararow["isParent"] = "true"
  189. ararow["alert_level"] = ""
  190. ararow["pid"] = tools.IsEmpty(ararow["voltage_level"])
  191. areaid, _ := strconv.Atoi(tools.IsEmpty(ararow["id"]))
  192. iedList, err := areaMgr.GetIedList(c.RootID, 0, int32(areaid), "")
  193. if err != nil {
  194. continue
  195. }
  196. //获取间隔下的IED
  197. alertLevel := ""
  198. for _, row := range iedList {
  199. row["isParent"] = "false"
  200. row["pid"] = ararow["id"]
  201. row["id"] = row["node_id"]
  202. row["title"] = "[" + tools.IsEmpty(row["attr_name"]) + "]" + strings.Replace(tools.IsEmpty(row["attr_desc"]), tools.IsEmpty(row["name"]), "..", 1)
  203. iedAlart := alertlevelMap["IED"+tools.IsEmpty(row["attr_name"])]
  204. row["alert_level"] = iedAlart
  205. reuslt = append(reuslt, row)
  206. if alertDef[iedAlart] > alertDef[alertLevel] {
  207. alertLevel = iedAlart
  208. }
  209. }
  210. ararow["alert_level"] = alertLevel //间隔的告警级别
  211. reuslt = append(reuslt, ararow)
  212. vol := tools.IsEmpty(ararow["voltage_level"])
  213. if v, h := voltageLevel[vol]; h {
  214. if alertDef[alertLevel] > alertDef[v] {
  215. voltageLevel[vol] = alertLevel
  216. }
  217. } else {
  218. voltageLevel[vol] = alertLevel
  219. }
  220. }
  221. //添加电压等级子节点
  222. sql := "select voltage_level id,t1.name title,0 pid ,'true' isParent,'voltage_level' datatype from t_substation_area t,global_const_code t1 where t.voltage_level=t1.id and scd_id=? GROUP BY voltage_level ORDER BY voltage_level"
  223. voltagelevelRowset := []orm.Params{}
  224. db.Raw(sql, c.RootID).Values(&voltagelevelRowset)
  225. for _, row2 := range voltagelevelRowset {
  226. row2["pid"] = sclObj.NodeId
  227. vollevel := voltageLevel[tools.IsEmpty(row2["id"])]
  228. row2["alert_level"] = vollevel
  229. reuslt = append(reuslt, row2)
  230. if alertDef[vollevel] > alertDef[sclAlertLevel] {
  231. sclAlertLevel = vollevel
  232. }
  233. }
  234. //添加SCL节点
  235. reuslt = append(reuslt, orm.Params{
  236. "id": sclObj.NodeId,
  237. "title": "SCL",
  238. "pid": 0,
  239. "isParent": "true",
  240. "datatype": "SCL",
  241. "alert_level": sclAlertLevel,
  242. })
  243. } else {
  244. if datatype == "area" {
  245. //当前为间隔时,则返回该间隔下的IED
  246. iedList, err := areaMgr.GetIedList(c.RootID, 0, int32(id), "")
  247. if err != nil {
  248. return nil, err
  249. }
  250. for _, row := range iedList {
  251. row["isParent"] = "false"
  252. row["pid"] = id
  253. row["id"] = row["node_id"]
  254. row["title"] = strings.Replace(tools.IsEmpty(row["attr_desc"]), tools.IsEmpty(row["name"]), "..", 1)
  255. }
  256. reuslt = iedList
  257. }
  258. }
  259. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, "查询IED结构树", c.GetUserInfo())
  260. return reuslt, nil
  261. }
  262. //查询指定scd的节点列表
  263. func (c *ScdNode) List(param map[string]interface{}) ([]orm.Params, int, error) {
  264. scdid := tools.IsEmpty(param["scd_id"])
  265. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  266. if serr != nil {
  267. return nil, 0, serr
  268. }
  269. if scdXmlObj == nil {
  270. return nil, 0, errors.New("无效的SCD文件")
  271. }
  272. iedname := tools.IsEmpty(param["ied_name"])
  273. rowset := []orm.Params{}
  274. if v, ok := param["name"]; ok {
  275. name := tools.IsEmpty(v)
  276. switch name {
  277. case "SubNetwork":
  278. for _, item := range scdXmlObj.Communication.SubNetwork {
  279. rowobj := orm.Params{
  280. "node_id": item.NodeId,
  281. "node_name": "SubNetwork",
  282. "node_value": "",
  283. "parent_node_id": scdXmlObj.Communication.NodeId,
  284. "attr_desc": item.Desc,
  285. "attr_name": item.Name,
  286. "attr_type": item.Type,
  287. }
  288. rowset = append(rowset, rowobj)
  289. }
  290. break
  291. case "ConnectedAP":
  292. for _, item := range scdXmlObj.Communication.SubNetwork {
  293. for _, c1 := range item.ConnectedAP {
  294. rowobj := orm.Params{
  295. "node_id": c1.NodeId,
  296. "node_name": "ConnectedAP",
  297. "node_value": "",
  298. "parent_node_id": item.NodeId,
  299. "attr_desc": c1.Desc,
  300. "attr_ied_name": c1.IedName,
  301. "attr_ap_name": c1.ApName,
  302. }
  303. rowset = append(rowset, rowobj)
  304. }
  305. }
  306. break
  307. case "AccessPoint":
  308. if iedname == "" {
  309. return nil, 0, errors.New("IED Name不能为空")
  310. }
  311. iedObj := new(ScdNode).GetIed(scdXmlObj, scdid, iedname)
  312. if iedObj == nil {
  313. return nil, 0, errors.New("无效的IED Name")
  314. }
  315. for _, item := range iedObj.AccessPoint {
  316. rowobj := orm.Params{
  317. "node_id": item.NodeId,
  318. "node_name": "AccessPoint",
  319. "node_value": "",
  320. "parent_node_id": iedObj.NodeId,
  321. "attr_desc": item.Desc,
  322. "ied_name": iedObj.Name,
  323. "attr_name": item.Name,
  324. "attr_clock": item.Clock,
  325. "attr_router": item.Router,
  326. }
  327. rowset = append(rowset, rowobj)
  328. }
  329. break
  330. case "DataSet":
  331. if iedname == "" {
  332. return nil, 0, errors.New("IED Name不能为空")
  333. }
  334. iedObj := new(ScdNode).GetIed(scdXmlObj, scdid, iedname)
  335. if iedObj == nil {
  336. return nil, 0, errors.New("无效的IED Name")
  337. }
  338. for _, item := range iedObj.AccessPoint {
  339. if item.Server == nil {
  340. continue
  341. }
  342. for _, c1 := range item.Server.LDevice {
  343. for _, ds := range c1.LN0.DataSet {
  344. rowobj := orm.Params{
  345. "node_id": ds.NodeId,
  346. "node_name": "DataSet",
  347. "node_value": "",
  348. "parent_node_id": c1.NodeId,
  349. "attr_desc": ds.Desc,
  350. "ied_name": iedObj.Name,
  351. "attr_name": ds.Name,
  352. }
  353. rowset = append(rowset, rowobj)
  354. }
  355. }
  356. }
  357. break
  358. case "LN0":
  359. parent_node_id, _ := strconv.ParseInt(tools.IsEmpty(param["parent_node_id"]), 10, 64)
  360. scdidint64, _ := strconv.ParseInt(scdid, 10, 64)
  361. v_scdcache, _ := GlobalNodeMap.Load(scdidint64)
  362. if v_scdcache == nil {
  363. break
  364. }
  365. scdcache := v_scdcache.(map[int64]NodeCacheMap)
  366. ldevice := scdcache[parent_node_id].ObjAddr.(*node_attr.NLDevice)
  367. rowobj := orm.Params{
  368. "node_id": ldevice.LN0.NodeId,
  369. "node_name": "LN0",
  370. "node_value": "",
  371. "parent_node_id": parent_node_id,
  372. "attr_desc": ldevice.LN0.Desc,
  373. "ied_name": "",
  374. "attr_inst": ldevice.LN0.Inst,
  375. "attr_ln_class": ldevice.LN0.LnClass,
  376. "attr_ln_type": ldevice.LN0.LnType,
  377. "attr_prefix": ldevice.LN0.Prefix,
  378. }
  379. rowset = append(rowset, rowobj)
  380. break
  381. case "LN":
  382. parent_node_id, _ := strconv.ParseInt(tools.IsEmpty(param["parent_node_id"]), 10, 64)
  383. scdidint64, _ := strconv.ParseInt(scdid, 10, 64)
  384. v_scdcache, _ := GlobalNodeMap.Load(scdidint64)
  385. if v_scdcache == nil {
  386. break
  387. }
  388. scdcache := v_scdcache.(map[int64]NodeCacheMap)
  389. ldevice := scdcache[parent_node_id].ObjAddr.(*node_attr.NLDevice)
  390. for _, ln := range ldevice.LN {
  391. rowobj := orm.Params{
  392. "node_id": ln.NodeId,
  393. "node_name": "LN",
  394. "node_value": "",
  395. "parent_node_id": parent_node_id,
  396. "attr_desc": ln.Desc,
  397. "ied_name": "",
  398. "attr_inst": ln.Inst,
  399. "attr_ln_class": ln.LnClass,
  400. "attr_ln_type": ln.LnType,
  401. "attr_prefix": ln.Prefix,
  402. }
  403. rowset = append(rowset, rowobj)
  404. }
  405. break
  406. case "FCDA":
  407. parent_node_id, _ := strconv.ParseInt(tools.IsEmpty(param["parent_node_id"]), 10, 64)
  408. scdidint64, _ := strconv.ParseInt(scdid, 10, 64)
  409. v_scdcache, _ := GlobalNodeMap.Load(scdidint64)
  410. if v_scdcache == nil {
  411. break
  412. }
  413. scdcache := v_scdcache.(map[int64]NodeCacheMap)
  414. ds := scdcache[parent_node_id].ObjAddr.(*node_attr.NDataSet)
  415. for _, fcda := range ds.FCDA {
  416. rowobj := orm.Params{
  417. "node_id": fcda.NodeId,
  418. "node_name": "FCDA",
  419. "node_value": "",
  420. "parent_node_id": parent_node_id,
  421. "attr_da_name": fcda.DaName,
  422. "attr_do_name": fcda.DoName,
  423. "attr_fc": fcda.Fc,
  424. "attr_ld_inst": fcda.LdInst,
  425. "attr_ln_class": fcda.LnClass,
  426. "attr_ln_inst": fcda.LnInst,
  427. "attr_prefix": fcda.Prefix,
  428. }
  429. rowset = append(rowset, rowobj)
  430. }
  431. default:
  432. break
  433. }
  434. }
  435. return rowset, len(rowset), nil
  436. }
  437. //获取指定节点的所有属性及属性值
  438. func (c *ScdNode) GetAttrValues(param map[string]interface{}) (interface{}, error) {
  439. node_id := tools.IsEmpty(param["node_id"])
  440. if node_id == "" {
  441. return nil, errors.New("节点编号不能为空")
  442. }
  443. node_id_int, _ := strconv.ParseInt(node_id, 10, 64)
  444. scdid := tools.IsEmpty(param["scd_id"])
  445. scdidint64, _ := strconv.ParseInt(scdid, 10, 64)
  446. v_scdcache, _ := GlobalNodeMap.Load(scdidint64)
  447. if v_scdcache == nil {
  448. return nil, errors.New("无效的节点")
  449. }
  450. nodeInfo := v_scdcache.(map[int64]NodeCacheMap)
  451. nodeobj := nodeInfo[node_id_int].ObjAddr
  452. if nodeobj == nil {
  453. return nil, errors.New("无效的节点")
  454. }
  455. return new(node_attr.BaseNode).ToMap(nodeobj), nil
  456. }
  457. //统计指定节点的下级节点类型及数量
  458. func (c *ScdNode) GetChildrenStat(scdid, nodeid string) ([]orm.Params, int, error) {
  459. if scdid == "" {
  460. return nil, 0, errors.New("SCD文件编号不能为空!")
  461. }
  462. if nodeid == "" {
  463. return nil, 0, errors.New("节点编号不能为空!")
  464. }
  465. db := orm.NewOrm()
  466. rowset := []orm.Params{}
  467. sql := "select node_name,count(1) cnt from t_scd_node_scl t where 1=1 and t.scd_id=? and t.parent_node_id=? GROUP BY t.node_name"
  468. sqllog := fmt.Sprintf("SQL:%s,参数:%s,%s", sql, scdid, nodeid)
  469. _, err := db.Raw(sql, scdid, nodeid).Values(&rowset)
  470. if err != nil {
  471. logger.Logger.Error(err, sqllog)
  472. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_datastat, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  473. return rowset, 0, err
  474. }
  475. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_datastat, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  476. return rowset, len(rowset), nil
  477. }
  478. //获取指定accessPoint下的Ldevice节点列表
  479. func (c *ScdNode) GetLdeviceList(scdid, accesspointid string) ([]orm.Params, int, error) {
  480. if scdid == "" {
  481. return nil, 0, errors.New("SCD文件编号不能为空!")
  482. }
  483. if accesspointid == "" {
  484. return nil, 0, errors.New("AccessPoint编号不能为空!")
  485. }
  486. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  487. if serr != nil {
  488. return nil, 0, serr
  489. }
  490. if scdXmlObj == nil {
  491. return nil, 0, errors.New("无效的SCD文件!")
  492. }
  493. rowset := []orm.Params{}
  494. accesspointidInt, _ := strconv.ParseInt(accesspointid, 10, 64)
  495. for _, row := range scdXmlObj.IED {
  496. for _, r1 := range row.AccessPoint {
  497. if r1.Server == nil {
  498. continue
  499. }
  500. if r1.NodeId == accesspointidInt {
  501. for _, r2 := range r1.Server.LDevice {
  502. rowset = append(rowset, orm.Params{
  503. "node_id": r2.NodeId,
  504. "attr_inst": r2.Inst,
  505. "attr_desc": r2.Desc,
  506. })
  507. }
  508. break
  509. }
  510. }
  511. }
  512. return rowset, len(rowset), nil
  513. }
  514. func (c *ScdNode) GetIedByID(sclObj *node_attr.SCL, scdid string, ied_id int64) *node_attr.NIED {
  515. if sclObj == nil {
  516. return nil
  517. }
  518. var masterIed *node_attr.NIED
  519. for _, row := range sclObj.IED {
  520. if row.NodeId == ied_id {
  521. masterIed = row
  522. break
  523. }
  524. }
  525. return masterIed
  526. }
  527. //获取IED
  528. func (c *ScdNode) GetIed(sclObj *node_attr.SCL, scdid string, ied_name string) *node_attr.NIED {
  529. if sclObj == nil {
  530. return nil
  531. }
  532. var masterIed *node_attr.NIED
  533. for _, row := range sclObj.IED {
  534. if row.Name == ied_name {
  535. masterIed = row
  536. break
  537. }
  538. }
  539. return masterIed
  540. }
  541. //获取指定IED节点的关联关系
  542. func (c *ScdNode) GetIedRelations(param map[string]interface{}) (map[string]interface{}, error) {
  543. scdid := tools.IsEmpty(param["scd_id"])
  544. //判断是否需要重新分析关系
  545. //isreset := tools.IsEmpty(param["reset"])
  546. v_iedname := tools.IsEmpty(param["ied_name"])
  547. cacheKey := "GetIedRelations_" + scdid
  548. cacheKey2 := "GetIedRelations_" + scdid + v_iedname
  549. if v_iedname == "" {
  550. if v, h := global.GoCahce.Get(cacheKey); h {
  551. return v.(map[string]interface{}), nil
  552. }
  553. } else {
  554. if v, h := global.GoCahce.Get(cacheKey2); h {
  555. return v.(map[string]interface{}), nil
  556. }
  557. if v, h := global.GoCahce.Get(cacheKey); h {
  558. alldata := v.(map[string]interface{})
  559. result := map[string]interface{}{}
  560. result[v_iedname] = alldata[v_iedname]
  561. return result, nil
  562. }
  563. }
  564. //logger.Logger.Debug(fmt.Sprintf("\n\n加载IED装置%s的关联IED\n", v_iedname))
  565. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  566. if serr != nil {
  567. return nil, serr
  568. }
  569. if scdXmlObj == nil {
  570. return nil, errors.New("无效的SCD")
  571. }
  572. result := map[string]interface{}{}
  573. //ref为1时,查询的是该IED的输入关联IED
  574. //ref为0时,查询的是该iED的输出关联IED
  575. for _, row := range scdXmlObj.IED {
  576. ied_name := row.Name
  577. //查找输入的ied
  578. obj := orm.Params{"desc": row.Desc, "ied_name": row.Name, "node_id": row.NodeId, "list": []orm.Params{}}
  579. tmpAry := map[string]orm.Params{}
  580. for _, alist := range row.AccessPoint {
  581. if alist.Server == nil {
  582. logger.Logger.Error(errors.New(fmt.Sprintf("%s装置中的%s未发现Server定义", ied_name, alist.Name)))
  583. continue
  584. }
  585. for _, ldlist := range alist.Server.LDevice {
  586. if ldlist.LN0.Inputs != nil {
  587. for _, extreflist := range ldlist.LN0.Inputs.ExtRef {
  588. ref_ied_name := extreflist.IedName
  589. if _, h := tmpAry[ref_ied_name]; h {
  590. continue
  591. }
  592. refIedObj := c.GetIed(scdXmlObj, scdid, ref_ied_name)
  593. if refIedObj != nil {
  594. tmpAry[ref_ied_name] = orm.Params{"ied_desc": row.Desc, "ied_name": row.Name, "node_id": row.NodeId, "ref_ied_id": refIedObj.NodeId, "ref_ied_desc": refIedObj.Desc, "ref_ied_name": ref_ied_name, "ref_type": "1"}
  595. }
  596. }
  597. }
  598. }
  599. }
  600. for _, k := range tmpAry {
  601. obj["list"] = append(obj["list"].([]orm.Params), k)
  602. }
  603. //查找输出的ied
  604. tmpAry = map[string]orm.Params{}
  605. for _, outrow := range scdXmlObj.IED {
  606. if ied_name == outrow.Name {
  607. continue
  608. }
  609. for _, alist := range outrow.AccessPoint {
  610. if alist.Server == nil {
  611. logger.Logger.Error(errors.New(fmt.Sprintf("%s装置中的%s未发现Server定义", ied_name, alist.Name)))
  612. continue
  613. }
  614. for _, ldlist := range alist.Server.LDevice {
  615. if ldlist.LN0.Inputs != nil {
  616. for _, extreflist := range ldlist.LN0.Inputs.ExtRef {
  617. ref_ied_name := extreflist.IedName
  618. if ref_ied_name != ied_name {
  619. continue
  620. }
  621. if _, h := tmpAry[outrow.Name]; h {
  622. continue
  623. }
  624. refIedObj := c.GetIed(scdXmlObj, scdid, outrow.Name)
  625. if refIedObj != nil {
  626. tmpAry[outrow.Name] = orm.Params{"ied_desc": row.Desc, "ied_name": row.Name, "node_id": row.NodeId, "ref_ied_id": refIedObj.NodeId, "ref_ied_desc": outrow.Desc, "ref_ied_name": outrow.Name, "ref_type": "0"}
  627. }
  628. }
  629. }
  630. }
  631. }
  632. }
  633. for _, k := range tmpAry {
  634. obj["list"] = append(obj["list"].([]orm.Params), k)
  635. }
  636. result[ied_name] = obj
  637. }
  638. global.GoCahce.Set(cacheKey, result, -1)
  639. if v_iedname != "" {
  640. result2 := map[string]interface{}{}
  641. result2[v_iedname] = result[v_iedname]
  642. global.GoCahce.Set(cacheKey2, result2, -1)
  643. return result2, nil
  644. }
  645. return result, nil
  646. }
  647. //获取指定IED的控制块信息
  648. func (c *ScdNode) GetIedCtrlBlock(scdid int64, iedname string) (map[string]interface{}, error) {
  649. key := fmt.Sprintf("GetIedCtrlBlock_%d_%s", scdid, iedname)
  650. if v, h := global.GoCahce.Get(key); h {
  651. return v.(map[string]interface{}), nil
  652. }
  653. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  654. if serr != nil {
  655. return nil, serr
  656. }
  657. if scdXmlObj == nil {
  658. return nil, errors.New("无效的SCD")
  659. }
  660. var iedObj *node_attr.NIED
  661. for _, row := range scdXmlObj.IED {
  662. if row.Name == iedname {
  663. iedObj = row
  664. break
  665. }
  666. }
  667. if iedObj == nil {
  668. return nil, errors.New("无效的IED装置名称")
  669. }
  670. result := map[string]interface{}{}
  671. gselist := []orm.Params{}
  672. smvlist := []orm.Params{}
  673. for _, row := range iedObj.AccessPoint {
  674. if row.Server == nil {
  675. logger.Logger.Error(errors.New(fmt.Sprintf("%s装置中的%s未发现Server定义", iedObj.Name, row.Name)))
  676. continue
  677. }
  678. for _, ld := range row.Server.LDevice {
  679. ldinst := ld.Inst
  680. if ld.LN0 != nil {
  681. for _, gse := range ld.LN0.GSEControl {
  682. datSetdesc := ""
  683. for _, ds := range ld.LN0.DataSet {
  684. if ds.Name == gse.DatSet {
  685. datSetdesc = ds.Desc
  686. break
  687. }
  688. }
  689. gooseaddress := orm.Params{}
  690. //获取控制块appid
  691. for _, subn := range scdXmlObj.Communication.SubNetwork {
  692. if subn.Type == "IECGOOSE" {
  693. for _, ap := range subn.ConnectedAP {
  694. if ap.IedName == iedObj.Name {
  695. for _, gse1 := range ap.GSE {
  696. if gse1.CbName == gse.Name && gse1.LdInst == ld.Inst {
  697. if gse1.Address != nil {
  698. for _, addrP := range gse1.Address.P {
  699. gooseaddress[strings.ReplaceAll(addrP.Type, "-", "_")] = addrP.InnerText
  700. }
  701. }
  702. break
  703. }
  704. }
  705. break
  706. }
  707. }
  708. break
  709. }
  710. }
  711. gselist = append(gselist, orm.Params{
  712. "attr_appid": gse.AppID,
  713. "attr_dat_set": gse.DatSet,
  714. "attr_name": gse.Name,
  715. "attr_conf_rev": gse.ConfRev,
  716. "attr_desc": "",
  717. "attr_type": gse.Type,
  718. "datset_desc": datSetdesc,
  719. "ldinst": ldinst,
  720. "node_id": gse.NodeId,
  721. "address": gooseaddress,
  722. })
  723. }
  724. for _, sv := range ld.LN0.SampledValueControl {
  725. datSetdesc := ""
  726. //获取控制块数据集信息
  727. for _, ds := range ld.LN0.DataSet {
  728. if ds.Name == sv.DatSet {
  729. datSetdesc = ds.Desc
  730. break
  731. }
  732. }
  733. svaddress := orm.Params{}
  734. //获取控制块appid
  735. for _, subn := range scdXmlObj.Communication.SubNetwork {
  736. if subn.Type == "SMV" {
  737. for _, ap := range subn.ConnectedAP {
  738. if ap.IedName == iedObj.Name {
  739. for _, smv := range ap.SMV {
  740. if smv.CbName == sv.Name && smv.LdInst == ld.Inst {
  741. if smv.Address != nil {
  742. for _, addrP := range smv.Address.P {
  743. svaddress[strings.ReplaceAll(addrP.Type, "-", "_")] = addrP.InnerText
  744. }
  745. }
  746. break
  747. }
  748. }
  749. break
  750. }
  751. }
  752. break
  753. }
  754. }
  755. smvlist = append(smvlist, orm.Params{
  756. "attr_smv_id": sv.SmvID,
  757. "attr_dat_set": sv.DatSet,
  758. "attr_smp_rate": sv.SmpRate,
  759. "attr_name": sv.Name,
  760. "attr_conf_rev": sv.ConfRev,
  761. "attr_desc": "",
  762. "attr_multicast": sv.Multicast,
  763. "datset_desc": datSetdesc,
  764. "ldinst": ldinst,
  765. "attr_nof_asdu": sv.NofASDU,
  766. "node_id": sv.NodeId,
  767. "address": svaddress,
  768. })
  769. }
  770. }
  771. }
  772. }
  773. result["GSEControl"] = gselist
  774. result["SampledValueControl"] = smvlist
  775. global.GoCahce.Set(key, result, -1)
  776. return result, nil
  777. }
  778. //获取指定IED的指定SMV控制块发送端子列表
  779. func (c *ScdNode) GetIedSMVCtrlBlockSendFcdaList(scdid int64, iedname string, ctrl_id int64) ([]orm.Params, error) {
  780. rowset := []orm.Params{}
  781. v_scdcache, _ := GlobalNodeMap.Load(scdid)
  782. if v_scdcache == nil {
  783. return nil, errors.New("无效的节点")
  784. }
  785. scdCacheObj := v_scdcache.(map[int64]NodeCacheMap)
  786. ctrlObj1 := scdCacheObj[ctrl_id]
  787. if ctrlObj1.ObjAddr == nil {
  788. return rowset, errors.New("无效的控制块ID")
  789. }
  790. //获取当前IED的输出IED
  791. relIed, err := c.GetIedRelations(map[string]interface{}{"scd_id": scdid, "ied_name": iedname})
  792. if relIed == nil {
  793. return nil, err
  794. }
  795. ieds0 := relIed[iedname].(orm.Params)
  796. if ieds0 == nil {
  797. return rowset, nil
  798. }
  799. ieds := ieds0["list"].([]orm.Params)
  800. outtoieds := []*node_attr.NIED{}
  801. //获取当前IED输出的目标IED,即ref_type为0的.结果中需要返回输出IED中对应的端子信息
  802. for _, r := range ieds {
  803. if tools.IsEmpty(r["ref_type"]) == "0" {
  804. iedid, _ := strconv.ParseInt(tools.IsEmpty(r["ref_ied_id"]), 10, 64)
  805. tmpIedObj := scdCacheObj[iedid].ObjAddr.(*node_attr.NIED)
  806. if tmpIedObj.Name == iedname {
  807. continue
  808. }
  809. outtoieds = append(outtoieds, tmpIedObj)
  810. }
  811. }
  812. if len(outtoieds) == 0 {
  813. return rowset, nil
  814. }
  815. ctrlObj := ctrlObj1.ObjAddr.(*node_attr.NSampledValueControl)
  816. datasetname := ctrlObj.DatSet
  817. ln0 := scdCacheObj[ctrlObj1.ParentNodeId].ObjAddr.(*node_attr.NLN0)
  818. ldid := scdCacheObj[ctrlObj1.ParentNodeId].ParentNodeId
  819. ld := scdCacheObj[ldid].ObjAddr.(*node_attr.NLDevice)
  820. for _, ds := range ln0.DataSet {
  821. if ds.Name == datasetname {
  822. for _, fcda := range ds.FCDA {
  823. obj := orm.Params{
  824. "do_desc": "",
  825. "do_name": fcda.DoName,
  826. "ld_inst": fcda.LdInst,
  827. "ln_inst": fcda.LnInst,
  828. "ln_class": fcda.LnClass,
  829. "prefix": fcda.Prefix,
  830. "out_intaddr": "",
  831. "out_ied_name": "",
  832. "out_ied_desc": "",
  833. "out_do_desc": "",
  834. }
  835. doi_desc := ""
  836. if fcda.LnClass == "LLN0" {
  837. for _, doi := range ld.LN0.DOI {
  838. if doi.Name == fcda.DoName {
  839. doi_desc = doi.Desc
  840. break
  841. }
  842. }
  843. } else {
  844. for _, ln := range ld.LN {
  845. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  846. for _, doi := range ln.DOI {
  847. if doi.Name == fcda.DoName {
  848. doi_desc = doi.Desc
  849. break
  850. }
  851. }
  852. }
  853. if doi_desc != "" {
  854. break
  855. }
  856. }
  857. }
  858. obj["do_desc"] = doi_desc //内部端子描述
  859. //获取外部信息及端子描述
  860. doi_desc = ""
  861. outFound := false //是否查找到对应的外部端子
  862. out_lns := map[string]*node_attr.NLN{}
  863. for _, ied := range outtoieds {
  864. for _, acc := range ied.AccessPoint {
  865. if acc.Server != nil {
  866. for _, ld := range acc.Server.LDevice {
  867. if ld.LN0.Inputs != nil {
  868. for _, extref := range ld.LN0.Inputs.ExtRef {
  869. if extref.IedName == iedname && extref.DoName == fcda.DoName && extref.LdInst == fcda.LdInst && extref.LnClass == fcda.LnClass && extref.LnInst == fcda.LnInst && extref.Prefix == fcda.Prefix {
  870. outFound = true
  871. obj["out_intaddr"] = extref.IntAddr
  872. obj["out_ied_name"] = ied.Name
  873. obj["out_ied_desc"] = ied.Desc
  874. outLnStr := strings.Split(extref.IntAddr, ".")[0]
  875. outDoName := strings.Split(extref.IntAddr, ".")[1]
  876. var ln *node_attr.NLN
  877. if v, h := out_lns[outLnStr]; h {
  878. ln = v
  879. } else {
  880. //查找内部地址指向的Ln
  881. lnFound := false
  882. for _, tLd := range acc.Server.LDevice {
  883. if extref.LnClass == "LLN0" {
  884. for _, doi := range tLd.LN0.DOI {
  885. if doi.Name == fcda.DoName {
  886. doi_desc = doi.Desc
  887. lnFound = true
  888. break
  889. }
  890. }
  891. }
  892. if doi_desc != "" {
  893. obj["out_do_desc"] = doi_desc
  894. break
  895. }
  896. for _, tLn := range tLd.LN {
  897. if outLnStr == fmt.Sprintf("%s/%s%s%s", tLd.Inst, tLn.Prefix, tLn.LnClass, tLn.Inst) {
  898. out_lns[outLnStr] = tLn
  899. ln = tLn
  900. lnFound = true
  901. break
  902. }
  903. }
  904. if lnFound {
  905. break
  906. }
  907. }
  908. }
  909. if ln == nil {
  910. continue
  911. }
  912. for _, doi := range ln.DOI {
  913. if doi.Name == outDoName {
  914. obj["out_do_desc"] = doi.Desc
  915. break
  916. }
  917. }
  918. break
  919. }
  920. }
  921. }
  922. if outFound {
  923. break
  924. }
  925. }
  926. if outFound {
  927. break
  928. }
  929. }
  930. if outFound {
  931. break
  932. }
  933. }
  934. if outFound {
  935. break
  936. }
  937. }
  938. rowset = append(rowset, obj)
  939. }
  940. break
  941. }
  942. }
  943. return rowset, nil
  944. }
  945. //获取指定IED的SMV接收块及端子列表
  946. func (c *ScdNode) GetIedSMVCtrlBlockRevList(scdid int64, iedname string) ([]orm.Params, error) {
  947. rowset := []orm.Params{}
  948. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  949. if serr != nil {
  950. return nil, serr
  951. }
  952. if scdXmlObj == nil {
  953. return nil, errors.New("无效的SCD")
  954. }
  955. currentIedObj := c.GetIed(scdXmlObj, tools.IsEmpty(scdid), iedname)
  956. if currentIedObj == nil {
  957. return rowset, errors.New("无效的IED装置名称")
  958. }
  959. fromiedObjs := map[string]interface{}{}
  960. for _, acc := range currentIedObj.AccessPoint {
  961. if acc.Server != nil {
  962. for _, ld := range acc.Server.LDevice {
  963. if ld.LN0 != nil && ld.LN0.Inputs != nil {
  964. for _, extref := range ld.LN0.Inputs.ExtRef {
  965. form_ied_name := extref.IedName
  966. var tmpFromIed *node_attr.NIED
  967. if v, h := fromiedObjs[form_ied_name]; h {
  968. tmpFromIed = v.(*node_attr.NIED)
  969. } else {
  970. tmpFromIed = c.GetIed(scdXmlObj, tools.IsEmpty(scdid), form_ied_name)
  971. }
  972. if tmpFromIed == nil {
  973. logger.Logger.Error(fmt.Sprintf("未发现IED装置%s", form_ied_name))
  974. break
  975. }
  976. //获取目标IED的块
  977. iedBlockList, _ := c.GetIedCtrlBlock(scdid, form_ied_name)
  978. //logger.Logger.Debug(fmt.Sprintf("=====%s 装置,extref:%+v", form_ied_name, iedBlockList))
  979. if iedBlockList == nil {
  980. continue
  981. }
  982. smvBlcokList := iedBlockList["SampledValueControl"].([]orm.Params)
  983. if len(smvBlcokList) == 0 {
  984. continue
  985. }
  986. smvDataSetMap := map[string]int{}
  987. for _, smvRow := range smvBlcokList {
  988. smvDataSetMap[tools.IsEmpty(smvRow["attr_dat_set"])] = 1
  989. }
  990. found := false
  991. out_lns := map[string]*node_attr.NLN{}
  992. for _, fromacc := range tmpFromIed.AccessPoint {
  993. if fromacc.Server != nil {
  994. for _, fromld := range fromacc.Server.LDevice {
  995. if fromld.Inst == extref.LdInst {
  996. for _, ds := range fromld.LN0.DataSet {
  997. _, h := smvDataSetMap[ds.Name]
  998. if !h {
  999. continue
  1000. }
  1001. for _, fromfcda := range ds.FCDA {
  1002. if extref.LnClass == fromfcda.LnClass && extref.Prefix == fromfcda.Prefix && extref.LnInst == fromfcda.LnInst && extref.DoName == fromfcda.DoName {
  1003. obj := orm.Params{
  1004. "int_addr": extref.IntAddr,
  1005. "out_do_name": fromfcda.DoName,
  1006. "out_ied_name": tmpFromIed.Name,
  1007. "out_ied_desc": tmpFromIed.Desc,
  1008. "out_dataset_name": ds.Name,
  1009. "out_dataset_desc": ds.Desc,
  1010. "out_smv_ctrl_name": "",
  1011. "out_smv_ctrl_address": "",
  1012. }
  1013. //获取内部信号描述
  1014. doi_desc := ""
  1015. outLnStr := strings.Split(extref.IntAddr, ".")[0]
  1016. outDoName := strings.Split(extref.IntAddr, ".")[1]
  1017. var ln *node_attr.NLN
  1018. if v, h := out_lns[outLnStr]; h {
  1019. ln = v
  1020. } else {
  1021. //查找内部地址指向的Ln
  1022. lnFound := false
  1023. for _, tLd := range acc.Server.LDevice {
  1024. if extref.LnClass == "LLN0" {
  1025. for _, doi := range tLd.LN0.DOI {
  1026. if doi.Name == outDoName {
  1027. doi_desc = doi.Desc
  1028. lnFound = true
  1029. break
  1030. }
  1031. }
  1032. }
  1033. if doi_desc != "" {
  1034. obj["do_desc"] = doi_desc
  1035. break
  1036. }
  1037. for _, tLn := range tLd.LN {
  1038. if outLnStr == fmt.Sprintf("%s/%s%s%s", tLd.Inst, tLn.Prefix, tLn.LnClass, tLn.Inst) {
  1039. out_lns[outLnStr] = tLn
  1040. ln = tLn
  1041. lnFound = true
  1042. break
  1043. }
  1044. }
  1045. if lnFound {
  1046. break
  1047. }
  1048. }
  1049. }
  1050. if ln != nil {
  1051. for _, doi := range ln.DOI {
  1052. if doi.Name == outDoName {
  1053. obj["do_desc"] = doi.Desc
  1054. break
  1055. }
  1056. }
  1057. }
  1058. //获取输入块信息
  1059. for _, smvRow := range smvBlcokList {
  1060. if tools.IsEmpty(smvRow["attr_dat_set"]) == ds.Name {
  1061. obj["out_smv_ctrl_name"] = smvRow["attr_name"]
  1062. obj["out_smv_ctrl_address"] = smvRow["address"]
  1063. break
  1064. }
  1065. }
  1066. doi_desc = ""
  1067. if fromfcda.LnClass == "LLN0" {
  1068. for _, doi := range fromld.LN0.DOI {
  1069. if doi.Name == fromfcda.DoName {
  1070. doi_desc = doi.Desc
  1071. break
  1072. }
  1073. }
  1074. } else {
  1075. for _, ln := range fromld.LN {
  1076. if ln.Inst == fromfcda.LnInst && ln.LnClass == fromfcda.LnClass && ln.Prefix == fromfcda.Prefix {
  1077. for _, doi := range ln.DOI {
  1078. if doi.Name == fromfcda.DoName {
  1079. doi_desc = doi.Desc
  1080. break
  1081. }
  1082. }
  1083. }
  1084. if doi_desc != "" {
  1085. break
  1086. }
  1087. }
  1088. }
  1089. if doi_desc != "" {
  1090. obj["out_do_desc"] = doi_desc
  1091. }
  1092. rowset = append(rowset, obj)
  1093. }
  1094. }
  1095. }
  1096. found = true
  1097. break
  1098. }
  1099. }
  1100. if found {
  1101. break
  1102. }
  1103. }
  1104. }
  1105. }
  1106. }
  1107. }
  1108. }
  1109. }
  1110. return rowset, nil
  1111. }
  1112. //获取指定IED的goose控制块发送端子列表
  1113. func (c *ScdNode) GetIedGooseCtrlBlockSendFcdaList(scdid int64, iedname string, ctrl_id int64) ([]orm.Params, error) {
  1114. rowset := []orm.Params{}
  1115. v_scdcache, _ := GlobalNodeMap.Load(scdid)
  1116. if v_scdcache == nil {
  1117. return nil, errors.New("无效的SCD")
  1118. }
  1119. scdCacheObj := v_scdcache.(map[int64]NodeCacheMap)
  1120. ctrlObj1 := scdCacheObj[ctrl_id]
  1121. if ctrlObj1.ObjAddr == nil {
  1122. return rowset, errors.New("无效的控制块ID")
  1123. }
  1124. //获取当前IED的输出IED
  1125. relIed, err := c.GetIedRelations(map[string]interface{}{"scd_id": scdid, "ied_name": iedname})
  1126. if relIed == nil {
  1127. return nil, err
  1128. }
  1129. ieds0 := relIed[iedname].(orm.Params)
  1130. if ieds0 == nil {
  1131. return rowset, nil
  1132. }
  1133. ieds := ieds0["list"].([]orm.Params)
  1134. outtoieds := []*node_attr.NIED{}
  1135. //获取当前IED输出的目标IED,即ref_type为0的.结果中需要返回输出IED中对应的端子信息
  1136. for _, r := range ieds {
  1137. if tools.IsEmpty(r["ref_type"]) == "0" {
  1138. iedid, _ := strconv.ParseInt(tools.IsEmpty(r["ref_ied_id"]), 10, 64)
  1139. tmpIedObj := scdCacheObj[iedid].ObjAddr.(*node_attr.NIED)
  1140. if tmpIedObj.Name == iedname {
  1141. continue
  1142. }
  1143. outtoieds = append(outtoieds, tmpIedObj)
  1144. }
  1145. }
  1146. if len(outtoieds) == 0 {
  1147. return rowset, nil
  1148. }
  1149. ctrlObj := ctrlObj1.ObjAddr.(*node_attr.NGSEControl)
  1150. datasetname := ctrlObj.DatSet
  1151. ln0 := scdCacheObj[ctrlObj1.ParentNodeId].ObjAddr.(*node_attr.NLN0)
  1152. ldid := scdCacheObj[ctrlObj1.ParentNodeId].ParentNodeId
  1153. ld := scdCacheObj[ldid].ObjAddr.(*node_attr.NLDevice)
  1154. for _, ds := range ln0.DataSet {
  1155. if ds.Name == datasetname {
  1156. for _, fcda := range ds.FCDA {
  1157. obj := orm.Params{
  1158. "do_desc": "",
  1159. "do_name": fcda.DoName,
  1160. "ld_inst": fcda.LdInst,
  1161. "ln_inst": fcda.LnInst,
  1162. "ln_class": fcda.LnClass,
  1163. "prefix": fcda.Prefix,
  1164. "out_intaddr": "",
  1165. "out_ied_name": "",
  1166. "out_ied_desc": "",
  1167. "out_do_desc": "",
  1168. }
  1169. doi_desc := ""
  1170. if fcda.LnClass == "LLN0" {
  1171. for _, doi := range ld.LN0.DOI {
  1172. if doi.Name == fcda.DoName {
  1173. doi_desc = doi.Desc
  1174. break
  1175. }
  1176. }
  1177. } else {
  1178. for _, ln := range ld.LN {
  1179. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  1180. for _, doi := range ln.DOI {
  1181. if doi.Name == fcda.DoName {
  1182. doi_desc = doi.Desc
  1183. break
  1184. }
  1185. }
  1186. }
  1187. if doi_desc != "" {
  1188. break
  1189. }
  1190. }
  1191. }
  1192. obj["do_desc"] = doi_desc //内部端子描述
  1193. //获取外部信息及端子描述
  1194. doi_desc = ""
  1195. outFound := false //是否查找到对应的外部端子
  1196. out_lns := map[string]*node_attr.NLN{}
  1197. for _, ied := range outtoieds {
  1198. for _, acc := range ied.AccessPoint {
  1199. if acc.Server != nil {
  1200. for _, ld := range acc.Server.LDevice {
  1201. if ld.LN0.Inputs != nil {
  1202. for _, extref := range ld.LN0.Inputs.ExtRef {
  1203. if extref.IedName == iedname && extref.DoName == fcda.DoName && extref.LdInst == fcda.LdInst && extref.LnClass == fcda.LnClass && extref.LnInst == fcda.LnInst && extref.Prefix == fcda.Prefix {
  1204. outFound = true
  1205. obj["out_intaddr"] = extref.IntAddr
  1206. obj["out_ied_name"] = ied.Name
  1207. obj["out_ied_desc"] = ied.Desc
  1208. outLnStr := strings.Split(extref.IntAddr, ".")[0]
  1209. ports := strings.Split(outLnStr, ":")
  1210. if len(ports) > 1 {
  1211. outLnStr = ports[1]
  1212. }
  1213. outDoName := strings.Split(extref.IntAddr, ".")[1]
  1214. var ln *node_attr.NLN
  1215. if v, h := out_lns[outLnStr]; h {
  1216. ln = v
  1217. } else {
  1218. //查找内部地址指向的Ln
  1219. lnFound := false
  1220. for _, tLd := range acc.Server.LDevice {
  1221. if extref.LnClass == "LLN0" {
  1222. for _, doi := range tLd.LN0.DOI {
  1223. if doi.Name == fcda.DoName {
  1224. doi_desc = doi.Desc
  1225. lnFound = true
  1226. break
  1227. }
  1228. }
  1229. }
  1230. if doi_desc != "" {
  1231. obj["out_do_desc"] = doi_desc
  1232. break
  1233. }
  1234. for _, tLn := range tLd.LN {
  1235. if outLnStr == fmt.Sprintf("%s/%s%s%s", tLd.Inst, tLn.Prefix, tLn.LnClass, tLn.Inst) {
  1236. out_lns[outLnStr] = tLn
  1237. ln = tLn
  1238. lnFound = true
  1239. break
  1240. }
  1241. }
  1242. if lnFound {
  1243. break
  1244. }
  1245. }
  1246. }
  1247. if ln == nil {
  1248. continue
  1249. }
  1250. for _, doi := range ln.DOI {
  1251. if doi.Name == outDoName {
  1252. obj["out_do_desc"] = doi.Desc
  1253. break
  1254. }
  1255. }
  1256. break
  1257. }
  1258. }
  1259. }
  1260. if outFound {
  1261. break
  1262. }
  1263. }
  1264. if outFound {
  1265. break
  1266. }
  1267. }
  1268. if outFound {
  1269. break
  1270. }
  1271. }
  1272. if outFound {
  1273. break
  1274. }
  1275. }
  1276. rowset = append(rowset, obj)
  1277. }
  1278. break
  1279. }
  1280. }
  1281. return rowset, nil
  1282. }
  1283. //获取指定IED的goose接收块及端子列表
  1284. func (c *ScdNode) GetIedGooseCtrlBlockRevList(scdid int64, iedname string) ([]orm.Params, error) {
  1285. rowset := []orm.Params{}
  1286. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  1287. if serr != nil {
  1288. return nil, serr
  1289. }
  1290. if scdXmlObj == nil {
  1291. return nil, errors.New("无效的SCD")
  1292. }
  1293. currentIedObj := c.GetIed(scdXmlObj, tools.IsEmpty(scdid), iedname)
  1294. if currentIedObj == nil {
  1295. return rowset, errors.New("无效的IED装置名称")
  1296. }
  1297. fromiedObjs := map[string]interface{}{}
  1298. for _, acc := range currentIedObj.AccessPoint {
  1299. if acc.Server != nil {
  1300. for _, ld := range acc.Server.LDevice {
  1301. if ld.LN0 != nil && ld.LN0.Inputs != nil {
  1302. for _, extref := range ld.LN0.Inputs.ExtRef {
  1303. form_ied_name := extref.IedName
  1304. var tmpFromIed *node_attr.NIED
  1305. if v, h := fromiedObjs[form_ied_name]; h {
  1306. tmpFromIed = v.(*node_attr.NIED)
  1307. } else {
  1308. tmpFromIed = c.GetIed(scdXmlObj, tools.IsEmpty(scdid), form_ied_name)
  1309. }
  1310. if tmpFromIed == nil {
  1311. logger.Logger.Error(fmt.Sprintf("未发现IED装置%s", form_ied_name))
  1312. break
  1313. }
  1314. //获取目标IED的块
  1315. iedBlockList, _ := c.GetIedCtrlBlock(scdid, form_ied_name)
  1316. //logger.Logger.Debug(fmt.Sprintf("=====%s 装置,iedBlockList:%+v", form_ied_name, iedBlockList))
  1317. if iedBlockList == nil {
  1318. continue
  1319. }
  1320. smvBlcokList := iedBlockList["GSEControl"].([]orm.Params)
  1321. if len(smvBlcokList) == 0 {
  1322. continue
  1323. }
  1324. gooseDataSetMap := map[string]int{}
  1325. for _, smvRow := range smvBlcokList {
  1326. gooseDataSetMap[tools.IsEmpty(smvRow["attr_dat_set"])] = 1
  1327. }
  1328. found := false
  1329. out_lns := map[string]*node_attr.NLN{}
  1330. for _, fromacc := range tmpFromIed.AccessPoint {
  1331. if fromacc.Server != nil {
  1332. for _, fromld := range fromacc.Server.LDevice {
  1333. if fromld.Inst == extref.LdInst {
  1334. for _, ds := range fromld.LN0.DataSet {
  1335. _, h := gooseDataSetMap[ds.Name]
  1336. if !h {
  1337. continue
  1338. }
  1339. for _, fromfcda := range ds.FCDA {
  1340. if extref.LnClass == fromfcda.LnClass && extref.Prefix == fromfcda.Prefix && extref.LnInst == fromfcda.LnInst && extref.DoName == fromfcda.DoName {
  1341. obj := orm.Params{
  1342. "int_addr": extref.IntAddr,
  1343. "out_do_name": fromfcda.DoName,
  1344. "out_ied_name": tmpFromIed.Name,
  1345. "out_ied_desc": tmpFromIed.Desc,
  1346. "out_dataset_name": ds.Name,
  1347. "out_dataset_desc": ds.Desc,
  1348. "out_gse_ctrl_name": "",
  1349. "out_gse_ctrl_address": "",
  1350. }
  1351. //获取内部信号描述
  1352. doi_desc := ""
  1353. outLnStr := strings.Split(extref.IntAddr, ".")[0]
  1354. outDoName := strings.Split(extref.IntAddr, ".")[1]
  1355. var ln *node_attr.NLN
  1356. if v, h := out_lns[outLnStr]; h {
  1357. ln = v
  1358. } else {
  1359. //查找内部地址指向的Ln
  1360. lnFound := false
  1361. for _, tLd := range acc.Server.LDevice {
  1362. if extref.LnClass == "LLN0" {
  1363. for _, doi := range tLd.LN0.DOI {
  1364. if doi.Name == outDoName {
  1365. doi_desc = doi.Desc
  1366. lnFound = true
  1367. break
  1368. }
  1369. }
  1370. }
  1371. if doi_desc != "" {
  1372. obj["do_desc"] = doi_desc
  1373. break
  1374. }
  1375. for _, tLn := range tLd.LN {
  1376. if outLnStr == fmt.Sprintf("%s/%s%s%s", tLd.Inst, tLn.Prefix, tLn.LnClass, tLn.Inst) {
  1377. out_lns[outLnStr] = tLn
  1378. ln = tLn
  1379. lnFound = true
  1380. break
  1381. }
  1382. }
  1383. if lnFound {
  1384. break
  1385. }
  1386. }
  1387. }
  1388. if ln != nil {
  1389. for _, doi := range ln.DOI {
  1390. if doi.Name == outDoName {
  1391. obj["do_desc"] = doi.Desc
  1392. break
  1393. }
  1394. }
  1395. }
  1396. //获取输入块信息
  1397. for _, smvRow := range smvBlcokList {
  1398. if tools.IsEmpty(smvRow["attr_dat_set"]) == ds.Name {
  1399. obj["out_gse_ctrl_name"] = smvRow["attr_name"]
  1400. obj["out_gse_ctrl_address"] = smvRow["address"]
  1401. break
  1402. }
  1403. }
  1404. doi_desc = ""
  1405. if fromfcda.LnClass == "LLN0" {
  1406. for _, doi := range fromld.LN0.DOI {
  1407. if doi.Name == fromfcda.DoName {
  1408. doi_desc = doi.Desc
  1409. break
  1410. }
  1411. }
  1412. } else {
  1413. for _, ln := range fromld.LN {
  1414. if ln.Inst == fromfcda.LnInst && ln.LnClass == fromfcda.LnClass && ln.Prefix == fromfcda.Prefix {
  1415. for _, doi := range ln.DOI {
  1416. if doi.Name == fromfcda.DoName {
  1417. doi_desc = doi.Desc
  1418. break
  1419. }
  1420. }
  1421. }
  1422. if doi_desc != "" {
  1423. break
  1424. }
  1425. }
  1426. }
  1427. if doi_desc != "" {
  1428. obj["out_do_desc"] = doi_desc
  1429. }
  1430. rowset = append(rowset, obj)
  1431. }
  1432. }
  1433. }
  1434. found = true
  1435. break
  1436. }
  1437. }
  1438. if found {
  1439. break
  1440. }
  1441. }
  1442. }
  1443. }
  1444. }
  1445. }
  1446. }
  1447. }
  1448. return rowset, nil
  1449. }
  1450. //生成指定scd下的ied输入输出关系数据
  1451. func (c *ScdNode) MakeIedRelations(scdid int64, iedname ...string) error {
  1452. db := orm.NewOrm()
  1453. rowset := []orm.Params{}
  1454. v_iedname := ""
  1455. if len(iedname) > 0 {
  1456. v_iedname = iedname[0]
  1457. }
  1458. var err error
  1459. sql := ""
  1460. if v_iedname != "" {
  1461. sql = "select node_id, attr_name from t_scd_ied_attrs where scd_id=? and attr_name=?"
  1462. _, err = db.Raw(sql, scdid, v_iedname).Values(&rowset)
  1463. } else {
  1464. sql = "select node_id, attr_name from t_scd_ied_attrs where scd_id=?"
  1465. _, err = db.Raw(sql, scdid).Values(&rowset)
  1466. }
  1467. sqllog := fmt.Sprintf("SQL:%s,参数:%d,%s", sql, scdid, v_iedname)
  1468. if err != nil {
  1469. logger.Logger.Error(err, sqllog)
  1470. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  1471. return err
  1472. }
  1473. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  1474. if len(rowset) == 0 {
  1475. return errors.New("无效的SCD文件编号")
  1476. }
  1477. //wg := sync.WaitGroup{}
  1478. //wg.Add(len(rowset))
  1479. for _, row := range rowset {
  1480. ied_name := tools.IsEmpty(row["attr_name"])
  1481. iedid := tools.IsEmpty(row["node_id"])
  1482. //go func(iedid, ied_name string) {
  1483. // defer wg.Done()
  1484. // time.Sleep(100 * time.Millisecond)
  1485. //db0 := orm.NewOrm()
  1486. //ref为1时,查询的是该IED的输入关联IED
  1487. //ref为0时,查询的是该iED的输出关联IED
  1488. sql := `insert into t_ied_relation(scd_id,ied_id,ied_name,ref_type,ref_ied_name) select ` + fmt.Sprintf("%d", scdid) + ` scdid, ` + iedid + ` iedid, '` + ied_name + `' iedname, '1' ref, t1.attr_ied_name ied_name from t_scd_node_scl t,t_scd_extref_attrs t1 where t.id =t1.node_id and t.scd_id=? and t1.scd_id=? and t.ied_name=? and t.node_name='ExtRef' GROUP BY t1.attr_ied_name
  1489. union
  1490. select ` + fmt.Sprintf("%d", scdid) + ` scdid, ` + iedid + ` iedid, '` + ied_name + `' iedname,'0' ref, t.ied_name from t_scd_extref_attrs t1,t_scd_node_scl t where t.id=t1.node_id and t.scd_id=? and t1.scd_id=? and t1.attr_ied_name=? GROUP BY t.ied_name`
  1491. _, err = db.Raw(sql, scdid, scdid, ied_name, scdid, scdid, ied_name).Exec()
  1492. sqllog := fmt.Sprintf("SQL:%s,参数:%+v", sql, []interface{}{scdid, scdid, ied_name, scdid, scdid, ied_name})
  1493. if err != nil {
  1494. logger.Logger.Error(err, sqllog)
  1495. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Insert, enum.OptEventType_Bus, enum.OptEventLevel_Hight, sqllog, c.GetUserInfo())
  1496. return err
  1497. }
  1498. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Insert, enum.OptEventType_Bus, enum.OptEventLevel_Hight, sqllog, c.GetUserInfo())
  1499. //}(ied_id, ied_name)
  1500. }
  1501. //wg.Wait()
  1502. return nil
  1503. }
  1504. //获取指定IEd节点的控制块关系
  1505. func (c *ScdNode) GetIedBlockRelations(scdid int64, ied_name string, forcerefresh ...bool) ([]orm.Params, error) {
  1506. if ied_name == "" {
  1507. return nil, errors.New("IEDname不能同时为空")
  1508. }
  1509. if scdid == 0 {
  1510. return nil, errors.New("scd编号不能为空")
  1511. }
  1512. cacheKey := fmt.Sprintf("GetIedBlockRelations_%d_%s", scdid, ied_name)
  1513. if v, h := global.GoCahce.Get(cacheKey); h {
  1514. return v.([]orm.Params), nil
  1515. }
  1516. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  1517. if serr != nil {
  1518. return nil, serr
  1519. }
  1520. if scdXmlObj == nil {
  1521. return nil, errors.New("无效的SCD")
  1522. }
  1523. queryRowset := []orm.Params{}
  1524. var masterIed = c.GetIed(scdXmlObj, tools.IsEmpty(scdid), ied_name)
  1525. if masterIed == nil {
  1526. return nil, errors.New("无效的IED装备名称")
  1527. }
  1528. extreflist, _ := c.GetIedInputsRelations(map[string]interface{}{"ied_name": masterIed.Name, "scd_id": scdid})
  1529. if extreflist == nil || len(extreflist) == 0 {
  1530. return nil, nil
  1531. }
  1532. //缓存每个块关联的详情
  1533. cachebBlockDetail := map[string][]orm.Params{}
  1534. //获取当前IED的控制块,获取输入的IED及块
  1535. inputBlock := map[string]orm.Params{}
  1536. for _, row := range extreflist {
  1537. //"attr_ld_inst","attr_prefix","attr_ln_class","attr_ln_inst","attr_do_name","attr_da_name"
  1538. tmpIedName := tools.IsEmpty(row["ied_name"])
  1539. if tmpIedName == masterIed.Name {
  1540. continue
  1541. }
  1542. if tools.IsEmpty(row["inout_type"]) == "out" {
  1543. //过滤该ied中的输出ExtRef
  1544. continue
  1545. }
  1546. extrefid := row["node_id"]
  1547. ldInst := tools.IsEmpty(row["attr_ld_inst"])
  1548. prefix := tools.IsEmpty(row["attr_prefix"])
  1549. lnClass := tools.IsEmpty(row["attr_ln_class"])
  1550. lnInst := tools.IsEmpty(row["attr_ln_inst"])
  1551. doName := tools.IsEmpty(row["attr_do_name"])
  1552. daName := tools.IsEmpty(row["attr_da_name"])
  1553. inout := tools.IsEmpty(row["inout_type"]) //in:输入当前IED out:输出到其他IED
  1554. inIed := c.GetIed(scdXmlObj, tools.IsEmpty(scdid), tmpIedName)
  1555. if inIed == nil {
  1556. logger.Logger.Error(errors.New(fmt.Sprintf("在scd:中未找到装置%s", scdid, tmpIedName)))
  1557. continue
  1558. }
  1559. if inIed.AccessPoint == nil {
  1560. continue
  1561. }
  1562. for _, t1 := range inIed.AccessPoint {
  1563. if t1.Server == nil {
  1564. continue
  1565. }
  1566. for _, t2 := range t1.Server.LDevice {
  1567. if t2.Inst == ldInst {
  1568. for _, dataset := range t2.LN0.DataSet {
  1569. foundCnt := 0
  1570. isfound := false
  1571. obj := orm.Params{"scd_id": scdid, "master_ied_id": masterIed.NodeId, "master_ied_name": masterIed.Name, "ref_type": "", "inputs_cnt": 0, "out_ld_id": "", "out_ld_inst": "", "out_id_desc": "", "ld_id": "", "ld_inst": "", "id_desc": "", "ctrl_id": "", "ctrl_type": "", "ctrl_name": "", "datset_id": "", "datset_desc": "", "datset_name": ""}
  1572. for _, fcda := range dataset.FCDA {
  1573. if prefix == fcda.Prefix && doName == fcda.DoName && daName == fcda.DaName && fcda.LdInst == ldInst && fcda.LnInst == lnInst && fcda.LnClass == lnClass {
  1574. if foundCnt == 0 {
  1575. obj["ld_id"] = t2.NodeId
  1576. obj["ld_inst"] = t2.Inst
  1577. obj["ld_desc"] = t2.Desc
  1578. obj["datset_id"] = dataset.NodeId
  1579. obj["datset_desc"] = dataset.Desc
  1580. obj["datset_name"] = dataset.Name
  1581. obj["fcda_id"] = fcda.NodeId
  1582. obj["extref_id"] = extrefid
  1583. }
  1584. foundCnt = foundCnt + 1 //计算关联的端子数量
  1585. isfound = true
  1586. break
  1587. }
  1588. }
  1589. obj["inputs_cnt"] = foundCnt
  1590. if isfound {
  1591. datasetName := tools.IsEmpty(obj["datset_name"])
  1592. //获取控制块信息
  1593. for _, gse := range t2.LN0.GSEControl {
  1594. if gse.DatSet == datasetName {
  1595. obj["ctrl_id"] = gse.NodeId
  1596. obj["ctrl_type"] = gse.Type
  1597. obj["ctrl_name"] = gse.Name
  1598. }
  1599. }
  1600. for _, smv := range t2.LN0.SampledValueControl {
  1601. if smv.DatSet == datasetName {
  1602. obj["ctrl_id"] = smv.NodeId
  1603. obj["ctrl_type"] = "smv"
  1604. obj["ctrl_name"] = smv.Name
  1605. }
  1606. }
  1607. obj["ref_type"] = "1"
  1608. obj["inout_type"] = inout
  1609. obj["source_ied_id"] = masterIed.NodeId
  1610. obj["source_ied_name"] = masterIed.Name
  1611. obj["target_ied_id"] = inIed.NodeId
  1612. obj["target_ied_name"] = tmpIedName
  1613. obj["out_ld_id"] = t2.NodeId
  1614. obj["out_ld_desc"] = t2.Desc
  1615. obj["out_ld_inst"] = t2.Inst
  1616. key := fmt.Sprintf("%d%s%s%d", scdid, masterIed.Name, tmpIedName, obj["ctrl_id"])
  1617. if v, h := inputBlock[key]; h {
  1618. v1, _ := strconv.Atoi(tools.IsEmpty(v["inputs_cnt"]))
  1619. v["inputs_cnt"] = v1 + 1
  1620. inputBlock[key] = v
  1621. cachebBlockDetail[key] = append(cachebBlockDetail[key], obj)
  1622. } else {
  1623. //queryRowset = append(queryRowset, obj)
  1624. inputBlock[key] = obj
  1625. cachebBlockDetail[key] = []orm.Params{obj}
  1626. }
  1627. }
  1628. }
  1629. }
  1630. }
  1631. }
  1632. }
  1633. for _, r := range inputBlock {
  1634. queryRowset = append(queryRowset, r)
  1635. }
  1636. //获取关联IED的控制块,获取输出的IED及块
  1637. inputBlock = map[string]orm.Params{}
  1638. relIedlist, _ := c.GetIedRelations(map[string]interface{}{"scd_id": scdid, "ied_name": masterIed.Name})
  1639. if relIedlist != nil {
  1640. relIedlist = relIedlist[masterIed.Name].(orm.Params)
  1641. vList := relIedlist["list"].([]orm.Params)
  1642. for _, refIed := range vList {
  1643. if refIed["ref_ied_name"] == nil {
  1644. continue
  1645. }
  1646. if refIed["ref_type"] == "1" {
  1647. //输入IED
  1648. continue
  1649. }
  1650. tmpIedName := refIed["ref_ied_name"].(string)
  1651. extreflist, _ := c.GetIedInputsRelations(map[string]interface{}{"ied_name": tmpIedName, "scd_id": scdid})
  1652. if extreflist == nil || len(extreflist) == 0 {
  1653. continue
  1654. }
  1655. for _, extref := range extreflist {
  1656. if tools.IsEmpty(extref["inout_type"]) == "out" {
  1657. //过滤该ied中的输出ExtRef
  1658. continue
  1659. }
  1660. toIedName := tools.IsEmpty(extref["ied_name"])
  1661. if toIedName != masterIed.Name {
  1662. //过虑输入ied非当前查询ied的extref
  1663. continue
  1664. }
  1665. extrefid := extref["node_id"]
  1666. ldInst := tools.IsEmpty(extref["attr_ld_inst"])
  1667. prefix := tools.IsEmpty(extref["attr_prefix"])
  1668. lnClass := tools.IsEmpty(extref["attr_ln_class"])
  1669. lnInst := tools.IsEmpty(extref["attr_ln_inst"])
  1670. doName := tools.IsEmpty(extref["attr_do_name"])
  1671. daName := tools.IsEmpty(extref["attr_da_name"])
  1672. inout := tools.IsEmpty(extref["inout_type"]) //in:输入当前IED out:输出到其他IED
  1673. inIed := masterIed //c.GetIed(scdXmlObj, tools.IsEmpty(scdid), tmpIedName)
  1674. if inIed.AccessPoint == nil {
  1675. continue
  1676. }
  1677. for _, t1 := range inIed.AccessPoint {
  1678. if t1.Server == nil {
  1679. continue
  1680. }
  1681. for _, t2 := range t1.Server.LDevice {
  1682. //logger.Logger.Debug(fmt.Sprintf("%s LDevice%+v:", tmpIedName, t2.Desc))
  1683. for _, dataset := range t2.LN0.DataSet {
  1684. foundCnt := 0
  1685. isfound := false
  1686. obj := orm.Params{"scd_id": scdid, "master_ied_id": masterIed.NodeId, "master_ied_name": masterIed.Name, "ref_type": "", "inputs_cnt": 0, "out_ld_id": "", "out_ld_inst": "", "out_id_desc": "", "ld_id": "", "ld_inst": "", "id_desc": "", "ctrl_id": "", "ctrl_type": "", "ctrl_name": "", "datset_id": "", "datset_desc": "", "datset_name": ""}
  1687. for _, fcda := range dataset.FCDA {
  1688. if prefix == fcda.Prefix && doName == fcda.DoName && daName == fcda.DaName && fcda.LdInst == ldInst && fcda.LnInst == lnInst && fcda.LnClass == lnClass {
  1689. if foundCnt == 0 {
  1690. obj["ld_id"] = t2.NodeId
  1691. obj["ld_inst"] = t2.Inst
  1692. obj["ld_desc"] = t2.Desc
  1693. obj["datset_id"] = dataset.NodeId
  1694. obj["datset_desc"] = dataset.Desc
  1695. obj["datset_name"] = dataset.Name
  1696. obj["fcda_id"] = fcda.NodeId
  1697. obj["extref_id"] = extrefid
  1698. }
  1699. foundCnt = foundCnt + 1 //计算关联的端子数量
  1700. isfound = true
  1701. break
  1702. }
  1703. }
  1704. obj["inputs_cnt"] = foundCnt
  1705. if isfound {
  1706. datasetName := tools.IsEmpty(obj["datset_name"])
  1707. //获取控制块信息
  1708. for _, gse := range t2.LN0.GSEControl {
  1709. if gse.DatSet == datasetName {
  1710. obj["ctrl_id"] = gse.NodeId
  1711. obj["ctrl_type"] = gse.Type
  1712. obj["ctrl_name"] = gse.Name
  1713. }
  1714. }
  1715. for _, smv := range t2.LN0.SampledValueControl {
  1716. if smv.DatSet == datasetName {
  1717. obj["ctrl_id"] = smv.NodeId
  1718. obj["ctrl_type"] = "smv"
  1719. obj["ctrl_name"] = smv.Name
  1720. }
  1721. }
  1722. obj["ref_type"] = "0"
  1723. obj["source_ied_id"] = inIed.NodeId
  1724. obj["source_ied_name"] = tmpIedName
  1725. obj["target_ied_id"] = masterIed.NodeId
  1726. obj["target_ied_name"] = masterIed.Name
  1727. obj["out_ld_id"] = t2.NodeId
  1728. obj["out_ld_desc"] = t2.Desc
  1729. obj["out_ld_inst"] = t2.Inst
  1730. obj["inout_type"] = inout
  1731. key := fmt.Sprintf("%d%s%s%d", scdid, masterIed.Name, tmpIedName, obj["ctrl_id"])
  1732. if v, h := inputBlock[key]; h {
  1733. v1, _ := strconv.Atoi(tools.IsEmpty(v["inputs_cnt"]))
  1734. v["inputs_cnt"] = v1 + 1
  1735. inputBlock[key] = v
  1736. cachebBlockDetail[key] = append(cachebBlockDetail[key], obj)
  1737. } else {
  1738. //queryRowset = append(queryRowset, obj)
  1739. inputBlock[key] = obj
  1740. cachebBlockDetail[key] = []orm.Params{obj}
  1741. }
  1742. }
  1743. }
  1744. }
  1745. }
  1746. }
  1747. }
  1748. }
  1749. for _, r := range inputBlock {
  1750. queryRowset = append(queryRowset, r)
  1751. }
  1752. mqtt.PublishMessage("/jujutong/scd_check_tools/iedblockrelations/"+tools.IsEmpty(scdid)+"/"+ied_name, `{"ied_name":"`+ied_name+`","code":1}`)
  1753. //缓存块关联详情
  1754. global.GoCahce.Set(fmt.Sprintf("cachebBlockDetail_%d", scdid), cachebBlockDetail, -1)
  1755. return queryRowset, nil
  1756. }
  1757. //获取指定IED节点的虚端子关系
  1758. func (c *ScdNode) GetIedInputsRelations(param map[string]interface{}) ([]orm.Params, error) {
  1759. iedid := tools.IsEmpty(param["ied_id"])
  1760. ied_name := tools.IsEmpty(param["ied_name"])
  1761. if iedid == "" && ied_name == "" {
  1762. return nil, errors.New("IED编号和name不能同时为空")
  1763. }
  1764. scdid := tools.IsEmpty(param["scd_id"])
  1765. if scdid == "" {
  1766. return nil, errors.New("scd编号不能为空")
  1767. }
  1768. cacheKey1 := "GetIedInputsRelations_" + scdid + ied_name
  1769. if v, h := global.GoCahce.Get(cacheKey1); h {
  1770. return v.([]orm.Params), nil
  1771. }
  1772. scdobj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  1773. if serr != nil {
  1774. return nil, serr
  1775. }
  1776. if scdobj == nil {
  1777. return nil, errors.New("该scd还未解析或解析未完成!")
  1778. }
  1779. if iedid != "" {
  1780. has := false
  1781. for _, item := range scdobj.IED {
  1782. if tools.IsEmpty(item.NodeId) == iedid {
  1783. has = true
  1784. ied_name = item.Name
  1785. break
  1786. }
  1787. }
  1788. if !has {
  1789. return nil, errors.New("无效的IED编号")
  1790. }
  1791. }
  1792. attrsrows := []orm.Params{} //input输入输出虚端子关系
  1793. for _, item := range scdobj.IED {
  1794. for _, accpointitem := range item.AccessPoint {
  1795. if accpointitem.Server == nil {
  1796. continue
  1797. }
  1798. for _, lditem := range accpointitem.Server.LDevice {
  1799. if lditem.LN0.Inputs == nil {
  1800. continue
  1801. }
  1802. no := 0
  1803. for _, extrefitem := range lditem.LN0.Inputs.ExtRef {
  1804. no = no + 1
  1805. inout := ""
  1806. tmpIedName := ""
  1807. doinDesc := ""
  1808. dooutDesc := ""
  1809. if item.Name == ied_name {
  1810. inout = "in"
  1811. tmpIedName = extrefitem.IedName
  1812. //获取内部地址的描述
  1813. _, _, doinDesc = c.GetIntAddrDesc(item, extrefitem.IntAddr)
  1814. fcda_addr := fmt.Sprintf("%s/%s%s%s.%s", extrefitem.LdInst, extrefitem.Prefix, extrefitem.LnClass, extrefitem.LnInst, extrefitem.DoName)
  1815. if extrefitem.DaName != "" {
  1816. fcda_addr = fcda_addr + "." + extrefitem.DaName
  1817. }
  1818. extrefIed := c.GetIed(scdobj, scdid, tmpIedName)
  1819. _, _, dooutDesc = c.GetIntAddrDesc(extrefIed, fcda_addr)
  1820. } else if extrefitem.IedName == ied_name {
  1821. inout = "out"
  1822. tmpIedName = item.Name
  1823. _, _, doinDesc = c.GetIntAddrDesc(item, extrefitem.IntAddr)
  1824. //获取fcda的描述
  1825. fcda_addr := fmt.Sprintf("%s/%s%s%s.%s", extrefitem.LdInst, extrefitem.Prefix, extrefitem.LnClass, extrefitem.LnInst, extrefitem.DoName)
  1826. if extrefitem.DaName != "" {
  1827. fcda_addr = fcda_addr + "." + extrefitem.DaName
  1828. }
  1829. mIed := c.GetIed(scdobj, scdid, ied_name)
  1830. _, _, dooutDesc = c.GetIntAddrDesc(mIed, fcda_addr)
  1831. } else {
  1832. continue
  1833. }
  1834. v_o := orm.Params{
  1835. "no": no,
  1836. "inout_type": inout,
  1837. "ied_name": tmpIedName,
  1838. "node_id": extrefitem.NodeId,
  1839. "attr_ld_inst": extrefitem.LdInst,
  1840. "attr_prefix": extrefitem.Prefix,
  1841. "attr_ln_class": extrefitem.LnClass,
  1842. "attr_ln_inst": extrefitem.LnInst,
  1843. "attr_do_name": extrefitem.DoName,
  1844. "attr_da_name": extrefitem.DaName,
  1845. "attr_int_addr": extrefitem.IntAddr,
  1846. "line_no": extrefitem.Lineno,
  1847. "do_target_desc": doinDesc,
  1848. "do_source_desc": dooutDesc,
  1849. }
  1850. attrsrows = append(attrsrows, v_o)
  1851. }
  1852. }
  1853. }
  1854. }
  1855. //logger.Logger.Debug(fmt.Sprintf("ied_name:%s attrsrows:%+v", ied_name, attrsrows))
  1856. global.GoCahce.Set(cacheKey1, attrsrows, -1)
  1857. return attrsrows, nil
  1858. }
  1859. //获取指定IED节点及控制块ID的虚端子关系
  1860. func (c *ScdNode) GetIedCtrlInputsRelations(param map[string]interface{}) ([]orm.Params, error) {
  1861. m_ied_name := tools.IsEmpty(param["m_ied_name"])
  1862. if m_ied_name == "" {
  1863. return nil, errors.New("源IED name不能为空")
  1864. }
  1865. s_ied_name := tools.IsEmpty(param["s_ied_name"])
  1866. if s_ied_name == "" {
  1867. return nil, errors.New("目标IED name不能为空")
  1868. }
  1869. scdid := tools.IsEmpty(param["scd_id"])
  1870. if scdid == "" {
  1871. return nil, errors.New("scd编号不能为空")
  1872. }
  1873. scdidint64, _ := strconv.ParseInt(scdid, 10, 64)
  1874. //缓存块关联详情
  1875. cachebBlockDetail, _ := global.GoCahce.Get(fmt.Sprintf("cachebBlockDetail_%s", scdid))
  1876. if cachebBlockDetail == nil {
  1877. return nil, errors.New("未查询到数据")
  1878. }
  1879. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  1880. if serr != nil {
  1881. return nil, serr
  1882. }
  1883. if scdXmlObj == nil {
  1884. return nil, errors.New("无效的SCD")
  1885. }
  1886. m_ctrlid := tools.IsEmpty(param["m_ctrlid"])
  1887. s_ctrlid := tools.IsEmpty(param["s_ctrlid"])
  1888. key := fmt.Sprintf("%s%s%s%s%s", scdid, m_ied_name, s_ied_name, m_ctrlid, s_ctrlid)
  1889. cachebBlockDetailMap := cachebBlockDetail.(map[string][]orm.Params)
  1890. //logger.Logger.Debug(fmt.Sprintf("获取指定IED节点及控制块ID的虚端子关系:%s\n%+v", key, cachebBlockDetailMap))
  1891. attrsrows := cachebBlockDetailMap[key]
  1892. //返回数据:id,fcda_id as node_id,from_doi_desc,from_ied,from_ln_desc,to_doi_desc,to_ied,to_ln_desc,attr_ld_inst,attr_ln_class,attr_ln_inst,attr_prefix,attr_ix,attr_int_addr,attr_fc,attr_do_name,attr_da_name
  1893. rowset := []orm.Params{}
  1894. v_scdcache, _ := GlobalNodeMap.Load(scdidint64)
  1895. if v_scdcache == nil {
  1896. return nil, errors.New("无效的SCD")
  1897. }
  1898. cacheNodeList := v_scdcache.(map[int64]NodeCacheMap)
  1899. mIed := new(ScdNode).GetIed(scdXmlObj, scdid, m_ied_name)
  1900. sIed := new(ScdNode).GetIed(scdXmlObj, scdid, s_ied_name)
  1901. fmt.Println("=======attrsrows:" + fmt.Sprintf("%+v", attrsrows))
  1902. for _, row := range attrsrows {
  1903. obj := orm.Params{}
  1904. ln_desc := ""
  1905. doi_desc := ""
  1906. extrefid := tools.IsEmpty(row["extref_id"])
  1907. fcdaid := tools.IsEmpty(row["fcda_id"])
  1908. target_ied_name := tools.IsEmpty(row["target_ied_name"])
  1909. master_ied_name := tools.IsEmpty(row["master_ied_name"])
  1910. if m_ctrlid != "" && master_ied_name == m_ied_name {
  1911. fcdaidint64, _ := strconv.ParseInt(fcdaid, 10, 64)
  1912. //主IED向外输出,根据主IED的fcda查找from_doi等信息
  1913. nodeInfo := cacheNodeList[fcdaidint64]
  1914. if nodeInfo.ObjAddr != nil {
  1915. fcda := nodeInfo.ObjAddr.(*node_attr.NFCDA)
  1916. //logger.Logger.Debug(fmt.Sprintf("fcda %s info:%+v", fcdaid, fcda))
  1917. obj["node_id"] = fcda.NodeId
  1918. obj["attr_ld_inst"] = fcda.LdInst
  1919. obj["attr_ln_class"] = fcda.LnClass
  1920. obj["attr_ln_inst"] = fcda.LnInst
  1921. obj["attr_prefix"] = fcda.Prefix
  1922. obj["attr_ix"] = fcda.Ix
  1923. obj["attr_fc"] = fcda.Fc
  1924. obj["attr_do_name"] = fcda.DoName
  1925. obj["attr_da_name"] = fcda.DaName
  1926. var ld *node_attr.NLDevice
  1927. ld, ln_desc, doi_desc = c.GetFcdaDesc(mIed, fcda)
  1928. if ld != nil {
  1929. obj["attr_ld_desc"] = ld.Desc
  1930. }
  1931. /*
  1932. for _, ied := range mIed.AccessPoint {
  1933. if ied.Server != nil {
  1934. for _, ld := range ied.Server.LDevice {
  1935. //logger.Logger.Debug(fmt.Sprintf(" ld========%s=============%s", ld.Inst, fcda.LdInst))
  1936. if ld.Inst == fcda.LdInst {
  1937. obj["attr_ld_desc"] = ld.Desc
  1938. if fcda.LnClass == "LLN0" {
  1939. ln_desc = ld.LN0.Desc
  1940. for _, doi := range ld.LN0.DOI {
  1941. if doi.Name == fcda.DoName {
  1942. doi_desc = doi.Desc
  1943. break
  1944. }
  1945. }
  1946. break
  1947. }
  1948. for _, ln := range ld.LN {
  1949. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  1950. ln_desc = ln.Desc
  1951. //logger.Logger.Debug(fmt.Sprintf(" LN=====================%+v", ln))
  1952. for _, doi := range ln.DOI {
  1953. if doi.Name == fcda.DoName {
  1954. doi_desc = doi.Desc
  1955. break
  1956. }
  1957. }
  1958. }
  1959. if doi_desc != "" {
  1960. break
  1961. }
  1962. }
  1963. }
  1964. if doi_desc != "" {
  1965. break
  1966. }
  1967. }
  1968. }
  1969. if doi_desc != "" {
  1970. break
  1971. }
  1972. }
  1973. */
  1974. }
  1975. obj["from_doi_desc"] = doi_desc
  1976. obj["from_ln_desc"] = ln_desc
  1977. //主IED向外输出,根据接收IED的extref的内部地址查找to_doi等信息
  1978. extrefidint64, _ := strconv.ParseInt(extrefid, 10, 64)
  1979. nodeInfo = cacheNodeList[extrefidint64]
  1980. ln_desc = ""
  1981. doi_desc = ""
  1982. var ld *node_attr.NLDevice
  1983. if nodeInfo.ObjAddr != nil {
  1984. extref := nodeInfo.ObjAddr.(*node_attr.NExtRef)
  1985. //logger.Logger.Debug(fmt.Sprintf("extref %s info:%+v", extrefid, extref))
  1986. obj["attr_int_addr"] = extref.IntAddr
  1987. ld, ln_desc, doi_desc = c.GetIntAddrDesc(sIed, extref.IntAddr)
  1988. if ld != nil {
  1989. obj["to_ld_inst"] = ld.Inst
  1990. obj["to_ld_desc"] = ld.Desc
  1991. }
  1992. /*
  1993. addrparts := strings.Split(extref.IntAddr, "/")
  1994. to_ldinst := addrparts[0]
  1995. //to_lnPri := addrparts[1] //ln标识符,由prefix+lnClass+inst.doname.daname组成
  1996. to_lnPriParts := strings.Split(addrparts[1], ".")
  1997. to_doname := to_lnPriParts[1]
  1998. for _, ied := range sIed.AccessPoint {
  1999. if ied.Server != nil {
  2000. for _, ld := range ied.Server.LDevice {
  2001. if ld.Inst == to_ldinst {
  2002. obj["to_ld_inst"] = ld.Inst
  2003. obj["to_ld_desc"] = ld.Desc
  2004. for _, ln := range ld.LN {
  2005. //logger.Logger.Debug(fmt.Sprintf("to: %s==%s", ln.Prefix+ln.LnClass+ln.Inst, to_lnPriParts[0]))
  2006. if (ln.Prefix + ln.LnClass + ln.Inst) == to_lnPriParts[0] {
  2007. ln_desc = ln.Desc
  2008. for _, doi := range ln.DOI {
  2009. if doi.Name == to_doname {
  2010. doi_desc = doi.Desc
  2011. break
  2012. }
  2013. }
  2014. }
  2015. if doi_desc != "" {
  2016. break
  2017. }
  2018. }
  2019. }
  2020. if doi_desc != "" {
  2021. break
  2022. }
  2023. }
  2024. }
  2025. if doi_desc != "" {
  2026. break
  2027. }
  2028. }
  2029. */
  2030. }
  2031. obj["to_doi_desc"] = doi_desc
  2032. obj["to_ln_desc"] = ln_desc
  2033. rowset = append(rowset, obj)
  2034. }
  2035. if s_ctrlid != "" && target_ied_name == s_ied_name {
  2036. //向主IED输入
  2037. fcdaidint64, _ := strconv.ParseInt(fcdaid, 10, 64)
  2038. //主IED向外输出,根据主IED的fcda查找from_doi等信息
  2039. nodeInfo := cacheNodeList[fcdaidint64]
  2040. if nodeInfo.ObjAddr != nil {
  2041. fcda := nodeInfo.ObjAddr.(*node_attr.NFCDA)
  2042. fmt.Println(fmt.Sprintf("fcda id:%d,fcda info:%+v", fcdaidint64, fcda))
  2043. //logger.Logger.Debug(fmt.Sprintf("fcda %s info:%+v", fcdaid, fcda))
  2044. obj["node_id"] = fcda.NodeId
  2045. obj["attr_ld_inst"] = fcda.LdInst
  2046. obj["attr_ln_class"] = fcda.LnClass
  2047. obj["attr_ln_inst"] = fcda.LnInst
  2048. obj["attr_prefix"] = fcda.Prefix
  2049. obj["attr_ix"] = fcda.Ix
  2050. obj["attr_fc"] = fcda.Fc
  2051. obj["attr_do_name"] = fcda.DoName
  2052. obj["attr_da_name"] = fcda.DaName
  2053. var ld *node_attr.NLDevice
  2054. ld, ln_desc, doi_desc = c.GetFcdaDesc(sIed, fcda)
  2055. if ld != nil {
  2056. obj["attr_ld_desc"] = ld.Desc
  2057. }
  2058. /*
  2059. for _, ied := range sIed.AccessPoint {
  2060. if ied.Server != nil {
  2061. for _, ld := range ied.Server.LDevice {
  2062. //logger.Logger.Debug(fmt.Sprintf(" ld========%s=============%s", ld.Inst, fcda.LdInst))
  2063. if ld.Inst == fcda.LdInst {
  2064. obj["attr_ld_desc"] = ld.Desc
  2065. if fcda.LnClass == "LLN0" {
  2066. ln_desc = ld.LN0.Desc
  2067. for _, doi := range ld.LN0.DOI {
  2068. if doi.Name == fcda.DoName {
  2069. doi_desc = doi.Desc
  2070. break
  2071. }
  2072. }
  2073. break
  2074. }
  2075. for _, ln := range ld.LN {
  2076. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  2077. ln_desc = ln.Desc
  2078. //logger.Logger.Debug(fmt.Sprintf(" LN=====================%+v", ln))
  2079. for _, doi := range ln.DOI {
  2080. if doi.Name == fcda.DoName {
  2081. doi_desc = doi.Desc
  2082. break
  2083. }
  2084. }
  2085. }
  2086. if doi_desc != "" {
  2087. break
  2088. }
  2089. }
  2090. }
  2091. if doi_desc != "" {
  2092. break
  2093. }
  2094. }
  2095. }
  2096. if doi_desc != "" {
  2097. break
  2098. }
  2099. }
  2100. */
  2101. }
  2102. obj["from_doi_desc"] = doi_desc
  2103. obj["from_ln_desc"] = ln_desc
  2104. //主IED向外输出,根据接收IED的extref的内部地址查找to_doi等信息
  2105. extrefidint64, _ := strconv.ParseInt(extrefid, 10, 64)
  2106. nodeInfo = cacheNodeList[extrefidint64]
  2107. ln_desc = ""
  2108. doi_desc = ""
  2109. var ld *node_attr.NLDevice
  2110. if nodeInfo.ObjAddr != nil {
  2111. extref := nodeInfo.ObjAddr.(*node_attr.NExtRef)
  2112. //logger.Logger.Debug(fmt.Sprintf("extref %s info:%+v", extrefid, extref))
  2113. obj["attr_int_addr"] = extref.IntAddr
  2114. ld, ln_desc, doi_desc = c.GetIntAddrDesc(mIed, extref.IntAddr)
  2115. if ld != nil {
  2116. obj["to_ld_inst"] = ld.Inst
  2117. obj["to_ld_desc"] = ld.Desc
  2118. }
  2119. /*
  2120. addrparts := strings.Split(extref.IntAddr, "/")
  2121. to_ldinst := addrparts[0]
  2122. //to_lnPri := addrparts[1] //ln标识符,由prefix+lnClass+inst.doname.daname组成
  2123. to_lnPriParts := strings.Split(addrparts[1], ".")
  2124. to_doname := to_lnPriParts[1]
  2125. for _, ied := range mIed.AccessPoint {
  2126. if ied.Server != nil {
  2127. for _, ld := range ied.Server.LDevice {
  2128. if ld.Inst == to_ldinst {
  2129. obj["to_ld_inst"] = ld.Inst
  2130. obj["to_ld_desc"] = ld.Desc
  2131. for _, ln := range ld.LN {
  2132. //logger.Logger.Debug(fmt.Sprintf("to: %s==%s", ln.Prefix+ln.LnClass+ln.Inst, to_lnPriParts[0]))
  2133. if (ln.Prefix + ln.LnClass + ln.Inst) == to_lnPriParts[0] {
  2134. ln_desc = ln.Desc
  2135. for _, doi := range ln.DOI {
  2136. if doi.Name == to_doname {
  2137. doi_desc = doi.Desc
  2138. break
  2139. }
  2140. }
  2141. }
  2142. if doi_desc != "" {
  2143. break
  2144. }
  2145. }
  2146. }
  2147. if doi_desc != "" {
  2148. break
  2149. }
  2150. }
  2151. }
  2152. if doi_desc != "" {
  2153. break
  2154. }
  2155. }*/
  2156. }
  2157. obj["to_doi_desc"] = doi_desc
  2158. obj["to_ln_desc"] = ln_desc
  2159. rowset = append(rowset, obj)
  2160. }
  2161. }
  2162. return rowset, nil
  2163. }
  2164. //获取指定FCDA的do或者Da描述
  2165. func (c *ScdNode) GetFcdaDesc(mIed *node_attr.NIED, fcda *node_attr.NFCDA) (rld *node_attr.NLDevice, lndesc string, dodesc string) {
  2166. doi_desc := ""
  2167. ln_desc := ""
  2168. if mIed == nil || fcda == nil {
  2169. return nil, ln_desc, doi_desc
  2170. }
  2171. doParts := strings.Split(fcda.DoName, ".") //拆分do中的有效name部分
  2172. to_doname := doParts[0]
  2173. for _, ied := range mIed.AccessPoint {
  2174. if ied.Server != nil {
  2175. for _, ld := range ied.Server.LDevice {
  2176. //logger.Logger.Debug(fmt.Sprintf(" ld========%s=============%s", ld.Inst, fcda.LdInst))
  2177. if ld.Inst == fcda.LdInst {
  2178. rld = ld
  2179. if fcda.LnClass == "LLN0" {
  2180. ln_desc = ld.LN0.Desc
  2181. for _, doi := range ld.LN0.DOI {
  2182. if doi.Name == to_doname {
  2183. doi_desc = doi.Desc
  2184. break
  2185. }
  2186. }
  2187. break
  2188. }
  2189. for _, ln := range ld.LN {
  2190. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  2191. ln_desc = ln.Desc
  2192. //logger.Logger.Debug(fmt.Sprintf(" LN=====================%+v", ln))
  2193. for _, doi := range ln.DOI {
  2194. if doi.Name == to_doname {
  2195. doi_desc = doi.Desc
  2196. break
  2197. }
  2198. }
  2199. }
  2200. if doi_desc != "" {
  2201. break
  2202. }
  2203. }
  2204. }
  2205. if doi_desc != "" {
  2206. break
  2207. }
  2208. }
  2209. }
  2210. if doi_desc != "" {
  2211. break
  2212. }
  2213. }
  2214. return rld, ln_desc, doi_desc
  2215. }
  2216. //获取指定Extref的本地描述
  2217. func (c *ScdNode) GetIntAddrDesc(mIed *node_attr.NIED, intAddr string) (rld *node_attr.NLDevice, lndesc string, dodesc string) {
  2218. doi_desc := ""
  2219. ln_desc := ""
  2220. if mIed == nil || intAddr == "" {
  2221. return nil, ln_desc, doi_desc
  2222. }
  2223. addrs := strings.Split(intAddr, ":")
  2224. if len(addrs) == 2 {
  2225. intAddr = addrs[1]
  2226. }
  2227. addrparts := strings.Split(intAddr, "/")
  2228. to_ldinst := addrparts[0]
  2229. //addrparts[1] //ln标识符,由prefix+lnClass+inst.doname.daname组成
  2230. to_lnPriParts := strings.Split(addrparts[1], ".")
  2231. to_doname := to_lnPriParts[1]
  2232. for _, ied := range mIed.AccessPoint {
  2233. if ied.Server != nil {
  2234. for _, ld := range ied.Server.LDevice {
  2235. if ld.Inst == to_ldinst {
  2236. rld = ld
  2237. for _, ln := range ld.LN {
  2238. //logger.Logger.Debug(fmt.Sprintf("to: %s==%s", ln.Prefix+ln.LnClass+ln.Inst, to_lnPriParts[0]))
  2239. if (ln.Prefix + ln.LnClass + ln.Inst) == to_lnPriParts[0] {
  2240. ln_desc = ln.Desc
  2241. for _, doi := range ln.DOI {
  2242. if doi.Name == to_doname {
  2243. doi_desc = doi.Desc
  2244. break
  2245. }
  2246. }
  2247. }
  2248. if doi_desc != "" {
  2249. break
  2250. }
  2251. }
  2252. }
  2253. if doi_desc != "" {
  2254. break
  2255. }
  2256. }
  2257. }
  2258. if doi_desc != "" {
  2259. break
  2260. }
  2261. }
  2262. return rld, ln_desc, doi_desc
  2263. }
  2264. //获取指定IED的网络配置信息
  2265. func (c *ScdNode) GetIedNetworkInfo(scdid int64, ied_name string) ([]orm.Params, error) {
  2266. cacheKey := fmt.Sprintf("networkinfo_%d", scdid)
  2267. if scdid == 0 {
  2268. return nil, errors.New("SCD编号不能为空")
  2269. }
  2270. if ied_name == "" {
  2271. return nil, errors.New("IED名称不能为空")
  2272. }
  2273. networkInfo := []orm.Params{}
  2274. cachedata, h := global.GoCahce.Get(cacheKey)
  2275. if h {
  2276. t1 := cachedata.([]orm.Params)
  2277. if ied_name != "" {
  2278. for _, row := range t1 {
  2279. if row["ied_name"] == ied_name {
  2280. networkInfo = append(networkInfo, row)
  2281. }
  2282. }
  2283. } else {
  2284. networkInfo = t1
  2285. }
  2286. return networkInfo, nil
  2287. }
  2288. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2289. if serr != nil {
  2290. return nil, serr
  2291. }
  2292. if scdXmlObj == nil {
  2293. return nil, errors.New("无效的SCD")
  2294. }
  2295. iedList := []orm.Params{}
  2296. for _, item1 := range scdXmlObj.Communication.SubNetwork {
  2297. net_type := "GSE"
  2298. if len(item1.Name) >= 3 && item1.Name[0:3] == "MMS" {
  2299. net_type = "MMS"
  2300. }
  2301. for _, item2 := range item1.ConnectedAP {
  2302. if len(item2.SMV) > 0 {
  2303. net_type = "SV"
  2304. for _, svitem := range item2.SMV {
  2305. obj := orm.Params{
  2306. "ap_node_id": item2.NodeId,
  2307. "ied_name": item2.IedName,
  2308. "ap_name": item2.ApName,
  2309. "subnetwork_name": item1.Name,
  2310. "subnetwork_desc": item1.Desc,
  2311. "subnetwork_type": item1.Type,
  2312. "net_type": net_type,
  2313. "net_node_id": svitem.NodeId,
  2314. "cb_name": svitem.CbName,
  2315. "ld_inst": svitem.LdInst,
  2316. "address_json": "",
  2317. }
  2318. if svitem.Address != nil {
  2319. jsonmap := map[string]string{}
  2320. for _, r1 := range svitem.Address.P {
  2321. jsonmap[r1.Type] = r1.InnerText
  2322. }
  2323. jsnstr, _ := json.Marshal(jsonmap)
  2324. obj["address_json"] = string(jsnstr)
  2325. }
  2326. networkInfo = append(networkInfo, obj)
  2327. if ied_name != "" && ied_name == item2.IedName {
  2328. iedList = append(iedList, obj)
  2329. }
  2330. }
  2331. } else if len(item2.GSE) > 0 {
  2332. net_type = "GSE"
  2333. for _, gseitem := range item2.GSE {
  2334. obj := orm.Params{
  2335. "ap_node_id": item2.NodeId,
  2336. "ied_name": item2.IedName,
  2337. "ap_name": item2.ApName,
  2338. "subnetwork_name": item1.Name,
  2339. "subnetwork_desc": item1.Desc,
  2340. "subnetwork_type": item1.Type,
  2341. "net_type": net_type,
  2342. "net_node_id": gseitem.NodeId,
  2343. "cb_name": gseitem.CbName,
  2344. "ld_inst": gseitem.LdInst,
  2345. "address_json": "",
  2346. }
  2347. if gseitem.Address != nil {
  2348. jsonmap := map[string]string{}
  2349. for _, r1 := range gseitem.Address.P {
  2350. jsonmap[r1.Type] = r1.InnerText
  2351. }
  2352. jsnstr, _ := json.Marshal(jsonmap)
  2353. obj["address_json"] = string(jsnstr)
  2354. }
  2355. networkInfo = append(networkInfo, obj)
  2356. if ied_name != "" && ied_name == item2.IedName {
  2357. iedList = append(iedList, obj)
  2358. }
  2359. }
  2360. } else {
  2361. obj := orm.Params{
  2362. "ap_node_id": item2.NodeId,
  2363. "ied_name": item2.IedName,
  2364. "ap_name": item2.ApName,
  2365. "subnetwork_name": item1.Name,
  2366. "subnetwork_desc": item1.Desc,
  2367. "subnetwork_type": item1.Type,
  2368. "net_type": net_type,
  2369. "net_node_id": item2.NodeId,
  2370. "cb_name": "",
  2371. "ld_inst": "",
  2372. "address_json": "",
  2373. }
  2374. if item2.Address != nil {
  2375. jsonmap := map[string]string{}
  2376. for _, r1 := range item2.Address.P {
  2377. jsonmap[r1.Type] = r1.InnerText
  2378. }
  2379. jsnstr, _ := json.Marshal(jsonmap)
  2380. obj["address_json"] = string(jsnstr)
  2381. }
  2382. networkInfo = append(networkInfo, obj)
  2383. if ied_name != "" && ied_name == item2.IedName {
  2384. iedList = append(iedList, obj)
  2385. }
  2386. }
  2387. }
  2388. }
  2389. global.GoCahce.Set(cacheKey, networkInfo, -1)
  2390. if ied_name != "" {
  2391. return iedList, nil
  2392. }
  2393. return networkInfo, nil
  2394. }
  2395. //获取指定IEd的指定GSEControl的网络配置信息
  2396. func (c *ScdNode) GetIedGseNetWorkInfo(scdid int64, ied_name, gocb_name string) (orm.Params, error) {
  2397. if scdid == 0 {
  2398. return nil, errors.New("SCD编号不能为空")
  2399. }
  2400. if ied_name == "" {
  2401. return nil, errors.New("IED名称不能为空")
  2402. }
  2403. if gocb_name == "" {
  2404. return nil, errors.New("gocb_name不能为空")
  2405. }
  2406. iedNetinfo, er := c.GetIedNetworkInfo(scdid, ied_name)
  2407. if er != nil {
  2408. return nil, er
  2409. }
  2410. for _, row := range iedNetinfo {
  2411. cb_name := tools.IsEmpty(row["cb_name"])
  2412. if cb_name == gocb_name {
  2413. return row, nil
  2414. }
  2415. }
  2416. return nil, nil
  2417. }
  2418. func (c *ScdNode) Init(stationidint int, name, path string, isenable int, ischeckinscd int) (int64, error) {
  2419. c.ScdName = name
  2420. c.ScdPath = path
  2421. c.StationID = stationidint
  2422. c.NodeRuleList = map[string][]orm.Params{}
  2423. c.NodeAttrRuleList = map[string][]orm.Params{}
  2424. c.NodeAttrUniqueRuleList = []orm.Params{}
  2425. c.NodeRuleFunctionList = []orm.Params{}
  2426. c.NotEndNodeIdList = []int64{}
  2427. c.NodeQue = map[int64]*t_scd_node_scl{}
  2428. c.NodeAttrQue = []interface{}{}
  2429. c.AreaMgr = new(ScdAreaMgr)
  2430. m := t_scd_scl{ScdName: name, Path: path}
  2431. m.IsCheckinScd = ischeckinscd
  2432. m.Enable = isenable
  2433. m.StationId = stationidint
  2434. if c.RootID > 0 {
  2435. m.Id = c.RootID
  2436. }
  2437. c.AreaMgr.ScdId = m.Id
  2438. m.CreatedBy, _ = strconv.Atoi(c.GetUserId())
  2439. m.CreatedTime = tools.NowTime()
  2440. db := orm.NewOrm()
  2441. _, err := db.Insert(&m)
  2442. if err != nil {
  2443. //判断SCD是否已经存在
  2444. if !strings.Contains(err.Error(), "PRIMARY") {
  2445. logger.Logger.Error(err, fmt.Sprintf("操作数据:%+v", m))
  2446. return 0, err
  2447. }
  2448. }
  2449. c.Name = name
  2450. //初始化间隔管理
  2451. c.AreaMgr.ScdId = m.Id //再次赋值,保证当scd不存在时,获取到新添加的SCD ID
  2452. c.AreaMgr.Init(m.Id)
  2453. //加载规则列表
  2454. //获取节点验证规则定义
  2455. lst := []orm.Params{}
  2456. /*
  2457. db.Raw("select * from t_scd_node_check").Values(&lst)
  2458. for _, r := range lst {
  2459. check_object := r["check_object"].(string)
  2460. keys := strings.Split(check_object, ":")
  2461. if ss, ok := c.NodeRuleList[keys[0]]; ok {
  2462. c.NodeRuleList[keys[0]] = append(ss, r)
  2463. } else {
  2464. c.NodeRuleList[keys[0]] = []orm.Params{r}
  2465. }
  2466. }
  2467. */
  2468. //获取节点属性验证规则
  2469. db.Raw("select * from t_scd_scl_check").Values(&lst)
  2470. for _, r := range lst {
  2471. object_name := r["object_name"].(string)
  2472. object_type := r["object_type"].(string)
  2473. if tools.IsEmpty(r["func_name"]) != "" {
  2474. c.NodeRuleFunctionList = append(c.NodeRuleFunctionList, r)
  2475. continue
  2476. }
  2477. //过滤出全局唯一或父节点下唯一的规则单独保存
  2478. if tools.IsEmpty(r["isunique_by_parent"]) == "1" || tools.IsEmpty(r["isunique_by_global"]) == "1" {
  2479. c.NodeAttrUniqueRuleList = append(c.NodeAttrUniqueRuleList, r)
  2480. continue
  2481. }
  2482. if object_type == "node" {
  2483. if ss, ok := c.NodeRuleList[object_name]; ok {
  2484. c.NodeRuleList[object_name] = append(ss, r)
  2485. } else {
  2486. c.NodeRuleList[object_name] = []orm.Params{r}
  2487. }
  2488. } else {
  2489. //node_path := tools.IsEmpty(r["node_path"])
  2490. keys := strings.Split(object_name, "||")
  2491. for _, k := range keys {
  2492. if ss, ok := c.NodeAttrRuleList[k]; ok {
  2493. c.NodeAttrRuleList[k] = append(ss, r)
  2494. } else {
  2495. c.NodeAttrRuleList[k] = []orm.Params{r}
  2496. }
  2497. }
  2498. }
  2499. }
  2500. return m.Id, nil
  2501. }
  2502. func (c *ScdNode) AddNode(name string, attrs map[string]interface{}, lineno int64) error {
  2503. m := new(t_scd_node_scl)
  2504. m.CreatedBy = 0
  2505. m.CreatedTime = tools.NowTime()
  2506. m.NodeName = name
  2507. m.NodeValue = ""
  2508. m.LineNo = lineno
  2509. m.ScdId = c.RootID
  2510. m.Id = c.GetID()
  2511. c.NodeQue[m.Id] = m
  2512. if attrs != nil && len(attrs) > 0 {
  2513. if name == "Bay" {
  2514. //如果存在bay元素,则间隔方式为Bay解析
  2515. c.IsBay = true
  2516. }
  2517. parentNodeNodeName := ""
  2518. parentNode, ok := c.NodeQue[m.ParentNodeId]
  2519. if ok {
  2520. parentNodeNodeName = parentNode.NodeName
  2521. }
  2522. c.NodeAttrQue = append(c.NodeAttrQue, map[string]interface{}{"scdid": c.RootID, "parentNodeName": parentNodeNodeName, "nodeid": m.Id, "nodename": name, "lineno": m.LineNo, "attrs": attrs})
  2523. if !c.IsBay && m.NodeName == "IED" {
  2524. c.AreaMgr.AppendIedNode(c.RootID, m.Id, tools.IsEmpty(attrs["name"]), tools.IsEmpty(attrs["desc"]))
  2525. }
  2526. }
  2527. return nil
  2528. }
  2529. func (c *ScdNode) EndNode(name, txt string) error {
  2530. return nil
  2531. }
  2532. func (c *ScdNode) Flush() {
  2533. //更新关联附件项的scd id
  2534. new(AttachmentMgr).UpdateScdID(c.StationID, c.ScdName, c.ScdPath, c.RootID)
  2535. //c.writeNodeDB()
  2536. //c.writeNodeAttrDB()
  2537. //通知SCD管理对象,解析完成,更新状态
  2538. new(ScdMgr).ParseFinish(c.RootID, c.IsDefaultRunVersion)
  2539. //test
  2540. //c.GetIedInputsRelations(map[string]interface{}{"scd_id": c.RootID, "ied_name": "PB7520A"})
  2541. /*
  2542. if c.AutoCompScdID > 0 {
  2543. comp := new(ScdCompare)
  2544. comp.CompareType = "SCD"
  2545. comp.Sourceid = c.RootID
  2546. comp.Targetid = c.AutoCompScdID
  2547. comp.StationId = c.StationID
  2548. comp.Compare(0)
  2549. }
  2550. */
  2551. }
  2552. //获取指定SCD的校验码
  2553. func (c *ScdNode) GetScdCRC(scdid string) (string, error) {
  2554. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  2555. if serr != nil {
  2556. return "", serr
  2557. }
  2558. if scdXmlObj == nil {
  2559. return "", errors.New("无效的SCD")
  2560. }
  2561. for _, pri := range scdXmlObj.Private {
  2562. if pri.Type == "Substation virtual terminal conection CRC" {
  2563. return pri.InnerText, nil
  2564. }
  2565. }
  2566. return "", nil
  2567. }
  2568. //获取指定SCD的校验码
  2569. func (c *ScdNode) GetIedCRC(scdid, iedname string) (string, error) {
  2570. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  2571. if serr != nil {
  2572. return "", serr
  2573. }
  2574. if scdXmlObj == nil {
  2575. return "", errors.New("无效的SCD")
  2576. }
  2577. iedObj := c.GetIed(scdXmlObj, scdid, iedname)
  2578. if iedObj == nil {
  2579. return "", errors.New("无效的IED装置名称")
  2580. }
  2581. for _, pri := range iedObj.Priavate {
  2582. if pri.Type == "IED virtual terminal conection CRC" {
  2583. return pri.InnerText, nil
  2584. }
  2585. }
  2586. return "", nil
  2587. }
  2588. func (c *ScdNode) writeNodeDB() {
  2589. stationIdStr := fmt.Sprintf("%d", c.StationID)
  2590. scdIdStr := fmt.Sprintf("%d", c.RootID)
  2591. db := orm.NewOrm()
  2592. s1 := time.Now().Unix()
  2593. nodeCols := "(id,scd_id,parent_node_id,node_name,node_value,line_no)"
  2594. totalRec := tools.IsEmpty(len(c.NodeQue))
  2595. loadedRec := 0
  2596. nodeSqlValuesAry := []string{}
  2597. data := map[string]string{"name": c.Name, "stationid": stationIdStr, "rootid": scdIdStr, "state": "0", "node": "write-db", "total": totalRec, "load": fmt.Sprintf("%d", loadedRec), "msg": ""}
  2598. dataMsg, _ := json.Marshal(data)
  2599. go mqtt.PublishMessage("/jujutong/scd_check_tools/parse/"+scdIdStr, string(dataMsg))
  2600. for _, m := range c.NodeQue {
  2601. nodeSqlValuesAry = append(nodeSqlValuesAry, fmt.Sprintf("(%d,%d,%d,'%s','%s',%d)", m.Id, m.ScdId, m.ParentNodeId, m.NodeName, m.NodeValue, m.LineNo))
  2602. if len(nodeSqlValuesAry) == 5000 {
  2603. sql := "insert into t_scd_node_scl" + nodeCols + "values" + strings.Join(nodeSqlValuesAry, ",")
  2604. _, err := db.Raw(sql).Exec()
  2605. if err != nil {
  2606. logger.Logger.Error(err)
  2607. }
  2608. loadedRec = loadedRec + 5000
  2609. nodeSqlValuesAry = []string{}
  2610. data = map[string]string{"name": c.Name, "stationid": stationIdStr, "rootid": scdIdStr, "state": "2", "node": "write-db", "total": totalRec, "load": fmt.Sprintf("%d", loadedRec), "msg": ""}
  2611. dataMsg, _ = json.Marshal(data)
  2612. go mqtt.PublishMessage("/jujutong/scd_check_tools/parse/"+scdIdStr, string(dataMsg))
  2613. }
  2614. m = nil
  2615. }
  2616. if len(nodeSqlValuesAry) > 0 {
  2617. sql := "insert into t_scd_node_scl" + nodeCols + "values" + strings.Join(nodeSqlValuesAry, ",")
  2618. _, err := db.Raw(sql).Exec()
  2619. if err != nil {
  2620. log.Println(err)
  2621. }
  2622. nodeSqlValuesAry = nil
  2623. }
  2624. c.NodeQue = nil
  2625. runtime.GC()
  2626. data = map[string]string{"name": c.Name, "stationid": stationIdStr, "rootid": fmt.Sprintf("%d", c.RootID), "state": "1", "node": "write-db", "total": totalRec, "load": totalRec, "msg": ""}
  2627. dataMsg, _ = json.Marshal(data)
  2628. go mqtt.PublishMessage("/jujutong/scd_check_tools/parse/"+fmt.Sprintf("%d", c.RootID), string(dataMsg))
  2629. s2 := time.Now().Unix()
  2630. logger.Logger.Println(fmt.Sprintf("===================Flush NodeQue 完成!。耗时:%d秒", s2-s1))
  2631. logger.Logger.Println("===========节点入库完成")
  2632. }
  2633. //查询定值
  2634. func (t *ScdNode) GetScdIedDingzhiList(scdid int64, ied_name string) ([]orm.Params, error) {
  2635. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2636. if serr != nil {
  2637. return nil, serr
  2638. }
  2639. if scdXmlObj == nil {
  2640. return nil, errors.New("无效的SCD")
  2641. }
  2642. iedObj := t.GetIed(scdXmlObj, tools.IsEmpty(scdid), ied_name)
  2643. if iedObj == nil {
  2644. return nil, errors.New("无效的IED装置名称")
  2645. }
  2646. scdMgr := new(ScdMgr)
  2647. mapTargetLNodeType := scdMgr.GetLNodeType(scdXmlObj)
  2648. mapTargetLDoType := scdMgr.GetDOType(scdXmlObj)
  2649. rowset := []orm.Params{}
  2650. for _, acc := range iedObj.AccessPoint {
  2651. if acc.Server != nil {
  2652. for _, ld := range acc.Server.LDevice {
  2653. if ld.LN0 != nil {
  2654. for _, ds := range ld.LN0.DataSet {
  2655. if ds.Name == "dsParameter" || ds.Name == "dsSetting" {
  2656. obj := orm.Params{
  2657. "accesspoint_name": acc.Name,
  2658. "ld_desc": ld.Desc,
  2659. "ld_name": ld.Inst,
  2660. "dataset_desc": ds.Desc,
  2661. "dataset_name": ds.Name,
  2662. "list": []orm.Params{},
  2663. }
  2664. for _, fcda := range ds.FCDA {
  2665. fcdaobj := orm.Params{}
  2666. fcdaobj["short_addr"] = fmt.Sprintf("%s/%s%s%s.%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName)
  2667. fcdaobj["doi_name"] = fcda.DoName
  2668. fcdaobj["doi_desc"] = ""
  2669. fcdaobj["da_maxval"] = ""
  2670. fcdaobj["da_minval"] = ""
  2671. fcdaobj["da_stepsize"] = ""
  2672. fcdaobj["da_units"] = ""
  2673. found := false
  2674. if fcda.LnClass == "LLN0" {
  2675. if lnnodetpye, h := mapTargetLNodeType[ld.LN0.LnType]; h {
  2676. for _, doitem := range lnnodetpye.DO {
  2677. if doitem.Name == fcda.DoName {
  2678. dotype := doitem.Type
  2679. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2680. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2681. }
  2682. break
  2683. }
  2684. }
  2685. }
  2686. for _, doi := range ld.LN0.DOI {
  2687. if doi.Name == fcda.DoName {
  2688. fcdaobj["doi_desc"] = doi.Desc
  2689. for _, da := range doi.DAI {
  2690. if da.Name == "maxVal" && da.Val != nil {
  2691. fcdaobj["da_maxval"] = da.Val.InnerText
  2692. }
  2693. if da.Name == "minVal" && da.Val != nil {
  2694. fcdaobj["da_minval"] = da.Val.InnerText
  2695. }
  2696. if da.Name == "stepSize" && da.Val != nil {
  2697. fcdaobj["da_stepsize"] = da.Val.InnerText
  2698. }
  2699. if da.Name == "units" && da.Val != nil {
  2700. fcdaobj["da_units"] = da.Val.InnerText
  2701. }
  2702. }
  2703. found = true
  2704. break
  2705. }
  2706. }
  2707. } else {
  2708. for _, ln := range ld.LN {
  2709. if ln.LnClass == fcda.LnClass && ln.Inst == fcda.LnInst {
  2710. if lnnodetpye, h := mapTargetLNodeType[ln.LnType]; h {
  2711. for _, doitem := range lnnodetpye.DO {
  2712. if doitem.Name == fcda.DoName {
  2713. dotype := doitem.Type
  2714. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2715. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2716. }
  2717. break
  2718. }
  2719. }
  2720. }
  2721. for _, doi := range ln.DOI {
  2722. if doi.Name == fcda.DoName {
  2723. fcdaobj["doi_desc"] = doi.Desc
  2724. for _, da := range doi.DAI {
  2725. if da.Name == "maxVal" && da.Val != nil {
  2726. fcdaobj["da_maxval"] = da.Val.InnerText
  2727. }
  2728. if da.Name == "minVal" && da.Val != nil {
  2729. fcdaobj["da_minval"] = da.Val.InnerText
  2730. }
  2731. if da.Name == "stepSize" && da.Val != nil {
  2732. fcdaobj["da_stepsize"] = da.Val.InnerText
  2733. }
  2734. if da.Name == "units" && da.Val != nil {
  2735. fcdaobj["da_units"] = da.Val.InnerText
  2736. }
  2737. }
  2738. if fcdaobj["da_maxval"] == "" {
  2739. for _, sdi := range doi.SDI {
  2740. if sdi.Name == "maxVal" {
  2741. for _, dai2 := range sdi.DAI {
  2742. if dai2.Name == "f" && dai2.Val != nil {
  2743. fcdaobj["da_maxval"] = dai2.Val.InnerText
  2744. }
  2745. }
  2746. }
  2747. }
  2748. }
  2749. if fcdaobj["da_minval"] == "" {
  2750. for _, sdi := range doi.SDI {
  2751. if sdi.Name == "minVal" {
  2752. for _, dai2 := range sdi.DAI {
  2753. if dai2.Name == "f" && dai2.Val != nil {
  2754. fcdaobj["da_minval"] = dai2.Val.InnerText
  2755. }
  2756. }
  2757. }
  2758. }
  2759. }
  2760. if fcdaobj["da_stepsize"] == "" {
  2761. for _, sdi := range doi.SDI {
  2762. if sdi.Name == "stepSize" {
  2763. for _, dai2 := range sdi.DAI {
  2764. if dai2.Name == "f" && dai2.Val != nil {
  2765. fcdaobj["da_stepsize"] = dai2.Val.InnerText
  2766. }
  2767. }
  2768. }
  2769. }
  2770. }
  2771. unintsFound := false
  2772. if fcdaobj["da_units"] == "" {
  2773. for _, sdi := range doi.SDI {
  2774. if sdi.Name == "units" {
  2775. for _, dai2 := range sdi.DAI {
  2776. if dai2.Name == "SIUnit" {
  2777. for _, enumtype := range scdXmlObj.DataTypeTemplates.EnumType {
  2778. if enumtype.Id == dai2.Name {
  2779. for _, t123 := range enumtype.EnumVal {
  2780. if dai2.Val == nil {
  2781. fcdaobj["da_units"] = ""
  2782. } else if t123.Ord == dai2.Val.InnerText {
  2783. fcdaobj["da_units"] = t123.InnerText
  2784. unintsFound = true
  2785. break
  2786. }
  2787. }
  2788. }
  2789. if unintsFound {
  2790. break
  2791. }
  2792. }
  2793. }
  2794. if unintsFound {
  2795. break
  2796. }
  2797. }
  2798. }
  2799. if unintsFound {
  2800. break
  2801. }
  2802. }
  2803. }
  2804. found = true
  2805. break
  2806. }
  2807. }
  2808. }
  2809. if found {
  2810. break
  2811. }
  2812. }
  2813. }
  2814. obj["list"] = append(obj["list"].([]orm.Params), fcdaobj)
  2815. }
  2816. rowset = append(rowset, obj)
  2817. }
  2818. }
  2819. }
  2820. }
  2821. }
  2822. }
  2823. return rowset, nil
  2824. }
  2825. //查询信息点表
  2826. func (t *ScdNode) GetScdIedPointTableList(scdid int64, ied_name string) ([]orm.Params, error) {
  2827. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2828. if serr != nil {
  2829. return nil, serr
  2830. }
  2831. if scdXmlObj == nil {
  2832. return nil, errors.New("无效的SCD")
  2833. }
  2834. iedObj := t.GetIed(scdXmlObj, tools.IsEmpty(scdid), ied_name)
  2835. if iedObj == nil {
  2836. return nil, errors.New("无效的IED装置名称")
  2837. }
  2838. scdMgr := new(ScdMgr)
  2839. mapTargetLNodeType := scdMgr.GetLNodeType(scdXmlObj)
  2840. mapTargetLDoType := scdMgr.GetDOType(scdXmlObj)
  2841. rowset := []orm.Params{}
  2842. for _, acc := range iedObj.AccessPoint {
  2843. if acc.Server != nil {
  2844. for _, ld := range acc.Server.LDevice {
  2845. if ld.LN0 != nil {
  2846. for _, rpc := range ld.LN0.ReportControl {
  2847. obj := orm.Params{
  2848. "accesspoint_name": acc.Name,
  2849. "ld_desc": ld.Desc,
  2850. "ld_inst": ld.Inst,
  2851. "block_desc": rpc.Desc,
  2852. "block_name": rpc.Name,
  2853. "block_datset": rpc.DatSet,
  2854. "block_rptid": rpc.RptID,
  2855. "block_intgpd": rpc.IntgPd,
  2856. "block_confrev": rpc.ConfRev,
  2857. "block_buftime": rpc.BufTime,
  2858. "block_buffered": rpc.Buffered,
  2859. "list": []orm.Params{},
  2860. }
  2861. for _, ds := range ld.LN0.DataSet {
  2862. if ds.Name == rpc.DatSet {
  2863. for _, fcda := range ds.FCDA {
  2864. fcdaobj := orm.Params{
  2865. "short_addr": fmt.Sprintf("%s/%s%s%s.%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName),
  2866. "doi_name": fcda.DoName,
  2867. "doi_desc": "",
  2868. }
  2869. found := false
  2870. if fcda.LnClass == "LLN0" {
  2871. if lnnodetpye, h := mapTargetLNodeType[ld.LN0.LnType]; h {
  2872. for _, doitem := range lnnodetpye.DO {
  2873. if doitem.Name == fcda.DoName {
  2874. dotype := doitem.Type
  2875. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2876. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2877. }
  2878. break
  2879. }
  2880. }
  2881. }
  2882. for _, doi := range ld.LN0.DOI {
  2883. if doi.Name == fcda.DoName {
  2884. fcdaobj["doi_desc"] = doi.Desc
  2885. found = true
  2886. break
  2887. }
  2888. }
  2889. } else {
  2890. for _, ln := range ld.LN {
  2891. if ln.LnClass == fcda.LnClass && ln.Inst == fcda.LnInst {
  2892. if lnnodetpye, h := mapTargetLNodeType[ln.LnType]; h {
  2893. for _, doitem := range lnnodetpye.DO {
  2894. if doitem.Name == fcda.DoName {
  2895. dotype := doitem.Type
  2896. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2897. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2898. }
  2899. break
  2900. }
  2901. }
  2902. }
  2903. for _, doi := range ln.DOI {
  2904. if doi.Name == fcda.DoName {
  2905. fcdaobj["doi_desc"] = doi.Desc
  2906. found = true
  2907. break
  2908. }
  2909. }
  2910. }
  2911. if found {
  2912. break
  2913. }
  2914. }
  2915. }
  2916. obj["list"] = append(obj["list"].([]orm.Params), fcdaobj)
  2917. }
  2918. break
  2919. }
  2920. }
  2921. rowset = append(rowset, obj)
  2922. }
  2923. }
  2924. }
  2925. }
  2926. }
  2927. return rowset, nil
  2928. }
  2929. //查询源XML
  2930. func (t *ScdNode) GetScdIedSourceXML(scdid int64, ied_name string) (string, error) {
  2931. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2932. if serr != nil {
  2933. return "", serr
  2934. }
  2935. if scdXmlObj == nil {
  2936. return "", errors.New("无效的SCD")
  2937. }
  2938. startLineNo := int64(0)
  2939. endLineNo := int64(0)
  2940. for _, ied := range scdXmlObj.IED {
  2941. if ied.Name == ied_name {
  2942. //当前ied的开始行号
  2943. startLineNo = ied.Lineno
  2944. } else {
  2945. if startLineNo > 0 {
  2946. //结束行为下一个ied的开始行减1
  2947. endLineNo = ied.Lineno - 1
  2948. break
  2949. }
  2950. }
  2951. }
  2952. //判断是不是最后一ied
  2953. if startLineNo > 0 && endLineNo == 0 {
  2954. //最后一个ied的结束行号
  2955. endLineNo = scdXmlObj.DataTypeTemplates.Lineno - 1
  2956. }
  2957. if startLineNo == 0 {
  2958. return "", errors.New("无效的IED装置名称")
  2959. }
  2960. logger.Logger.Debug(fmt.Sprintf("====startLineNo:%d,endLineNo:%d====", startLineNo, endLineNo))
  2961. scdinfo, _ := new(ScdMgr).One(tools.IsEmpty(scdid))
  2962. scdpath := scdinfo["path"].(string)
  2963. parsedFile := strings.ReplaceAll(scdpath, "\\", "/")
  2964. _, err := os.Stat(parsedFile)
  2965. if err != nil {
  2966. logger.Logger.Error(err)
  2967. return "", err
  2968. }
  2969. f, _ := os.Open(parsedFile)
  2970. reslist := []string{}
  2971. if f != nil {
  2972. defer f.Close()
  2973. r1 := bufio.NewReader(f)
  2974. startLineNo = startLineNo - 1 //跳过第一行xml标记行
  2975. lineno := int64(0) //初始行记数器。
  2976. for {
  2977. txt, err := r1.ReadString('\n')
  2978. if err == io.EOF {
  2979. break
  2980. }
  2981. if lineno >= startLineNo {
  2982. reslist = append(reslist, txt)
  2983. }
  2984. lineno = lineno + 1
  2985. if lineno == endLineNo {
  2986. break
  2987. }
  2988. }
  2989. }
  2990. return strings.Join(reslist, ""), nil
  2991. }
  2992. //查询源XML
  2993. func (t *ScdNode) GetScdLineSourceXML(scdid int64, lineno int64) ([]string, error) {
  2994. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2995. if serr != nil {
  2996. return nil, serr
  2997. }
  2998. if scdXmlObj == nil {
  2999. return nil, errors.New("无效的SCD")
  3000. }
  3001. startLineNo := int64(0)
  3002. endLineNo := int64(0)
  3003. if lineno < 0 {
  3004. lineno = 0
  3005. }
  3006. if lineno < 100 {
  3007. startLineNo = 0 //从最开始获取
  3008. endLineNo = lineno + 100
  3009. } else {
  3010. startLineNo = lineno - 100
  3011. endLineNo = lineno + 100
  3012. }
  3013. logger.Logger.Debug(fmt.Sprintf("====startLineNo:%d,endLineNo:%d====", startLineNo, endLineNo))
  3014. scdinfo, _ := new(ScdMgr).One(tools.IsEmpty(scdid))
  3015. scdpath := scdinfo["path"].(string)
  3016. parsedFile := strings.ReplaceAll(scdpath, "\\", "/")
  3017. _, err := os.Stat(parsedFile)
  3018. if err != nil {
  3019. logger.Logger.Error(err)
  3020. return nil, err
  3021. }
  3022. f, _ := os.Open(parsedFile)
  3023. reslist := []string{}
  3024. if f != nil {
  3025. defer f.Close()
  3026. r1 := bufio.NewReader(f)
  3027. startLineNo = startLineNo - 1 //跳过第一行xml标记行
  3028. c_lineno := int64(0) //初始行记数器。
  3029. for {
  3030. txt, err := r1.ReadString('\n')
  3031. if err == io.EOF {
  3032. break
  3033. }
  3034. if c_lineno >= startLineNo {
  3035. reslist = append(reslist, fmt.Sprintf("%d %s", c_lineno+1, txt))
  3036. }
  3037. c_lineno = c_lineno + 1
  3038. if c_lineno == endLineNo {
  3039. break
  3040. }
  3041. }
  3042. }
  3043. return reslist, nil
  3044. }