scd_node_mgr.go 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097
  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. outDoName := strings.Split(extref.IntAddr, ".")[1]
  1210. var ln *node_attr.NLN
  1211. if v, h := out_lns[outLnStr]; h {
  1212. ln = v
  1213. } else {
  1214. //查找内部地址指向的Ln
  1215. lnFound := false
  1216. for _, tLd := range acc.Server.LDevice {
  1217. if extref.LnClass == "LLN0" {
  1218. for _, doi := range tLd.LN0.DOI {
  1219. if doi.Name == fcda.DoName {
  1220. doi_desc = doi.Desc
  1221. lnFound = true
  1222. break
  1223. }
  1224. }
  1225. }
  1226. if doi_desc != "" {
  1227. obj["out_do_desc"] = doi_desc
  1228. break
  1229. }
  1230. for _, tLn := range tLd.LN {
  1231. if outLnStr == fmt.Sprintf("%s/%s%s%s", tLd.Inst, tLn.Prefix, tLn.LnClass, tLn.Inst) {
  1232. out_lns[outLnStr] = tLn
  1233. ln = tLn
  1234. lnFound = true
  1235. break
  1236. }
  1237. }
  1238. if lnFound {
  1239. break
  1240. }
  1241. }
  1242. }
  1243. if ln == nil {
  1244. continue
  1245. }
  1246. for _, doi := range ln.DOI {
  1247. if doi.Name == outDoName {
  1248. obj["out_do_desc"] = doi.Desc
  1249. break
  1250. }
  1251. }
  1252. break
  1253. }
  1254. }
  1255. }
  1256. if outFound {
  1257. break
  1258. }
  1259. }
  1260. if outFound {
  1261. break
  1262. }
  1263. }
  1264. if outFound {
  1265. break
  1266. }
  1267. }
  1268. if outFound {
  1269. break
  1270. }
  1271. }
  1272. rowset = append(rowset, obj)
  1273. }
  1274. break
  1275. }
  1276. }
  1277. return rowset, nil
  1278. }
  1279. //获取指定IED的goose接收块及端子列表
  1280. func (c *ScdNode) GetIedGooseCtrlBlockRevList(scdid int64, iedname string) ([]orm.Params, error) {
  1281. rowset := []orm.Params{}
  1282. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  1283. if serr != nil {
  1284. return nil, serr
  1285. }
  1286. if scdXmlObj == nil {
  1287. return nil, errors.New("无效的SCD")
  1288. }
  1289. currentIedObj := c.GetIed(scdXmlObj, tools.IsEmpty(scdid), iedname)
  1290. if currentIedObj == nil {
  1291. return rowset, errors.New("无效的IED装置名称")
  1292. }
  1293. fromiedObjs := map[string]interface{}{}
  1294. for _, acc := range currentIedObj.AccessPoint {
  1295. if acc.Server != nil {
  1296. for _, ld := range acc.Server.LDevice {
  1297. if ld.LN0 != nil && ld.LN0.Inputs != nil {
  1298. for _, extref := range ld.LN0.Inputs.ExtRef {
  1299. form_ied_name := extref.IedName
  1300. var tmpFromIed *node_attr.NIED
  1301. if v, h := fromiedObjs[form_ied_name]; h {
  1302. tmpFromIed = v.(*node_attr.NIED)
  1303. } else {
  1304. tmpFromIed = c.GetIed(scdXmlObj, tools.IsEmpty(scdid), form_ied_name)
  1305. }
  1306. if tmpFromIed == nil {
  1307. logger.Logger.Error(fmt.Sprintf("未发现IED装置%s", form_ied_name))
  1308. break
  1309. }
  1310. //获取目标IED的块
  1311. iedBlockList, _ := c.GetIedCtrlBlock(scdid, form_ied_name)
  1312. //logger.Logger.Debug(fmt.Sprintf("=====%s 装置,iedBlockList:%+v", form_ied_name, iedBlockList))
  1313. if iedBlockList == nil {
  1314. continue
  1315. }
  1316. smvBlcokList := iedBlockList["GSEControl"].([]orm.Params)
  1317. if len(smvBlcokList) == 0 {
  1318. continue
  1319. }
  1320. gooseDataSetMap := map[string]int{}
  1321. for _, smvRow := range smvBlcokList {
  1322. gooseDataSetMap[tools.IsEmpty(smvRow["attr_dat_set"])] = 1
  1323. }
  1324. found := false
  1325. out_lns := map[string]*node_attr.NLN{}
  1326. for _, fromacc := range tmpFromIed.AccessPoint {
  1327. if fromacc.Server != nil {
  1328. for _, fromld := range fromacc.Server.LDevice {
  1329. if fromld.Inst == extref.LdInst {
  1330. for _, ds := range fromld.LN0.DataSet {
  1331. _, h := gooseDataSetMap[ds.Name]
  1332. if !h {
  1333. continue
  1334. }
  1335. for _, fromfcda := range ds.FCDA {
  1336. if extref.LnClass == fromfcda.LnClass && extref.Prefix == fromfcda.Prefix && extref.LnInst == fromfcda.LnInst && extref.DoName == fromfcda.DoName {
  1337. obj := orm.Params{
  1338. "int_addr": extref.IntAddr,
  1339. "out_do_name": fromfcda.DoName,
  1340. "out_ied_name": tmpFromIed.Name,
  1341. "out_ied_desc": tmpFromIed.Desc,
  1342. "out_dataset_name": ds.Name,
  1343. "out_dataset_desc": ds.Desc,
  1344. "out_gse_ctrl_name": "",
  1345. "out_gse_ctrl_address": "",
  1346. }
  1347. //获取内部信号描述
  1348. doi_desc := ""
  1349. outLnStr := strings.Split(extref.IntAddr, ".")[0]
  1350. outDoName := strings.Split(extref.IntAddr, ".")[1]
  1351. var ln *node_attr.NLN
  1352. if v, h := out_lns[outLnStr]; h {
  1353. ln = v
  1354. } else {
  1355. //查找内部地址指向的Ln
  1356. lnFound := false
  1357. for _, tLd := range acc.Server.LDevice {
  1358. if extref.LnClass == "LLN0" {
  1359. for _, doi := range tLd.LN0.DOI {
  1360. if doi.Name == outDoName {
  1361. doi_desc = doi.Desc
  1362. lnFound = true
  1363. break
  1364. }
  1365. }
  1366. }
  1367. if doi_desc != "" {
  1368. obj["do_desc"] = doi_desc
  1369. break
  1370. }
  1371. for _, tLn := range tLd.LN {
  1372. if outLnStr == fmt.Sprintf("%s/%s%s%s", tLd.Inst, tLn.Prefix, tLn.LnClass, tLn.Inst) {
  1373. out_lns[outLnStr] = tLn
  1374. ln = tLn
  1375. lnFound = true
  1376. break
  1377. }
  1378. }
  1379. if lnFound {
  1380. break
  1381. }
  1382. }
  1383. }
  1384. if ln != nil {
  1385. for _, doi := range ln.DOI {
  1386. if doi.Name == outDoName {
  1387. obj["do_desc"] = doi.Desc
  1388. break
  1389. }
  1390. }
  1391. }
  1392. //获取输入块信息
  1393. for _, smvRow := range smvBlcokList {
  1394. if tools.IsEmpty(smvRow["attr_dat_set"]) == ds.Name {
  1395. obj["out_gse_ctrl_name"] = smvRow["attr_name"]
  1396. obj["out_gse_ctrl_address"] = smvRow["address"]
  1397. break
  1398. }
  1399. }
  1400. doi_desc = ""
  1401. if fromfcda.LnClass == "LLN0" {
  1402. for _, doi := range fromld.LN0.DOI {
  1403. if doi.Name == fromfcda.DoName {
  1404. doi_desc = doi.Desc
  1405. break
  1406. }
  1407. }
  1408. } else {
  1409. for _, ln := range fromld.LN {
  1410. if ln.Inst == fromfcda.LnInst && ln.LnClass == fromfcda.LnClass && ln.Prefix == fromfcda.Prefix {
  1411. for _, doi := range ln.DOI {
  1412. if doi.Name == fromfcda.DoName {
  1413. doi_desc = doi.Desc
  1414. break
  1415. }
  1416. }
  1417. }
  1418. if doi_desc != "" {
  1419. break
  1420. }
  1421. }
  1422. }
  1423. if doi_desc != "" {
  1424. obj["out_do_desc"] = doi_desc
  1425. }
  1426. rowset = append(rowset, obj)
  1427. }
  1428. }
  1429. }
  1430. found = true
  1431. break
  1432. }
  1433. }
  1434. if found {
  1435. break
  1436. }
  1437. }
  1438. }
  1439. }
  1440. }
  1441. }
  1442. }
  1443. }
  1444. return rowset, nil
  1445. }
  1446. //生成指定scd下的ied输入输出关系数据
  1447. func (c *ScdNode) MakeIedRelations(scdid int64, iedname ...string) error {
  1448. db := orm.NewOrm()
  1449. rowset := []orm.Params{}
  1450. v_iedname := ""
  1451. if len(iedname) > 0 {
  1452. v_iedname = iedname[0]
  1453. }
  1454. var err error
  1455. sql := ""
  1456. if v_iedname != "" {
  1457. sql = "select node_id, attr_name from t_scd_ied_attrs where scd_id=? and attr_name=?"
  1458. _, err = db.Raw(sql, scdid, v_iedname).Values(&rowset)
  1459. } else {
  1460. sql = "select node_id, attr_name from t_scd_ied_attrs where scd_id=?"
  1461. _, err = db.Raw(sql, scdid).Values(&rowset)
  1462. }
  1463. sqllog := fmt.Sprintf("SQL:%s,参数:%d,%s", sql, scdid, v_iedname)
  1464. if err != nil {
  1465. logger.Logger.Error(err, sqllog)
  1466. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  1467. return err
  1468. }
  1469. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
  1470. if len(rowset) == 0 {
  1471. return errors.New("无效的SCD文件编号")
  1472. }
  1473. //wg := sync.WaitGroup{}
  1474. //wg.Add(len(rowset))
  1475. for _, row := range rowset {
  1476. ied_name := tools.IsEmpty(row["attr_name"])
  1477. iedid := tools.IsEmpty(row["node_id"])
  1478. //go func(iedid, ied_name string) {
  1479. // defer wg.Done()
  1480. // time.Sleep(100 * time.Millisecond)
  1481. //db0 := orm.NewOrm()
  1482. //ref为1时,查询的是该IED的输入关联IED
  1483. //ref为0时,查询的是该iED的输出关联IED
  1484. 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
  1485. union
  1486. 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`
  1487. _, err = db.Raw(sql, scdid, scdid, ied_name, scdid, scdid, ied_name).Exec()
  1488. sqllog := fmt.Sprintf("SQL:%s,参数:%+v", sql, []interface{}{scdid, scdid, ied_name, scdid, scdid, ied_name})
  1489. if err != nil {
  1490. logger.Logger.Error(err, sqllog)
  1491. new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Insert, enum.OptEventType_Bus, enum.OptEventLevel_Hight, sqllog, c.GetUserInfo())
  1492. return err
  1493. }
  1494. new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Insert, enum.OptEventType_Bus, enum.OptEventLevel_Hight, sqllog, c.GetUserInfo())
  1495. //}(ied_id, ied_name)
  1496. }
  1497. //wg.Wait()
  1498. return nil
  1499. }
  1500. //获取指定IEd节点的控制块关系
  1501. func (c *ScdNode) GetIedBlockRelations(scdid int64, ied_name string, forcerefresh ...bool) ([]orm.Params, error) {
  1502. if ied_name == "" {
  1503. return nil, errors.New("IEDname不能同时为空")
  1504. }
  1505. if scdid == 0 {
  1506. return nil, errors.New("scd编号不能为空")
  1507. }
  1508. cacheKey := fmt.Sprintf("GetIedBlockRelations_%d_%s", scdid, ied_name)
  1509. if v, h := global.GoCahce.Get(cacheKey); h {
  1510. return v.([]orm.Params), nil
  1511. }
  1512. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  1513. if serr != nil {
  1514. return nil, serr
  1515. }
  1516. if scdXmlObj == nil {
  1517. return nil, errors.New("无效的SCD")
  1518. }
  1519. queryRowset := []orm.Params{}
  1520. var masterIed = c.GetIed(scdXmlObj, tools.IsEmpty(scdid), ied_name)
  1521. if masterIed == nil {
  1522. return nil, errors.New("无效的IED装备名称")
  1523. }
  1524. extreflist, _ := c.GetIedInputsRelations(map[string]interface{}{"ied_name": masterIed.Name, "scd_id": scdid})
  1525. if extreflist == nil || len(extreflist) == 0 {
  1526. return nil, nil
  1527. }
  1528. //缓存每个块关联的详情
  1529. cachebBlockDetail := map[string][]orm.Params{}
  1530. //获取当前IED的控制块,获取输入的IED及块
  1531. inputBlock := map[string]orm.Params{}
  1532. for _, row := range extreflist {
  1533. //"attr_ld_inst","attr_prefix","attr_ln_class","attr_ln_inst","attr_do_name","attr_da_name"
  1534. tmpIedName := tools.IsEmpty(row["ied_name"])
  1535. if tmpIedName == masterIed.Name {
  1536. continue
  1537. }
  1538. if tools.IsEmpty(row["inout_type"]) == "out" {
  1539. //过滤该ied中的输出ExtRef
  1540. continue
  1541. }
  1542. extrefid := row["node_id"]
  1543. ldInst := tools.IsEmpty(row["attr_ld_inst"])
  1544. prefix := tools.IsEmpty(row["attr_prefix"])
  1545. lnClass := tools.IsEmpty(row["attr_ln_class"])
  1546. lnInst := tools.IsEmpty(row["attr_ln_inst"])
  1547. doName := tools.IsEmpty(row["attr_do_name"])
  1548. //daName := tools.IsEmpty(row["attr_da_name"])
  1549. inout := tools.IsEmpty(row["inout_type"]) //in:输入当前IED out:输出到其他IED
  1550. inIed := c.GetIed(scdXmlObj, tools.IsEmpty(scdid), tmpIedName)
  1551. if inIed == nil {
  1552. logger.Logger.Error(errors.New(fmt.Sprintf("在scd:中未找到装置%s", scdid, tmpIedName)))
  1553. continue
  1554. }
  1555. if inIed.AccessPoint == nil {
  1556. continue
  1557. }
  1558. for _, t1 := range inIed.AccessPoint {
  1559. if t1.Server == nil {
  1560. continue
  1561. }
  1562. for _, t2 := range t1.Server.LDevice {
  1563. if t2.Inst == ldInst {
  1564. for _, dataset := range t2.LN0.DataSet {
  1565. foundCnt := 0
  1566. isfound := false
  1567. 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": ""}
  1568. for _, fcda := range dataset.FCDA {
  1569. if prefix == fcda.Prefix && doName == fcda.DoName && fcda.LdInst == ldInst && fcda.LnInst == lnInst && fcda.LnClass == lnClass {
  1570. if foundCnt == 0 {
  1571. obj["ld_id"] = t2.NodeId
  1572. obj["ld_inst"] = t2.Inst
  1573. obj["ld_desc"] = t2.Desc
  1574. obj["datset_id"] = dataset.NodeId
  1575. obj["datset_desc"] = dataset.Desc
  1576. obj["datset_name"] = dataset.Name
  1577. obj["fcda_id"] = fcda.NodeId
  1578. obj["extref_id"] = extrefid
  1579. }
  1580. foundCnt = foundCnt + 1 //计算关联的端子数量
  1581. isfound = true
  1582. break
  1583. }
  1584. }
  1585. obj["inputs_cnt"] = foundCnt
  1586. if isfound {
  1587. datasetName := tools.IsEmpty(obj["datset_name"])
  1588. //获取控制块信息
  1589. for _, gse := range t2.LN0.GSEControl {
  1590. if gse.DatSet == datasetName {
  1591. obj["ctrl_id"] = gse.NodeId
  1592. obj["ctrl_type"] = gse.Type
  1593. obj["ctrl_name"] = gse.Name
  1594. }
  1595. }
  1596. for _, smv := range t2.LN0.SampledValueControl {
  1597. if smv.DatSet == datasetName {
  1598. obj["ctrl_id"] = smv.NodeId
  1599. obj["ctrl_type"] = "smv"
  1600. obj["ctrl_name"] = smv.Name
  1601. }
  1602. }
  1603. obj["ref_type"] = "1"
  1604. obj["inout_type"] = inout
  1605. obj["source_ied_id"] = masterIed.NodeId
  1606. obj["source_ied_name"] = masterIed.Name
  1607. obj["target_ied_id"] = inIed.NodeId
  1608. obj["target_ied_name"] = tmpIedName
  1609. obj["out_ld_id"] = t2.NodeId
  1610. obj["out_ld_desc"] = t2.Desc
  1611. obj["out_ld_inst"] = t2.Inst
  1612. key := fmt.Sprintf("%d%s%s%d", scdid, masterIed.Name, tmpIedName, obj["ctrl_id"])
  1613. if v, h := inputBlock[key]; h {
  1614. v1, _ := strconv.Atoi(tools.IsEmpty(v["inputs_cnt"]))
  1615. v["inputs_cnt"] = v1 + 1
  1616. inputBlock[key] = v
  1617. cachebBlockDetail[key] = append(cachebBlockDetail[key], obj)
  1618. } else {
  1619. //queryRowset = append(queryRowset, obj)
  1620. inputBlock[key] = obj
  1621. cachebBlockDetail[key] = []orm.Params{obj}
  1622. }
  1623. }
  1624. }
  1625. }
  1626. }
  1627. }
  1628. }
  1629. for _, r := range inputBlock {
  1630. queryRowset = append(queryRowset, r)
  1631. }
  1632. //获取关联IED的控制块,获取输出的IED及块
  1633. inputBlock = map[string]orm.Params{}
  1634. relIedlist, _ := c.GetIedRelations(map[string]interface{}{"scd_id": scdid, "ied_name": masterIed.Name})
  1635. if relIedlist != nil {
  1636. relIedlist = relIedlist[masterIed.Name].(orm.Params)
  1637. vList := relIedlist["list"].([]orm.Params)
  1638. for _, refIed := range vList {
  1639. if refIed["ref_ied_name"] == nil {
  1640. continue
  1641. }
  1642. if refIed["ref_type"] == "1" {
  1643. //输入IED
  1644. continue
  1645. }
  1646. tmpIedName := refIed["ref_ied_name"].(string)
  1647. extreflist, _ := c.GetIedInputsRelations(map[string]interface{}{"ied_name": tmpIedName, "scd_id": scdid})
  1648. if extreflist == nil || len(extreflist) == 0 {
  1649. continue
  1650. }
  1651. for _, extref := range extreflist {
  1652. if tools.IsEmpty(extref["inout_type"]) == "out" {
  1653. //过滤该ied中的输出ExtRef
  1654. continue
  1655. }
  1656. toIedName := tools.IsEmpty(extref["ied_name"])
  1657. if toIedName != masterIed.Name {
  1658. //过虑输入ied非当前查询ied的extref
  1659. continue
  1660. }
  1661. extrefid := extref["node_id"]
  1662. ldInst := tools.IsEmpty(extref["attr_ld_inst"])
  1663. prefix := tools.IsEmpty(extref["attr_prefix"])
  1664. lnClass := tools.IsEmpty(extref["attr_ln_class"])
  1665. lnInst := tools.IsEmpty(extref["attr_ln_inst"])
  1666. doName := tools.IsEmpty(extref["attr_do_name"])
  1667. //daName := tools.IsEmpty(row["attr_da_name"])
  1668. inout := tools.IsEmpty(extref["inout_type"]) //in:输入当前IED out:输出到其他IED
  1669. inIed := masterIed //c.GetIed(scdXmlObj, tools.IsEmpty(scdid), tmpIedName)
  1670. if inIed.AccessPoint == nil {
  1671. continue
  1672. }
  1673. for _, t1 := range inIed.AccessPoint {
  1674. if t1.Server == nil {
  1675. continue
  1676. }
  1677. for _, t2 := range t1.Server.LDevice {
  1678. //logger.Logger.Debug(fmt.Sprintf("%s LDevice%+v:", tmpIedName, t2.Desc))
  1679. for _, dataset := range t2.LN0.DataSet {
  1680. foundCnt := 0
  1681. isfound := false
  1682. 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": ""}
  1683. for _, fcda := range dataset.FCDA {
  1684. if prefix == fcda.Prefix && doName == fcda.DoName && fcda.LdInst == ldInst && fcda.LnInst == lnInst && fcda.LnClass == lnClass {
  1685. if foundCnt == 0 {
  1686. obj["ld_id"] = t2.NodeId
  1687. obj["ld_inst"] = t2.Inst
  1688. obj["ld_desc"] = t2.Desc
  1689. obj["datset_id"] = dataset.NodeId
  1690. obj["datset_desc"] = dataset.Desc
  1691. obj["datset_name"] = dataset.Name
  1692. obj["fcda_id"] = fcda.NodeId
  1693. obj["extref_id"] = extrefid
  1694. }
  1695. foundCnt = foundCnt + 1 //计算关联的端子数量
  1696. isfound = true
  1697. break
  1698. }
  1699. }
  1700. obj["inputs_cnt"] = foundCnt
  1701. if isfound {
  1702. datasetName := tools.IsEmpty(obj["datset_name"])
  1703. //获取控制块信息
  1704. for _, gse := range t2.LN0.GSEControl {
  1705. if gse.DatSet == datasetName {
  1706. obj["ctrl_id"] = gse.NodeId
  1707. obj["ctrl_type"] = gse.Type
  1708. obj["ctrl_name"] = gse.Name
  1709. }
  1710. }
  1711. for _, smv := range t2.LN0.SampledValueControl {
  1712. if smv.DatSet == datasetName {
  1713. obj["ctrl_id"] = smv.NodeId
  1714. obj["ctrl_type"] = "smv"
  1715. obj["ctrl_name"] = smv.Name
  1716. }
  1717. }
  1718. obj["ref_type"] = "0"
  1719. obj["source_ied_id"] = inIed.NodeId
  1720. obj["source_ied_name"] = tmpIedName
  1721. obj["target_ied_id"] = masterIed.NodeId
  1722. obj["target_ied_name"] = masterIed.Name
  1723. obj["out_ld_id"] = t2.NodeId
  1724. obj["out_ld_desc"] = t2.Desc
  1725. obj["out_ld_inst"] = t2.Inst
  1726. obj["inout_type"] = inout
  1727. key := fmt.Sprintf("%d%s%s%d", scdid, masterIed.Name, tmpIedName, obj["ctrl_id"])
  1728. if v, h := inputBlock[key]; h {
  1729. v1, _ := strconv.Atoi(tools.IsEmpty(v["inputs_cnt"]))
  1730. v["inputs_cnt"] = v1 + 1
  1731. inputBlock[key] = v
  1732. cachebBlockDetail[key] = append(cachebBlockDetail[key], obj)
  1733. } else {
  1734. //queryRowset = append(queryRowset, obj)
  1735. inputBlock[key] = obj
  1736. cachebBlockDetail[key] = []orm.Params{obj}
  1737. }
  1738. }
  1739. }
  1740. }
  1741. }
  1742. }
  1743. }
  1744. }
  1745. for _, r := range inputBlock {
  1746. queryRowset = append(queryRowset, r)
  1747. }
  1748. mqtt.PublishMessage("/jujutong/scd_check_tools/iedblockrelations/"+tools.IsEmpty(scdid)+"/"+ied_name, `{"ied_name":"`+ied_name+`","code":1}`)
  1749. //缓存块关联详情
  1750. global.GoCahce.Set(fmt.Sprintf("cachebBlockDetail_%d", scdid), cachebBlockDetail, -1)
  1751. return queryRowset, nil
  1752. }
  1753. //获取指定IED节点的虚端子关系
  1754. func (c *ScdNode) GetIedInputsRelations(param map[string]interface{}) ([]orm.Params, error) {
  1755. iedid := tools.IsEmpty(param["ied_id"])
  1756. ied_name := tools.IsEmpty(param["ied_name"])
  1757. if iedid == "" && ied_name == "" {
  1758. return nil, errors.New("IED编号和name不能同时为空")
  1759. }
  1760. scdid := tools.IsEmpty(param["scd_id"])
  1761. if scdid == "" {
  1762. return nil, errors.New("scd编号不能为空")
  1763. }
  1764. cacheKey1 := "GetIedInputsRelations_" + scdid + ied_name
  1765. if v, h := global.GoCahce.Get(cacheKey1); h {
  1766. return v.([]orm.Params), nil
  1767. }
  1768. scdobj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  1769. if serr != nil {
  1770. return nil, serr
  1771. }
  1772. if scdobj == nil {
  1773. return nil, errors.New("该scd还未解析或解析未完成!")
  1774. }
  1775. if iedid != "" {
  1776. has := false
  1777. for _, item := range scdobj.IED {
  1778. if tools.IsEmpty(item.NodeId) == iedid {
  1779. has = true
  1780. ied_name = item.Name
  1781. break
  1782. }
  1783. }
  1784. if !has {
  1785. return nil, errors.New("无效的IED编号")
  1786. }
  1787. }
  1788. attrsrows := []orm.Params{} //input输入输出虚端子关系
  1789. for _, item := range scdobj.IED {
  1790. for _, accpointitem := range item.AccessPoint {
  1791. if accpointitem.Server == nil {
  1792. continue
  1793. }
  1794. for _, lditem := range accpointitem.Server.LDevice {
  1795. if lditem.LN0.Inputs == nil {
  1796. continue
  1797. }
  1798. no := 0
  1799. for _, extrefitem := range lditem.LN0.Inputs.ExtRef {
  1800. no = no + 1
  1801. inout := ""
  1802. tmpIedName := ""
  1803. doinDesc := ""
  1804. dooutDesc := ""
  1805. if item.Name == ied_name {
  1806. inout = "in"
  1807. tmpIedName = extrefitem.IedName
  1808. //获取内部地址的描述
  1809. _, _, doinDesc = c.GetIntAddrDesc(item, extrefitem.IntAddr)
  1810. fcda_addr := fmt.Sprintf("%s/%s%s%s.%s", extrefitem.LdInst, extrefitem.Prefix, extrefitem.LnClass, extrefitem.LnInst, extrefitem.DoName)
  1811. if extrefitem.DaName != "" {
  1812. fcda_addr = fcda_addr + "." + extrefitem.DaName
  1813. }
  1814. extrefIed := c.GetIed(scdobj, scdid, tmpIedName)
  1815. _, _, dooutDesc = c.GetIntAddrDesc(extrefIed, fcda_addr)
  1816. } else if extrefitem.IedName == ied_name {
  1817. inout = "out"
  1818. tmpIedName = item.Name
  1819. _, _, doinDesc = c.GetIntAddrDesc(item, extrefitem.IntAddr)
  1820. //获取fcda的描述
  1821. fcda_addr := fmt.Sprintf("%s/%s%s%s.%s", extrefitem.LdInst, extrefitem.Prefix, extrefitem.LnClass, extrefitem.LnInst, extrefitem.DoName)
  1822. if extrefitem.DaName != "" {
  1823. fcda_addr = fcda_addr + "." + extrefitem.DaName
  1824. }
  1825. mIed := c.GetIed(scdobj, scdid, ied_name)
  1826. _, _, dooutDesc = c.GetIntAddrDesc(mIed, fcda_addr)
  1827. } else {
  1828. continue
  1829. }
  1830. v_o := orm.Params{
  1831. "no": no,
  1832. "inout_type": inout,
  1833. "ied_name": tmpIedName,
  1834. "node_id": extrefitem.NodeId,
  1835. "attr_ld_inst": extrefitem.LdInst,
  1836. "attr_prefix": extrefitem.Prefix,
  1837. "attr_ln_class": extrefitem.LnClass,
  1838. "attr_ln_inst": extrefitem.LnInst,
  1839. "attr_do_name": extrefitem.DoName,
  1840. "attr_da_name": extrefitem.DaName,
  1841. "attr_int_addr": extrefitem.IntAddr,
  1842. "line_no": extrefitem.Lineno,
  1843. "do_target_desc": doinDesc,
  1844. "do_source_desc": dooutDesc,
  1845. }
  1846. attrsrows = append(attrsrows, v_o)
  1847. }
  1848. }
  1849. }
  1850. }
  1851. //logger.Logger.Debug(fmt.Sprintf("%+v", attrsrows))
  1852. global.GoCahce.Set(cacheKey1, attrsrows, -1)
  1853. return attrsrows, nil
  1854. }
  1855. //获取指定IED节点及控制块ID的虚端子关系
  1856. func (c *ScdNode) GetIedCtrlInputsRelations(param map[string]interface{}) ([]orm.Params, error) {
  1857. m_ied_name := tools.IsEmpty(param["m_ied_name"])
  1858. if m_ied_name == "" {
  1859. return nil, errors.New("源IED name不能为空")
  1860. }
  1861. s_ied_name := tools.IsEmpty(param["s_ied_name"])
  1862. if s_ied_name == "" {
  1863. return nil, errors.New("目标IED name不能为空")
  1864. }
  1865. scdid := tools.IsEmpty(param["scd_id"])
  1866. if scdid == "" {
  1867. return nil, errors.New("scd编号不能为空")
  1868. }
  1869. scdidint64, _ := strconv.ParseInt(scdid, 10, 64)
  1870. //缓存块关联详情
  1871. cachebBlockDetail, _ := global.GoCahce.Get(fmt.Sprintf("cachebBlockDetail_%s", scdid))
  1872. if cachebBlockDetail == nil {
  1873. return nil, errors.New("未查询到数据")
  1874. }
  1875. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  1876. if serr != nil {
  1877. return nil, serr
  1878. }
  1879. if scdXmlObj == nil {
  1880. return nil, errors.New("无效的SCD")
  1881. }
  1882. m_ctrlid := tools.IsEmpty(param["m_ctrlid"])
  1883. s_ctrlid := tools.IsEmpty(param["s_ctrlid"])
  1884. key := fmt.Sprintf("%s%s%s%s%s", scdid, m_ied_name, s_ied_name, m_ctrlid, s_ctrlid)
  1885. cachebBlockDetailMap := cachebBlockDetail.(map[string][]orm.Params)
  1886. //logger.Logger.Debug(fmt.Sprintf("获取指定IED节点及控制块ID的虚端子关系:%s\n%+v", key, cachebBlockDetailMap))
  1887. attrsrows := cachebBlockDetailMap[key]
  1888. //返回数据: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
  1889. rowset := []orm.Params{}
  1890. v_scdcache, _ := GlobalNodeMap.Load(scdidint64)
  1891. if v_scdcache == nil {
  1892. return nil, errors.New("无效的SCD")
  1893. }
  1894. cacheNodeList := v_scdcache.(map[int64]NodeCacheMap)
  1895. mIed := new(ScdNode).GetIed(scdXmlObj, scdid, m_ied_name)
  1896. sIed := new(ScdNode).GetIed(scdXmlObj, scdid, s_ied_name)
  1897. for _, row := range attrsrows {
  1898. obj := orm.Params{}
  1899. ln_desc := ""
  1900. doi_desc := ""
  1901. extrefid := tools.IsEmpty(row["extref_id"])
  1902. fcdaid := tools.IsEmpty(row["fcda_id"])
  1903. target_ied_name := tools.IsEmpty(row["target_ied_name"])
  1904. master_ied_name := tools.IsEmpty(row["master_ied_name"])
  1905. if m_ctrlid != "" && master_ied_name == m_ied_name {
  1906. fcdaidint64, _ := strconv.ParseInt(fcdaid, 10, 64)
  1907. //主IED向外输出,根据主IED的fcda查找from_doi等信息
  1908. nodeInfo := cacheNodeList[fcdaidint64]
  1909. if nodeInfo.ObjAddr != nil {
  1910. fcda := nodeInfo.ObjAddr.(*node_attr.NFCDA)
  1911. //logger.Logger.Debug(fmt.Sprintf("fcda %s info:%+v", fcdaid, fcda))
  1912. obj["node_id"] = fcda.NodeId
  1913. obj["attr_ld_inst"] = fcda.LdInst
  1914. obj["attr_ln_class"] = fcda.LnClass
  1915. obj["attr_ln_inst"] = fcda.LnInst
  1916. obj["attr_prefix"] = fcda.Prefix
  1917. obj["attr_ix"] = fcda.Ix
  1918. obj["attr_fc"] = fcda.Fc
  1919. obj["attr_do_name"] = fcda.DoName
  1920. obj["attr_da_name"] = fcda.DaName
  1921. var ld *node_attr.NLDevice
  1922. ld, ln_desc, doi_desc = c.GetFcdaDesc(mIed, fcda)
  1923. if ld != nil {
  1924. obj["attr_ld_desc"] = ld.Desc
  1925. }
  1926. /*
  1927. for _, ied := range mIed.AccessPoint {
  1928. if ied.Server != nil {
  1929. for _, ld := range ied.Server.LDevice {
  1930. //logger.Logger.Debug(fmt.Sprintf(" ld========%s=============%s", ld.Inst, fcda.LdInst))
  1931. if ld.Inst == fcda.LdInst {
  1932. obj["attr_ld_desc"] = ld.Desc
  1933. if fcda.LnClass == "LLN0" {
  1934. ln_desc = ld.LN0.Desc
  1935. for _, doi := range ld.LN0.DOI {
  1936. if doi.Name == fcda.DoName {
  1937. doi_desc = doi.Desc
  1938. break
  1939. }
  1940. }
  1941. break
  1942. }
  1943. for _, ln := range ld.LN {
  1944. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  1945. ln_desc = ln.Desc
  1946. //logger.Logger.Debug(fmt.Sprintf(" LN=====================%+v", ln))
  1947. for _, doi := range ln.DOI {
  1948. if doi.Name == fcda.DoName {
  1949. doi_desc = doi.Desc
  1950. break
  1951. }
  1952. }
  1953. }
  1954. if 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. }
  1970. obj["from_doi_desc"] = doi_desc
  1971. obj["from_ln_desc"] = ln_desc
  1972. //主IED向外输出,根据接收IED的extref的内部地址查找to_doi等信息
  1973. extrefidint64, _ := strconv.ParseInt(extrefid, 10, 64)
  1974. nodeInfo = cacheNodeList[extrefidint64]
  1975. ln_desc = ""
  1976. doi_desc = ""
  1977. var ld *node_attr.NLDevice
  1978. if nodeInfo.ObjAddr != nil {
  1979. extref := nodeInfo.ObjAddr.(*node_attr.NExtRef)
  1980. //logger.Logger.Debug(fmt.Sprintf("extref %s info:%+v", extrefid, extref))
  1981. obj["attr_int_addr"] = extref.IntAddr
  1982. ld, ln_desc, doi_desc = c.GetIntAddrDesc(sIed, extref.IntAddr)
  1983. if ld != nil {
  1984. obj["to_ld_inst"] = ld.Inst
  1985. obj["to_ld_desc"] = ld.Desc
  1986. }
  1987. /*
  1988. addrparts := strings.Split(extref.IntAddr, "/")
  1989. to_ldinst := addrparts[0]
  1990. //to_lnPri := addrparts[1] //ln标识符,由prefix+lnClass+inst.doname.daname组成
  1991. to_lnPriParts := strings.Split(addrparts[1], ".")
  1992. to_doname := to_lnPriParts[1]
  1993. for _, ied := range sIed.AccessPoint {
  1994. if ied.Server != nil {
  1995. for _, ld := range ied.Server.LDevice {
  1996. if ld.Inst == to_ldinst {
  1997. obj["to_ld_inst"] = ld.Inst
  1998. obj["to_ld_desc"] = ld.Desc
  1999. for _, ln := range ld.LN {
  2000. //logger.Logger.Debug(fmt.Sprintf("to: %s==%s", ln.Prefix+ln.LnClass+ln.Inst, to_lnPriParts[0]))
  2001. if (ln.Prefix + ln.LnClass + ln.Inst) == to_lnPriParts[0] {
  2002. ln_desc = ln.Desc
  2003. for _, doi := range ln.DOI {
  2004. if doi.Name == to_doname {
  2005. doi_desc = doi.Desc
  2006. break
  2007. }
  2008. }
  2009. }
  2010. if 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. }
  2026. obj["to_doi_desc"] = doi_desc
  2027. obj["to_ln_desc"] = ln_desc
  2028. rowset = append(rowset, obj)
  2029. }
  2030. if s_ctrlid != "" && target_ied_name == s_ied_name {
  2031. //向主IED输入
  2032. fcdaidint64, _ := strconv.ParseInt(fcdaid, 10, 64)
  2033. //主IED向外输出,根据主IED的fcda查找from_doi等信息
  2034. nodeInfo := cacheNodeList[fcdaidint64]
  2035. if nodeInfo.ObjAddr != nil {
  2036. fcda := nodeInfo.ObjAddr.(*node_attr.NFCDA)
  2037. //logger.Logger.Debug(fmt.Sprintf("fcda %s info:%+v", fcdaid, fcda))
  2038. obj["node_id"] = fcda.NodeId
  2039. obj["attr_ld_inst"] = fcda.LdInst
  2040. obj["attr_ln_class"] = fcda.LnClass
  2041. obj["attr_ln_inst"] = fcda.LnInst
  2042. obj["attr_prefix"] = fcda.Prefix
  2043. obj["attr_ix"] = fcda.Ix
  2044. obj["attr_fc"] = fcda.Fc
  2045. obj["attr_do_name"] = fcda.DoName
  2046. obj["attr_da_name"] = fcda.DaName
  2047. var ld *node_attr.NLDevice
  2048. ld, ln_desc, doi_desc = c.GetFcdaDesc(sIed, fcda)
  2049. if ld != nil {
  2050. obj["attr_ld_desc"] = ld.Desc
  2051. }
  2052. /*
  2053. for _, ied := range sIed.AccessPoint {
  2054. if ied.Server != nil {
  2055. for _, ld := range ied.Server.LDevice {
  2056. //logger.Logger.Debug(fmt.Sprintf(" ld========%s=============%s", ld.Inst, fcda.LdInst))
  2057. if ld.Inst == fcda.LdInst {
  2058. obj["attr_ld_desc"] = ld.Desc
  2059. if fcda.LnClass == "LLN0" {
  2060. ln_desc = ld.LN0.Desc
  2061. for _, doi := range ld.LN0.DOI {
  2062. if doi.Name == fcda.DoName {
  2063. doi_desc = doi.Desc
  2064. break
  2065. }
  2066. }
  2067. break
  2068. }
  2069. for _, ln := range ld.LN {
  2070. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  2071. ln_desc = ln.Desc
  2072. //logger.Logger.Debug(fmt.Sprintf(" LN=====================%+v", ln))
  2073. for _, doi := range ln.DOI {
  2074. if doi.Name == fcda.DoName {
  2075. doi_desc = doi.Desc
  2076. break
  2077. }
  2078. }
  2079. }
  2080. if doi_desc != "" {
  2081. break
  2082. }
  2083. }
  2084. }
  2085. if doi_desc != "" {
  2086. break
  2087. }
  2088. }
  2089. }
  2090. if doi_desc != "" {
  2091. break
  2092. }
  2093. }
  2094. */
  2095. }
  2096. obj["from_doi_desc"] = doi_desc
  2097. obj["from_ln_desc"] = ln_desc
  2098. //主IED向外输出,根据接收IED的extref的内部地址查找to_doi等信息
  2099. extrefidint64, _ := strconv.ParseInt(extrefid, 10, 64)
  2100. nodeInfo = cacheNodeList[extrefidint64]
  2101. ln_desc = ""
  2102. doi_desc = ""
  2103. var ld *node_attr.NLDevice
  2104. if nodeInfo.ObjAddr != nil {
  2105. extref := nodeInfo.ObjAddr.(*node_attr.NExtRef)
  2106. //logger.Logger.Debug(fmt.Sprintf("extref %s info:%+v", extrefid, extref))
  2107. obj["attr_int_addr"] = extref.IntAddr
  2108. ld, ln_desc, doi_desc = c.GetIntAddrDesc(mIed, extref.IntAddr)
  2109. if ld != nil {
  2110. obj["to_ld_inst"] = ld.Inst
  2111. obj["to_ld_desc"] = ld.Desc
  2112. }
  2113. /*
  2114. addrparts := strings.Split(extref.IntAddr, "/")
  2115. to_ldinst := addrparts[0]
  2116. //to_lnPri := addrparts[1] //ln标识符,由prefix+lnClass+inst.doname.daname组成
  2117. to_lnPriParts := strings.Split(addrparts[1], ".")
  2118. to_doname := to_lnPriParts[1]
  2119. for _, ied := range mIed.AccessPoint {
  2120. if ied.Server != nil {
  2121. for _, ld := range ied.Server.LDevice {
  2122. if ld.Inst == to_ldinst {
  2123. obj["to_ld_inst"] = ld.Inst
  2124. obj["to_ld_desc"] = ld.Desc
  2125. for _, ln := range ld.LN {
  2126. //logger.Logger.Debug(fmt.Sprintf("to: %s==%s", ln.Prefix+ln.LnClass+ln.Inst, to_lnPriParts[0]))
  2127. if (ln.Prefix + ln.LnClass + ln.Inst) == to_lnPriParts[0] {
  2128. ln_desc = ln.Desc
  2129. for _, doi := range ln.DOI {
  2130. if doi.Name == to_doname {
  2131. doi_desc = doi.Desc
  2132. break
  2133. }
  2134. }
  2135. }
  2136. if doi_desc != "" {
  2137. break
  2138. }
  2139. }
  2140. }
  2141. if doi_desc != "" {
  2142. break
  2143. }
  2144. }
  2145. }
  2146. if doi_desc != "" {
  2147. break
  2148. }
  2149. }*/
  2150. }
  2151. obj["to_doi_desc"] = doi_desc
  2152. obj["to_ln_desc"] = ln_desc
  2153. rowset = append(rowset, obj)
  2154. }
  2155. }
  2156. return rowset, nil
  2157. }
  2158. //获取指定FCDA的do或者Da描述
  2159. func (c *ScdNode) GetFcdaDesc(mIed *node_attr.NIED, fcda *node_attr.NFCDA) (rld *node_attr.NLDevice, lndesc string, dodesc string) {
  2160. doi_desc := ""
  2161. ln_desc := ""
  2162. if mIed == nil || fcda == nil {
  2163. return nil, ln_desc, doi_desc
  2164. }
  2165. doParts := strings.Split(fcda.DoName, ".") //拆分do中的有效name部分
  2166. to_doname := doParts[0]
  2167. for _, ied := range mIed.AccessPoint {
  2168. if ied.Server != nil {
  2169. for _, ld := range ied.Server.LDevice {
  2170. //logger.Logger.Debug(fmt.Sprintf(" ld========%s=============%s", ld.Inst, fcda.LdInst))
  2171. if ld.Inst == fcda.LdInst {
  2172. rld = ld
  2173. if fcda.LnClass == "LLN0" {
  2174. ln_desc = ld.LN0.Desc
  2175. for _, doi := range ld.LN0.DOI {
  2176. if doi.Name == to_doname {
  2177. doi_desc = doi.Desc
  2178. break
  2179. }
  2180. }
  2181. break
  2182. }
  2183. for _, ln := range ld.LN {
  2184. if ln.Inst == fcda.LnInst && ln.LnClass == fcda.LnClass && ln.Prefix == fcda.Prefix {
  2185. ln_desc = ln.Desc
  2186. //logger.Logger.Debug(fmt.Sprintf(" LN=====================%+v", ln))
  2187. for _, doi := range ln.DOI {
  2188. if doi.Name == to_doname {
  2189. doi_desc = doi.Desc
  2190. break
  2191. }
  2192. }
  2193. }
  2194. if doi_desc != "" {
  2195. break
  2196. }
  2197. }
  2198. }
  2199. if doi_desc != "" {
  2200. break
  2201. }
  2202. }
  2203. }
  2204. if doi_desc != "" {
  2205. break
  2206. }
  2207. }
  2208. return rld, ln_desc, doi_desc
  2209. }
  2210. //获取指定Extref的本地描述
  2211. func (c *ScdNode) GetIntAddrDesc(mIed *node_attr.NIED, intAddr string) (rld *node_attr.NLDevice, lndesc string, dodesc string) {
  2212. doi_desc := ""
  2213. ln_desc := ""
  2214. if mIed == nil || intAddr == "" {
  2215. return nil, ln_desc, doi_desc
  2216. }
  2217. addrs := strings.Split(intAddr, ":")
  2218. if len(addrs) == 2 {
  2219. intAddr = addrs[1]
  2220. }
  2221. addrparts := strings.Split(intAddr, "/")
  2222. to_ldinst := addrparts[0]
  2223. //addrparts[1] //ln标识符,由prefix+lnClass+inst.doname.daname组成
  2224. to_lnPriParts := strings.Split(addrparts[1], ".")
  2225. to_doname := to_lnPriParts[1]
  2226. for _, ied := range mIed.AccessPoint {
  2227. if ied.Server != nil {
  2228. for _, ld := range ied.Server.LDevice {
  2229. if ld.Inst == to_ldinst {
  2230. rld = ld
  2231. for _, ln := range ld.LN {
  2232. //logger.Logger.Debug(fmt.Sprintf("to: %s==%s", ln.Prefix+ln.LnClass+ln.Inst, to_lnPriParts[0]))
  2233. if (ln.Prefix + ln.LnClass + ln.Inst) == to_lnPriParts[0] {
  2234. ln_desc = ln.Desc
  2235. for _, doi := range ln.DOI {
  2236. if doi.Name == to_doname {
  2237. doi_desc = doi.Desc
  2238. break
  2239. }
  2240. }
  2241. }
  2242. if doi_desc != "" {
  2243. break
  2244. }
  2245. }
  2246. }
  2247. if doi_desc != "" {
  2248. break
  2249. }
  2250. }
  2251. }
  2252. if doi_desc != "" {
  2253. break
  2254. }
  2255. }
  2256. return rld, ln_desc, doi_desc
  2257. }
  2258. //获取指定IED的网络配置信息
  2259. func (c *ScdNode) GetIedNetworkInfo(scdid int64, ied_name string) ([]orm.Params, error) {
  2260. cacheKey := fmt.Sprintf("networkinfo_%d", scdid)
  2261. if scdid == 0 {
  2262. return nil, errors.New("SCD编号不能为空")
  2263. }
  2264. if ied_name == "" {
  2265. return nil, errors.New("IED名称不能为空")
  2266. }
  2267. networkInfo := []orm.Params{}
  2268. cachedata, h := global.GoCahce.Get(cacheKey)
  2269. if h {
  2270. t1 := cachedata.([]orm.Params)
  2271. if ied_name != "" {
  2272. for _, row := range t1 {
  2273. if row["ied_name"] == ied_name {
  2274. networkInfo = append(networkInfo, row)
  2275. }
  2276. }
  2277. } else {
  2278. networkInfo = t1
  2279. }
  2280. return networkInfo, nil
  2281. }
  2282. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2283. if serr != nil {
  2284. return nil, serr
  2285. }
  2286. if scdXmlObj == nil {
  2287. return nil, errors.New("无效的SCD")
  2288. }
  2289. iedList := []orm.Params{}
  2290. for _, item1 := range scdXmlObj.Communication.SubNetwork {
  2291. net_type := "GSE"
  2292. if len(item1.Name) >= 3 && item1.Name[0:3] == "MMS" {
  2293. net_type = "MMS"
  2294. }
  2295. for _, item2 := range item1.ConnectedAP {
  2296. if len(item2.SMV) > 0 {
  2297. net_type = "SV"
  2298. for _, svitem := range item2.SMV {
  2299. obj := orm.Params{
  2300. "ap_node_id": item2.NodeId,
  2301. "ied_name": item2.IedName,
  2302. "ap_name": item2.ApName,
  2303. "subnetwork_name": item1.Name,
  2304. "subnetwork_desc": item1.Desc,
  2305. "subnetwork_type": item1.Type,
  2306. "net_type": net_type,
  2307. "net_node_id": svitem.NodeId,
  2308. "cb_name": svitem.CbName,
  2309. "ld_inst": svitem.LdInst,
  2310. "address_json": "",
  2311. }
  2312. if svitem.Address != nil {
  2313. jsonmap := map[string]string{}
  2314. for _, r1 := range svitem.Address.P {
  2315. jsonmap[r1.Type] = r1.InnerText
  2316. }
  2317. jsnstr, _ := json.Marshal(jsonmap)
  2318. obj["address_json"] = string(jsnstr)
  2319. }
  2320. networkInfo = append(networkInfo, obj)
  2321. if ied_name != "" && ied_name == item2.IedName {
  2322. iedList = append(iedList, obj)
  2323. }
  2324. }
  2325. } else if len(item2.GSE) > 0 {
  2326. net_type = "GSE"
  2327. for _, gseitem := range item2.GSE {
  2328. obj := orm.Params{
  2329. "ap_node_id": item2.NodeId,
  2330. "ied_name": item2.IedName,
  2331. "ap_name": item2.ApName,
  2332. "subnetwork_name": item1.Name,
  2333. "subnetwork_desc": item1.Desc,
  2334. "subnetwork_type": item1.Type,
  2335. "net_type": net_type,
  2336. "net_node_id": gseitem.NodeId,
  2337. "cb_name": gseitem.CbName,
  2338. "ld_inst": gseitem.LdInst,
  2339. "address_json": "",
  2340. }
  2341. if gseitem.Address != nil {
  2342. jsonmap := map[string]string{}
  2343. for _, r1 := range gseitem.Address.P {
  2344. jsonmap[r1.Type] = r1.InnerText
  2345. }
  2346. jsnstr, _ := json.Marshal(jsonmap)
  2347. obj["address_json"] = string(jsnstr)
  2348. }
  2349. networkInfo = append(networkInfo, obj)
  2350. if ied_name != "" && ied_name == item2.IedName {
  2351. iedList = append(iedList, obj)
  2352. }
  2353. }
  2354. } else {
  2355. obj := orm.Params{
  2356. "ap_node_id": item2.NodeId,
  2357. "ied_name": item2.IedName,
  2358. "ap_name": item2.ApName,
  2359. "subnetwork_name": item1.Name,
  2360. "subnetwork_desc": item1.Desc,
  2361. "subnetwork_type": item1.Type,
  2362. "net_type": net_type,
  2363. "net_node_id": item2.NodeId,
  2364. "cb_name": "",
  2365. "ld_inst": "",
  2366. "address_json": "",
  2367. }
  2368. if item2.Address != nil {
  2369. jsonmap := map[string]string{}
  2370. for _, r1 := range item2.Address.P {
  2371. jsonmap[r1.Type] = r1.InnerText
  2372. }
  2373. jsnstr, _ := json.Marshal(jsonmap)
  2374. obj["address_json"] = string(jsnstr)
  2375. }
  2376. networkInfo = append(networkInfo, obj)
  2377. if ied_name != "" && ied_name == item2.IedName {
  2378. iedList = append(iedList, obj)
  2379. }
  2380. }
  2381. }
  2382. }
  2383. global.GoCahce.Set(cacheKey, networkInfo, -1)
  2384. if ied_name != "" {
  2385. return iedList, nil
  2386. }
  2387. return networkInfo, nil
  2388. }
  2389. //获取指定IEd的指定GSEControl的网络配置信息
  2390. func (c *ScdNode) GetIedGseNetWorkInfo(scdid int64, ied_name, gocb_name string) (orm.Params, error) {
  2391. if scdid == 0 {
  2392. return nil, errors.New("SCD编号不能为空")
  2393. }
  2394. if ied_name == "" {
  2395. return nil, errors.New("IED名称不能为空")
  2396. }
  2397. if gocb_name == "" {
  2398. return nil, errors.New("gocb_name不能为空")
  2399. }
  2400. iedNetinfo, er := c.GetIedNetworkInfo(scdid, ied_name)
  2401. if er != nil {
  2402. return nil, er
  2403. }
  2404. for _, row := range iedNetinfo {
  2405. cb_name := tools.IsEmpty(row["cb_name"])
  2406. if cb_name == gocb_name {
  2407. return row, nil
  2408. }
  2409. }
  2410. return nil, nil
  2411. }
  2412. func (c *ScdNode) Init(stationidint int, name, path string, isenable int, ischeckinscd int) (int64, error) {
  2413. c.ScdName = name
  2414. c.ScdPath = path
  2415. c.StationID = stationidint
  2416. c.NodeRuleList = map[string][]orm.Params{}
  2417. c.NodeAttrRuleList = map[string][]orm.Params{}
  2418. c.NodeAttrUniqueRuleList = []orm.Params{}
  2419. c.NodeRuleFunctionList = []orm.Params{}
  2420. c.NotEndNodeIdList = []int64{}
  2421. c.NodeQue = map[int64]*t_scd_node_scl{}
  2422. c.NodeAttrQue = []interface{}{}
  2423. c.AreaMgr = new(ScdAreaMgr)
  2424. m := t_scd_scl{ScdName: name, Path: path}
  2425. m.IsCheckinScd = ischeckinscd
  2426. m.Enable = isenable
  2427. m.StationId = stationidint
  2428. if c.RootID > 0 {
  2429. m.Id = c.RootID
  2430. }
  2431. c.AreaMgr.ScdId = m.Id
  2432. m.CreatedBy, _ = strconv.Atoi(c.GetUserId())
  2433. m.CreatedTime = tools.NowTime()
  2434. db := orm.NewOrm()
  2435. _, err := db.Insert(&m)
  2436. if err != nil {
  2437. //判断SCD是否已经存在
  2438. if !strings.Contains(err.Error(), "PRIMARY") {
  2439. logger.Logger.Error(err, fmt.Sprintf("操作数据:%+v", m))
  2440. return 0, err
  2441. }
  2442. }
  2443. c.Name = name
  2444. //初始化间隔管理
  2445. c.AreaMgr.ScdId = m.Id //再次赋值,保证当scd不存在时,获取到新添加的SCD ID
  2446. c.AreaMgr.Init(m.Id)
  2447. //加载规则列表
  2448. //获取节点验证规则定义
  2449. lst := []orm.Params{}
  2450. /*
  2451. db.Raw("select * from t_scd_node_check").Values(&lst)
  2452. for _, r := range lst {
  2453. check_object := r["check_object"].(string)
  2454. keys := strings.Split(check_object, ":")
  2455. if ss, ok := c.NodeRuleList[keys[0]]; ok {
  2456. c.NodeRuleList[keys[0]] = append(ss, r)
  2457. } else {
  2458. c.NodeRuleList[keys[0]] = []orm.Params{r}
  2459. }
  2460. }
  2461. */
  2462. //获取节点属性验证规则
  2463. db.Raw("select * from t_scd_scl_check").Values(&lst)
  2464. for _, r := range lst {
  2465. object_name := r["object_name"].(string)
  2466. object_type := r["object_type"].(string)
  2467. if tools.IsEmpty(r["func_name"]) != "" {
  2468. c.NodeRuleFunctionList = append(c.NodeRuleFunctionList, r)
  2469. continue
  2470. }
  2471. //过滤出全局唯一或父节点下唯一的规则单独保存
  2472. if tools.IsEmpty(r["isunique_by_parent"]) == "1" || tools.IsEmpty(r["isunique_by_global"]) == "1" {
  2473. c.NodeAttrUniqueRuleList = append(c.NodeAttrUniqueRuleList, r)
  2474. continue
  2475. }
  2476. if object_type == "node" {
  2477. if ss, ok := c.NodeRuleList[object_name]; ok {
  2478. c.NodeRuleList[object_name] = append(ss, r)
  2479. } else {
  2480. c.NodeRuleList[object_name] = []orm.Params{r}
  2481. }
  2482. } else {
  2483. //node_path := tools.IsEmpty(r["node_path"])
  2484. keys := strings.Split(object_name, "||")
  2485. for _, k := range keys {
  2486. if ss, ok := c.NodeAttrRuleList[k]; ok {
  2487. c.NodeAttrRuleList[k] = append(ss, r)
  2488. } else {
  2489. c.NodeAttrRuleList[k] = []orm.Params{r}
  2490. }
  2491. }
  2492. }
  2493. }
  2494. return m.Id, nil
  2495. }
  2496. func (c *ScdNode) AddNode(name string, attrs map[string]interface{}, lineno int64) error {
  2497. m := new(t_scd_node_scl)
  2498. m.CreatedBy = 0
  2499. m.CreatedTime = tools.NowTime()
  2500. m.NodeName = name
  2501. m.NodeValue = ""
  2502. m.LineNo = lineno
  2503. m.ScdId = c.RootID
  2504. m.Id = c.GetID()
  2505. c.NodeQue[m.Id] = m
  2506. if attrs != nil && len(attrs) > 0 {
  2507. if name == "Bay" {
  2508. //如果存在bay元素,则间隔方式为Bay解析
  2509. c.IsBay = true
  2510. }
  2511. parentNodeNodeName := ""
  2512. parentNode, ok := c.NodeQue[m.ParentNodeId]
  2513. if ok {
  2514. parentNodeNodeName = parentNode.NodeName
  2515. }
  2516. c.NodeAttrQue = append(c.NodeAttrQue, map[string]interface{}{"scdid": c.RootID, "parentNodeName": parentNodeNodeName, "nodeid": m.Id, "nodename": name, "lineno": m.LineNo, "attrs": attrs})
  2517. if !c.IsBay && m.NodeName == "IED" {
  2518. c.AreaMgr.AppendIedNode(c.RootID, m.Id, tools.IsEmpty(attrs["name"]), tools.IsEmpty(attrs["desc"]))
  2519. }
  2520. }
  2521. return nil
  2522. }
  2523. func (c *ScdNode) EndNode(name, txt string) error {
  2524. return nil
  2525. }
  2526. func (c *ScdNode) Flush() {
  2527. //更新关联附件项的scd id
  2528. new(AttachmentMgr).UpdateScdID(c.StationID, c.ScdName, c.ScdPath, c.RootID)
  2529. //c.writeNodeDB()
  2530. //c.writeNodeAttrDB()
  2531. //通知SCD管理对象,解析完成,更新状态
  2532. new(ScdMgr).ParseFinish(c.RootID, c.IsDefaultRunVersion)
  2533. //test
  2534. //c.GetIedInputsRelations(map[string]interface{}{"scd_id": c.RootID, "ied_name": "PB7520A"})
  2535. /*
  2536. if c.AutoCompScdID > 0 {
  2537. comp := new(ScdCompare)
  2538. comp.CompareType = "SCD"
  2539. comp.Sourceid = c.RootID
  2540. comp.Targetid = c.AutoCompScdID
  2541. comp.StationId = c.StationID
  2542. comp.Compare(0)
  2543. }
  2544. */
  2545. }
  2546. //获取指定SCD的校验码
  2547. func (c *ScdNode) GetScdCRC(scdid string) (string, error) {
  2548. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  2549. if serr != nil {
  2550. return "", serr
  2551. }
  2552. if scdXmlObj == nil {
  2553. return "", errors.New("无效的SCD")
  2554. }
  2555. for _, pri := range scdXmlObj.Private {
  2556. if pri.Type == "Substation virtual terminal conection CRC" {
  2557. return pri.InnerText, nil
  2558. }
  2559. }
  2560. return "", nil
  2561. }
  2562. //获取指定SCD的校验码
  2563. func (c *ScdNode) GetIedCRC(scdid, iedname string) (string, error) {
  2564. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
  2565. if serr != nil {
  2566. return "", serr
  2567. }
  2568. if scdXmlObj == nil {
  2569. return "", errors.New("无效的SCD")
  2570. }
  2571. iedObj := c.GetIed(scdXmlObj, scdid, iedname)
  2572. if iedObj == nil {
  2573. return "", errors.New("无效的IED装置名称")
  2574. }
  2575. for _, pri := range iedObj.Priavate {
  2576. if pri.Type == "IED virtual terminal conection CRC" {
  2577. return pri.InnerText, nil
  2578. }
  2579. }
  2580. return "", nil
  2581. }
  2582. func (c *ScdNode) writeNodeDB() {
  2583. stationIdStr := fmt.Sprintf("%d", c.StationID)
  2584. scdIdStr := fmt.Sprintf("%d", c.RootID)
  2585. db := orm.NewOrm()
  2586. s1 := time.Now().Unix()
  2587. nodeCols := "(id,scd_id,parent_node_id,node_name,node_value,line_no)"
  2588. totalRec := tools.IsEmpty(len(c.NodeQue))
  2589. loadedRec := 0
  2590. nodeSqlValuesAry := []string{}
  2591. data := map[string]string{"name": c.Name, "stationid": stationIdStr, "rootid": scdIdStr, "state": "0", "node": "write-db", "total": totalRec, "load": fmt.Sprintf("%d", loadedRec), "msg": ""}
  2592. dataMsg, _ := json.Marshal(data)
  2593. go mqtt.PublishMessage("/jujutong/scd_check_tools/parse/"+scdIdStr, string(dataMsg))
  2594. for _, m := range c.NodeQue {
  2595. nodeSqlValuesAry = append(nodeSqlValuesAry, fmt.Sprintf("(%d,%d,%d,'%s','%s',%d)", m.Id, m.ScdId, m.ParentNodeId, m.NodeName, m.NodeValue, m.LineNo))
  2596. if len(nodeSqlValuesAry) == 5000 {
  2597. sql := "insert into t_scd_node_scl" + nodeCols + "values" + strings.Join(nodeSqlValuesAry, ",")
  2598. _, err := db.Raw(sql).Exec()
  2599. if err != nil {
  2600. logger.Logger.Error(err)
  2601. }
  2602. loadedRec = loadedRec + 5000
  2603. nodeSqlValuesAry = []string{}
  2604. data = map[string]string{"name": c.Name, "stationid": stationIdStr, "rootid": scdIdStr, "state": "2", "node": "write-db", "total": totalRec, "load": fmt.Sprintf("%d", loadedRec), "msg": ""}
  2605. dataMsg, _ = json.Marshal(data)
  2606. go mqtt.PublishMessage("/jujutong/scd_check_tools/parse/"+scdIdStr, string(dataMsg))
  2607. }
  2608. m = nil
  2609. }
  2610. if len(nodeSqlValuesAry) > 0 {
  2611. sql := "insert into t_scd_node_scl" + nodeCols + "values" + strings.Join(nodeSqlValuesAry, ",")
  2612. _, err := db.Raw(sql).Exec()
  2613. if err != nil {
  2614. log.Println(err)
  2615. }
  2616. nodeSqlValuesAry = nil
  2617. }
  2618. c.NodeQue = nil
  2619. runtime.GC()
  2620. 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": ""}
  2621. dataMsg, _ = json.Marshal(data)
  2622. go mqtt.PublishMessage("/jujutong/scd_check_tools/parse/"+fmt.Sprintf("%d", c.RootID), string(dataMsg))
  2623. s2 := time.Now().Unix()
  2624. logger.Logger.Println(fmt.Sprintf("===================Flush NodeQue 完成!。耗时:%d秒", s2-s1))
  2625. logger.Logger.Println("===========节点入库完成")
  2626. }
  2627. //查询定值
  2628. func (t *ScdNode) GetScdIedDingzhiList(scdid int64, ied_name string) ([]orm.Params, error) {
  2629. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2630. if serr != nil {
  2631. return nil, serr
  2632. }
  2633. if scdXmlObj == nil {
  2634. return nil, errors.New("无效的SCD")
  2635. }
  2636. iedObj := t.GetIed(scdXmlObj, tools.IsEmpty(scdid), ied_name)
  2637. if iedObj == nil {
  2638. return nil, errors.New("无效的IED装置名称")
  2639. }
  2640. scdMgr := new(ScdMgr)
  2641. mapTargetLNodeType := scdMgr.GetLNodeType(scdXmlObj)
  2642. mapTargetLDoType := scdMgr.GetDOType(scdXmlObj)
  2643. rowset := []orm.Params{}
  2644. for _, acc := range iedObj.AccessPoint {
  2645. if acc.Server != nil {
  2646. for _, ld := range acc.Server.LDevice {
  2647. if ld.LN0 != nil {
  2648. for _, ds := range ld.LN0.DataSet {
  2649. if ds.Name == "dsParameter" || ds.Name == "dsSetting" {
  2650. obj := orm.Params{
  2651. "accesspoint_name": acc.Name,
  2652. "ld_desc": ld.Desc,
  2653. "ld_name": ld.Inst,
  2654. "dataset_desc": ds.Desc,
  2655. "dataset_name": ds.Name,
  2656. "list": []orm.Params{},
  2657. }
  2658. for _, fcda := range ds.FCDA {
  2659. fcdaobj := orm.Params{}
  2660. fcdaobj["short_addr"] = fmt.Sprintf("%s/%s%s%s.%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName)
  2661. fcdaobj["doi_name"] = fcda.DoName
  2662. fcdaobj["doi_desc"] = ""
  2663. fcdaobj["da_maxval"] = ""
  2664. fcdaobj["da_minval"] = ""
  2665. fcdaobj["da_stepsize"] = ""
  2666. fcdaobj["da_units"] = ""
  2667. found := false
  2668. if fcda.LnClass == "LLN0" {
  2669. if lnnodetpye, h := mapTargetLNodeType[ld.LN0.LnType]; h {
  2670. for _, doitem := range lnnodetpye.DO {
  2671. if doitem.Name == fcda.DoName {
  2672. dotype := doitem.Type
  2673. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2674. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2675. }
  2676. break
  2677. }
  2678. }
  2679. }
  2680. for _, doi := range ld.LN0.DOI {
  2681. if doi.Name == fcda.DoName {
  2682. fcdaobj["doi_desc"] = doi.Desc
  2683. for _, da := range doi.DAI {
  2684. if da.Name == "maxVal" && da.Val != nil {
  2685. fcdaobj["da_maxval"] = da.Val.InnerText
  2686. }
  2687. if da.Name == "minVal" && da.Val != nil {
  2688. fcdaobj["da_minval"] = da.Val.InnerText
  2689. }
  2690. if da.Name == "stepSize" && da.Val != nil {
  2691. fcdaobj["da_stepsize"] = da.Val.InnerText
  2692. }
  2693. if da.Name == "units" && da.Val != nil {
  2694. fcdaobj["da_units"] = da.Val.InnerText
  2695. }
  2696. }
  2697. found = true
  2698. break
  2699. }
  2700. }
  2701. } else {
  2702. for _, ln := range ld.LN {
  2703. if ln.LnClass == fcda.LnClass && ln.Inst == fcda.LnInst {
  2704. if lnnodetpye, h := mapTargetLNodeType[ln.LnType]; h {
  2705. for _, doitem := range lnnodetpye.DO {
  2706. if doitem.Name == fcda.DoName {
  2707. dotype := doitem.Type
  2708. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2709. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2710. }
  2711. break
  2712. }
  2713. }
  2714. }
  2715. for _, doi := range ln.DOI {
  2716. if doi.Name == fcda.DoName {
  2717. fcdaobj["doi_desc"] = doi.Desc
  2718. for _, da := range doi.DAI {
  2719. if da.Name == "maxVal" && da.Val != nil {
  2720. fcdaobj["da_maxval"] = da.Val.InnerText
  2721. }
  2722. if da.Name == "minVal" && da.Val != nil {
  2723. fcdaobj["da_minval"] = da.Val.InnerText
  2724. }
  2725. if da.Name == "stepSize" && da.Val != nil {
  2726. fcdaobj["da_stepsize"] = da.Val.InnerText
  2727. }
  2728. if da.Name == "units" && da.Val != nil {
  2729. fcdaobj["da_units"] = da.Val.InnerText
  2730. }
  2731. }
  2732. if fcdaobj["da_maxval"] == "" {
  2733. for _, sdi := range doi.SDI {
  2734. if sdi.Name == "maxVal" {
  2735. for _, dai2 := range sdi.DAI {
  2736. if dai2.Name == "f" && dai2.Val != nil {
  2737. fcdaobj["da_maxval"] = dai2.Val.InnerText
  2738. }
  2739. }
  2740. }
  2741. }
  2742. }
  2743. if fcdaobj["da_minval"] == "" {
  2744. for _, sdi := range doi.SDI {
  2745. if sdi.Name == "minVal" {
  2746. for _, dai2 := range sdi.DAI {
  2747. if dai2.Name == "f" && dai2.Val != nil {
  2748. fcdaobj["da_minval"] = dai2.Val.InnerText
  2749. }
  2750. }
  2751. }
  2752. }
  2753. }
  2754. if fcdaobj["da_stepsize"] == "" {
  2755. for _, sdi := range doi.SDI {
  2756. if sdi.Name == "stepSize" {
  2757. for _, dai2 := range sdi.DAI {
  2758. if dai2.Name == "f" && dai2.Val != nil {
  2759. fcdaobj["da_stepsize"] = dai2.Val.InnerText
  2760. }
  2761. }
  2762. }
  2763. }
  2764. }
  2765. unintsFound := false
  2766. if fcdaobj["da_units"] == "" {
  2767. for _, sdi := range doi.SDI {
  2768. if sdi.Name == "units" {
  2769. for _, dai2 := range sdi.DAI {
  2770. if dai2.Name == "SIUnit" {
  2771. for _, enumtype := range scdXmlObj.DataTypeTemplates.EnumType {
  2772. if enumtype.Id == dai2.Name {
  2773. for _, t123 := range enumtype.EnumVal {
  2774. if dai2.Val == nil {
  2775. fcdaobj["da_units"] = ""
  2776. } else if t123.Ord == dai2.Val.InnerText {
  2777. fcdaobj["da_units"] = t123.InnerText
  2778. unintsFound = true
  2779. break
  2780. }
  2781. }
  2782. }
  2783. if unintsFound {
  2784. break
  2785. }
  2786. }
  2787. }
  2788. if unintsFound {
  2789. break
  2790. }
  2791. }
  2792. }
  2793. if unintsFound {
  2794. break
  2795. }
  2796. }
  2797. }
  2798. found = true
  2799. break
  2800. }
  2801. }
  2802. }
  2803. if found {
  2804. break
  2805. }
  2806. }
  2807. }
  2808. obj["list"] = append(obj["list"].([]orm.Params), fcdaobj)
  2809. }
  2810. rowset = append(rowset, obj)
  2811. }
  2812. }
  2813. }
  2814. }
  2815. }
  2816. }
  2817. return rowset, nil
  2818. }
  2819. //查询信息点表
  2820. func (t *ScdNode) GetScdIedPointTableList(scdid int64, ied_name string) ([]orm.Params, error) {
  2821. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2822. if serr != nil {
  2823. return nil, serr
  2824. }
  2825. if scdXmlObj == nil {
  2826. return nil, errors.New("无效的SCD")
  2827. }
  2828. iedObj := t.GetIed(scdXmlObj, tools.IsEmpty(scdid), ied_name)
  2829. if iedObj == nil {
  2830. return nil, errors.New("无效的IED装置名称")
  2831. }
  2832. scdMgr := new(ScdMgr)
  2833. mapTargetLNodeType := scdMgr.GetLNodeType(scdXmlObj)
  2834. mapTargetLDoType := scdMgr.GetDOType(scdXmlObj)
  2835. rowset := []orm.Params{}
  2836. for _, acc := range iedObj.AccessPoint {
  2837. if acc.Server != nil {
  2838. for _, ld := range acc.Server.LDevice {
  2839. if ld.LN0 != nil {
  2840. for _, rpc := range ld.LN0.ReportControl {
  2841. obj := orm.Params{
  2842. "accesspoint_name": acc.Name,
  2843. "ld_desc": ld.Desc,
  2844. "ld_inst": ld.Inst,
  2845. "block_desc": rpc.Desc,
  2846. "block_name": rpc.Name,
  2847. "block_datset": rpc.DatSet,
  2848. "block_rptid": rpc.RptID,
  2849. "block_intgpd": rpc.IntgPd,
  2850. "block_confrev": rpc.ConfRev,
  2851. "block_buftime": rpc.BufTime,
  2852. "block_buffered": rpc.Buffered,
  2853. "list": []orm.Params{},
  2854. }
  2855. for _, ds := range ld.LN0.DataSet {
  2856. if ds.Name == rpc.DatSet {
  2857. for _, fcda := range ds.FCDA {
  2858. fcdaobj := orm.Params{
  2859. "short_addr": fmt.Sprintf("%s/%s%s%s.%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName),
  2860. "doi_name": fcda.DoName,
  2861. "doi_desc": "",
  2862. }
  2863. found := false
  2864. if fcda.LnClass == "LLN0" {
  2865. if lnnodetpye, h := mapTargetLNodeType[ld.LN0.LnType]; h {
  2866. for _, doitem := range lnnodetpye.DO {
  2867. if doitem.Name == fcda.DoName {
  2868. dotype := doitem.Type
  2869. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2870. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2871. }
  2872. break
  2873. }
  2874. }
  2875. }
  2876. for _, doi := range ld.LN0.DOI {
  2877. if doi.Name == fcda.DoName {
  2878. fcdaobj["doi_desc"] = doi.Desc
  2879. found = true
  2880. break
  2881. }
  2882. }
  2883. } else {
  2884. for _, ln := range ld.LN {
  2885. if ln.LnClass == fcda.LnClass && ln.Inst == fcda.LnInst {
  2886. if lnnodetpye, h := mapTargetLNodeType[ln.LnType]; h {
  2887. for _, doitem := range lnnodetpye.DO {
  2888. if doitem.Name == fcda.DoName {
  2889. dotype := doitem.Type
  2890. if dotypeobj, h := mapTargetLDoType[dotype]; h {
  2891. fcdaobj["da_datatype"] = scdMgr.GetCdcDataTypeName(dotypeobj.Cdc)
  2892. }
  2893. break
  2894. }
  2895. }
  2896. }
  2897. for _, doi := range ln.DOI {
  2898. if doi.Name == fcda.DoName {
  2899. fcdaobj["doi_desc"] = doi.Desc
  2900. found = true
  2901. break
  2902. }
  2903. }
  2904. }
  2905. if found {
  2906. break
  2907. }
  2908. }
  2909. }
  2910. obj["list"] = append(obj["list"].([]orm.Params), fcdaobj)
  2911. }
  2912. break
  2913. }
  2914. }
  2915. rowset = append(rowset, obj)
  2916. }
  2917. }
  2918. }
  2919. }
  2920. }
  2921. return rowset, nil
  2922. }
  2923. //查询源XML
  2924. func (t *ScdNode) GetScdIedSourceXML(scdid int64, ied_name string) (string, error) {
  2925. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2926. if serr != nil {
  2927. return "", serr
  2928. }
  2929. if scdXmlObj == nil {
  2930. return "", errors.New("无效的SCD")
  2931. }
  2932. startLineNo := int64(0)
  2933. endLineNo := int64(0)
  2934. for _, ied := range scdXmlObj.IED {
  2935. if ied.Name == ied_name {
  2936. //当前ied的开始行号
  2937. startLineNo = ied.Lineno
  2938. } else {
  2939. if startLineNo > 0 {
  2940. //结束行为下一个ied的开始行减1
  2941. endLineNo = ied.Lineno - 1
  2942. break
  2943. }
  2944. }
  2945. }
  2946. //判断是不是最后一ied
  2947. if startLineNo > 0 && endLineNo == 0 {
  2948. //最后一个ied的结束行号
  2949. endLineNo = scdXmlObj.DataTypeTemplates.Lineno - 1
  2950. }
  2951. if startLineNo == 0 {
  2952. return "", errors.New("无效的IED装置名称")
  2953. }
  2954. logger.Logger.Debug(fmt.Sprintf("====startLineNo:%d,endLineNo:%d====", startLineNo, endLineNo))
  2955. scdinfo, _ := new(ScdMgr).One(tools.IsEmpty(scdid))
  2956. scdpath := scdinfo["path"].(string)
  2957. parsedFile := strings.ReplaceAll(scdpath, "\\", "/")
  2958. _, err := os.Stat(parsedFile)
  2959. if err != nil {
  2960. logger.Logger.Error(err)
  2961. return "", err
  2962. }
  2963. f, _ := os.Open(parsedFile)
  2964. reslist := []string{}
  2965. if f != nil {
  2966. defer f.Close()
  2967. r1 := bufio.NewReader(f)
  2968. startLineNo = startLineNo - 1 //跳过第一行xml标记行
  2969. lineno := int64(0) //初始行记数器。
  2970. for {
  2971. txt, err := r1.ReadString('\n')
  2972. if err == io.EOF {
  2973. break
  2974. }
  2975. if lineno >= startLineNo {
  2976. reslist = append(reslist, txt)
  2977. }
  2978. lineno = lineno + 1
  2979. if lineno == endLineNo {
  2980. break
  2981. }
  2982. }
  2983. }
  2984. return strings.Join(reslist, ""), nil
  2985. }
  2986. //查询源XML
  2987. func (t *ScdNode) GetScdLineSourceXML(scdid int64, lineno int64) ([]string, error) {
  2988. scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
  2989. if serr != nil {
  2990. return nil, serr
  2991. }
  2992. if scdXmlObj == nil {
  2993. return nil, errors.New("无效的SCD")
  2994. }
  2995. startLineNo := int64(0)
  2996. endLineNo := int64(0)
  2997. if lineno < 0 {
  2998. lineno = 0
  2999. }
  3000. if lineno < 100 {
  3001. startLineNo = 0 //从最开始获取
  3002. endLineNo = lineno + 100
  3003. } else {
  3004. startLineNo = lineno - 100
  3005. endLineNo = lineno + 100
  3006. }
  3007. logger.Logger.Debug(fmt.Sprintf("====startLineNo:%d,endLineNo:%d====", startLineNo, endLineNo))
  3008. scdinfo, _ := new(ScdMgr).One(tools.IsEmpty(scdid))
  3009. scdpath := scdinfo["path"].(string)
  3010. parsedFile := strings.ReplaceAll(scdpath, "\\", "/")
  3011. _, err := os.Stat(parsedFile)
  3012. if err != nil {
  3013. logger.Logger.Error(err)
  3014. return nil, err
  3015. }
  3016. f, _ := os.Open(parsedFile)
  3017. reslist := []string{}
  3018. if f != nil {
  3019. defer f.Close()
  3020. r1 := bufio.NewReader(f)
  3021. startLineNo = startLineNo - 1 //跳过第一行xml标记行
  3022. c_lineno := int64(0) //初始行记数器。
  3023. for {
  3024. txt, err := r1.ReadString('\n')
  3025. if err == io.EOF {
  3026. break
  3027. }
  3028. if c_lineno >= startLineNo {
  3029. reslist = append(reslist, fmt.Sprintf("%d %s", c_lineno+1, txt))
  3030. }
  3031. c_lineno = c_lineno + 1
  3032. if c_lineno == endLineNo {
  3033. break
  3034. }
  3035. }
  3036. }
  3037. return reslist, nil
  3038. }