scd_node_mgr.go 96 KB

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