12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456 |
- package bo
- import (
- "errors"
- "fmt"
- "scd_check_tools/logger"
- "scd_check_tools/models/enum"
- "scd_check_tools/models/node_attr"
- "scd_check_tools/tools"
- "strconv"
- "strings"
- "sync"
- "github.com/astaxie/beego/orm"
- )
- //检测时间隔管理
- type CheckAreaMgr struct {
- DeviceBaseModel
- //SCD文件ID
- ScdId int64
- //电压等级定义
- VoltageLevelDef map[string]int
- //设备类型定义
- DeviceTypeDef map[string]int
- CacheAreaID map[string]int64
- CacheAreaIDByIedNameNo map[string]int
- //检测模型列表
- CheckModelList []orm.Params
- //模型内装置关系定义
- CheckModelDef sync.Map
- CacheLock sync.RWMutex
- }
- type T_data_check_area struct {
- Id int64 `orm:"pk"`
- AreaName string
- ScdId int64
- VoltageLevel int
- AreaType string
- ModelId int
- Cr int // '创建人' ,
- Ct string `orm:"-"` // '创建时间' ,
- Ur int // '更新人' ,
- Ut string `orm:"-"` // '更新时间'
- }
- type t_data_check_area_ied struct {
- Id int64 `orm:"pk"`
- AreaId int64
- IedName string
- IedType string
- ScdId int64
- PType string
- IedNo string //所属间隔下支路(线路)在SCD中端子实际编号,如在母线间隔下支路9
- Cr int // '创建人' ,
- Ct string `orm:"-"` // '创建时间' ,
- Ur int // '更新人' ,
- Ut string `orm:"-"` // '更新时间'
- }
- func init() {
- orm.RegisterModel(new(T_data_check_area))
- orm.RegisterModel(new(t_data_check_area_ied))
- }
- func (c *CheckAreaMgr) Init(scdid int64) {
- c.VoltageLevelDef = map[string]int{}
- c.DeviceTypeDef = map[string]int{}
- c.CacheAreaIDByIedNameNo = map[string]int{}
- c.CacheAreaID = map[string]int64{}
- c.CacheLock = sync.RWMutex{}
- c.ScdId = scdid
- db := orm.NewOrm()
- rowset := []orm.Params{}
- db.Raw("select * from global_const_code where parentcode=?", "voltage_level").Values(&rowset)
- for _, row := range rowset {
- vl := strings.ToLower(tools.IsEmpty(row["code"]))
- id, _ := strconv.ParseInt(tools.IsEmpty(row["id"]), 10, 32)
- c.VoltageLevelDef[strings.ReplaceAll(vl, "v_level_", "")] = int(id)
- }
- db.Raw("select * from global_const_code where parentcode=?", "device_type").Values(&rowset)
- for _, row := range rowset {
- vl := tools.IsEmpty(row["code"])
- c.DeviceTypeDef[vl] = 1
- }
- v, _ := GetSysParamValue("OtherIedNameList", "")
- otherIedNameList = map[string]bool{}
- if v != "" {
- vs := strings.Split(v, ",")
- for _, vv := range vs {
- otherIedNameList[vv] = true
- }
- }
- //先清除ied与间隔关联关系
- clearSql := "delete from t_data_check_area_ied where area_id in(select id from t_data_check_area where scd_id=?)"
- _, err := db.Raw(clearSql, c.ScdId).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", clearSql, []interface{}{c.ScdId}))
- }
- clearSql = "delete from t_data_check_area where scd_id=?"
- _, err = db.Raw(clearSql, c.ScdId).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", clearSql, []interface{}{c.ScdId}))
- }
- //获取当前scd信息中获取到对应的电压等级id
- /*
- scdMgr := new(ScdMgr)
- scdinfo, _ := scdMgr.One(fmt.Sprintf("%d", c.ScdId))
- stationid := tools.IsEmpty(scdinfo["station_id"])
- volid := 0
- if stationid != "" {
- basearea := new(BasicArea)
- stationonof, _ := basearea.One(stationid)
- volid = stationonof.AreaLevel
- }
- */
- tmplist, _ := new(SysCheckModelMgr).GetModelsByVolid(2)
- scdModels, _, _ := new(TaskMgr).GetModelsByScdID(c.ScdId)
- ms := map[string]interface{}{}
- for _, row := range scdModels {
- ms[tools.IsEmpty(row["model_id"])] = row
- }
- for _, row := range tmplist {
- modelid := tools.IsEmpty(row["id"])
- if ms[modelid] != nil {
- c.CheckModelList = append(c.CheckModelList, row)
- }
- }
- logger.Logger.Debug(fmt.Sprintf("任务的模型列表:%+v", c.CheckModelList))
- ms = nil
- tmplist = nil
- }
- //保存指定间隔所属的电压等级
- func (c *CheckAreaMgr) SetVoltageLevel(id string, voltagelevel int) error {
- db := orm.NewOrm()
- _, err := db.Raw("update t_data_check_area set voltage_level=? where id=?", voltagelevel, id).Exec()
- return err
- }
- //修改指定间隔的名称
- func (c *CheckAreaMgr) UpdateName(scdid int64, area_id int, name string) error {
- db := orm.NewOrm()
- areaM := T_data_check_area{Id: int64(area_id), ScdId: scdid}
- err := db.Read(&areaM)
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- areaM.AreaName = name
- _, err = db.Update(&areaM)
- if err != nil {
- logger.Logger.Error(err)
- }
- return err
- }
- //修改指定IED的所属间隔
- func (c *CheckAreaMgr) UpdateIedArea(scdid int64, iedname string, area_id int) error {
- db := orm.NewOrm()
- _, err := db.Raw("update t_data_check_area_ied set area_id=? where scd_id=? and ied_name=?", area_id, scdid, iedname).Exec()
- return err
- }
- //获取指定scd的间隔信息
- func (c *CheckAreaMgr) GetAreaList(scdid int64) ([]orm.Params, error) {
- db := orm.NewOrm()
- sql := "select t.*,(select count(1) from t_data_check_area_ied where area_id=t.id) iedcount from t_data_check_area t where t.scd_id=? order by t.name"
- rowset := []orm.Params{}
- _, err := db.Raw(sql, scdid).Values(&rowset)
- sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{scdid})
- if err != nil {
- logger.Logger.Error(err, sqllog)
- new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- } else {
- new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- }
- return rowset, nil
- }
- //获取指定scd和电压等级的间隔信息
- func (c *CheckAreaMgr) GetAreaListByVol(scdid int64, vl, linkstyleid int) ([]orm.Params, error) {
- db := orm.NewOrm()
- sql := "select t1.id model_id, t1.model_name,t1.vol_id,g1.name vol_name,t1.line_link_style,ls.name,t.id area_id, t.area_name,t.ut,t.ur from t_data_check_area t right join t_data_model_defualt t1 on t.model_id=t1.id left join t_data_link_style ls on t1.line_link_style=ls.id left join global_const_code g1 on t1.vol_id=g1.id and g1.parentcode='voltage_level' where t.scd_id=? "
- params := []interface{}{scdid}
- if vl > 0 {
- sql = sql + " and t1.vol_id=? "
- params = append(params, vl)
- }
- if linkstyleid > 0 {
- sql = sql + " and t1.line_link_style=? "
- params = append(params, linkstyleid)
- }
- rowset := []orm.Params{}
- _, err := db.Raw(sql+" order by t1.vol_id,t1.line_link_style,t1.id", params).Values(&rowset)
- sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{scdid, vl})
- if err != nil {
- logger.Logger.Error(err, sqllog)
- new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- } else {
- new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- }
- return rowset, nil
- }
- //获取指定间隔下的IED列表
- func (c *CheckAreaMgr) GetIedList(scdid int64, areaid int) ([]orm.Params, error) {
- db := orm.NewOrm()
- sql := "select t1.* from t_data_check_area t,t_data_check_area_ied t1 where t.scd_id=? and t.id=t1.area_id "
- sqlParamters := []interface{}{}
- sqlParamters = append(sqlParamters, scdid)
- if areaid > 0 {
- sql = sql + " and t1.area_id=?"
- sqlParamters = append(sqlParamters, areaid)
- }
- scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
- if serr != nil {
- return nil, serr
- }
- if scdXmlObj == nil {
- return nil, errors.New("无效的SCD")
- }
- rowset := []orm.Params{}
- _, err := db.Raw(sql, sqlParamters).Values(&rowset)
- sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, sqlParamters)
- if err != nil {
- logger.Logger.Error(err, sqllog)
- new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- } else {
- scdNode := new(ScdNode)
- for i, row := range rowset {
- iedObj := scdNode.GetIed(scdXmlObj, tools.IsEmpty(scdid), tools.IsEmpty(row["ied_name"]))
- if iedObj == nil {
- continue
- }
- rowset[i]["attr_name"] = iedObj.Name
- rowset[i]["attr_desc"] = iedObj.Desc
- rowset[i]["attr_config_version"] = iedObj.ConfigVersion
- rowset[i]["attr_type"] = iedObj.Type
- rowset[i]["attr_manufacturer"] = iedObj.Manufacturer
- rowset[i]["ied_id"] = iedObj.NodeId
- }
- //new(SystemLog).Success(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- }
- return rowset, nil
- }
- //更新指定间隔下的装置定义
- func (c *CheckAreaMgr) UpdateIeds(scdid int64, areaid int, ieds string) error {
- db := orm.NewOrm()
- iedlist := strings.Split(ieds, ",")
- oldInfo := []orm.Params{}
- iedNoMap := map[string]orm.Params{}
- db.Raw("select * from t_data_check_area_ied where scd_id=? and area_id=?", scdid, areaid).Values(&oldInfo)
- for _, row := range oldInfo {
- iedNoMap[tools.IsEmpty(row["ied_name"])] = row
- }
- _, err := db.Raw("delete from t_data_check_area_ied where scd_id=? and area_id=?", scdid, areaid).Exec()
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- for _, row := range iedlist {
- iedno := tools.IsEmpty(iedNoMap[row]["ied_no"])
- iedType := tools.IsEmpty(iedNoMap[row]["ied_type"])
- pType := tools.IsEmpty(iedNoMap[row]["p_type"])
- if iedType == "" {
- iednameParts := new(ScdParse).ParseIedName(row)
- iedType = iednameParts[0]
- pType = iednameParts[1] + iednameParts[2]
- }
- _, err = db.Raw("insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_no,ied_type,p_type)values(?,?,?,?,?,?)", scdid, areaid, row, iedno, iedType, pType).Exec()
- if err != nil {
- logger.Logger.Error(err)
- break
- }
- }
- return err
- }
- //设置间隔下指定装置的端子编号,该编号只有在端子匹配表达式中存在{no}标识时才会使用
- func (c *CheckAreaMgr) SetIedNo(areaid int, iedname, no string) error {
- db := orm.NewOrm()
- _, err := db.Raw("update t_data_check_area_ied set ied_no=? where area_id=? and ied_name=?", no, areaid, iedname).Exec()
- return err
- }
- //获取指定SCD的IED类型列表
- func (c *CheckAreaMgr) GetIedTypeList(scdid int64) ([]orm.Params, error) {
- db := orm.NewOrm()
- sql := "select t2.* from t_data_check_area_ied t1,global_const_code t2 where t1.scd_id=? and t1.ied_type=t2.code and t2.parentcode='device_type' group by t1.ied_type "
- sqlParamters := []interface{}{}
- rowset := []orm.Params{}
- sqlParamters = append(sqlParamters, scdid)
- _, err := db.Raw(sql, sqlParamters).Values(&rowset)
- sqllog := fmt.Sprintf("SQL:%s 参数:%+v", sql, sqlParamters)
- if err != nil {
- logger.Logger.Error(err, sqllog)
- new(SystemLog).Fail(enum.AuditType_scd_show, enum.LogType_Query, enum.OptEventType_Bus, enum.OptEventLevel_Low, sqllog, c.GetUserInfo())
- }
- return rowset, nil
- }
- func (c *CheckAreaMgr) One(id string) (interface{}, error) {
- db := orm.NewOrm()
- idInt, err := strconv.ParseInt(id, 10, 64)
- if err != nil {
- return nil, err
- }
- areaM := T_data_check_area{Id: idInt}
- err = db.Read(&areaM)
- if err == nil {
- return areaM, nil
- }
- return nil, err
- }
- //重置scd的间隔信息
- func (c *CheckAreaMgr) Reset() error {
- dbo := orm.NewOrm()
- dbo.Raw("delete from t_data_check_area where scd_id=?", c.ScdId).Exec()
- dbo.Raw("delete from t_data_check_area_ied where scd_id=?", c.ScdId).Exec()
- c.ParseModelArea()
- logdesc := fmt.Sprintf("重置SCD[%d]检测模型间隔成功", c.ScdId)
- new(SystemLog).Success(enum.AuditType_check_task, enum.LogType_bind, enum.OptEventType_Bus, enum.OptEventLevel_Mid, logdesc, c.GetUserInfo())
- return nil
- }
- //生成SCD装置虚端子表
- //scdid:SCD文件ID
- //areaids:指定的间隔列表。可以不指定,不指定时则生成全站所有装置的端子关系表
- //iedname:指定的装置名称。可以不指定。
- func (c *CheckAreaMgr) MakeExtrefReport(scdid int64, areaids []string, iedname string) (re []orm.Params, err error) {
- findIeds := []orm.Params{}
- scdParseMgr := new(ScdParse)
- scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
- if areaids != nil && len(areaids) > 0 {
- for _, areaid := range areaids {
- if areaid == "" {
- continue
- }
- tmpid, _ := strconv.Atoi(areaid)
- r, _ := c.GetIedList(scdid, tmpid)
- if r == nil {
- continue
- }
- findIeds = append(findIeds, r...)
- }
- } else if iedname != "" {
- scdParseMgr := new(ScdParse)
- scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(scdid))
- scdNode := new(ScdNode)
- iedObj := scdNode.GetIed(scdXmlObj, tools.IsEmpty(scdid), iedname)
- if iedObj == nil {
- return findIeds, errors.New("无效的装置名称:" + iedname)
- }
- rowset := orm.Params{"ied_name": iedname}
- rowset["attr_name"] = iedObj.Name
- rowset["attr_desc"] = iedObj.Desc
- rowset["attr_config_version"] = iedObj.ConfigVersion
- rowset["attr_type"] = iedObj.Type
- rowset["attr_manufacturer"] = iedObj.Manufacturer
- rowset["ied_id"] = iedObj.NodeId
- findIeds = append(findIeds, rowset)
- } else {
- //获取所有的装置
- for _, iedObj := range scdXmlObj.IED {
- rowset := orm.Params{"ied_name": iedObj.Name}
- rowset["attr_name"] = iedObj.Name
- rowset["attr_desc"] = iedObj.Desc
- rowset["attr_config_version"] = iedObj.ConfigVersion
- rowset["attr_type"] = iedObj.Type
- rowset["attr_manufacturer"] = iedObj.Manufacturer
- rowset["ied_id"] = iedObj.NodeId
- findIeds = append(findIeds, rowset)
- }
- }
- scdNodeRule := new(ScdNodeRule)
- scdNodeRule.SetScdXmlObject(scdXmlObj)
- scdNode := new(ScdNode)
- //获取端子的外部端子输入信号类型
- var getFcdaType = func(inIedObj *node_attr.NIED, t2 *node_attr.NExtRef) string {
- isFoundType := false
- gooseorsv := ""
- for _, ap := range inIedObj.AccessPoint {
- if ap.Server == nil {
- continue
- }
- for _, ld := range ap.Server.LDevice {
- if ld.LN0 == nil {
- continue
- }
- dsname := ""
- for _, ds := range ld.LN0.DataSet {
- for _, fcda := range ds.FCDA {
- if fcda.LdInst == t2.LdInst && fcda.LnClass == t2.LnClass && fcda.LnInst == t2.LnInst && fcda.Prefix == t2.Prefix && fcda.DoName == t2.DoName {
- if t2.DaName == "" || fcda.DaName == t2.DaName {
- dsname = ds.Name
- break
- }
- }
- }
- if dsname != "" {
- break
- }
- }
- //logger.Logger.Debug(fmt.Sprintf("%s装置FCDA(%+v)的数据集名称:%s", inIedObj.Name, t2, dsname))
- if dsname != "" {
- for _, smcrl := range ld.LN0.SampledValueControl {
- if smcrl.DatSet == dsname {
- gooseorsv = "SV"
- break
- }
- }
- if gooseorsv == "" {
- for _, goosecrl := range ld.LN0.GSEControl {
- if goosecrl.DatSet == dsname {
- gooseorsv = "GOOSE"
- break
- }
- }
- }
- isFoundType = true
- break
- }
- }
- if isFoundType {
- break
- }
- }
- return gooseorsv
- }
- //处理ied的端子关系
- result := []orm.Params{}
- for _, ied := range findIeds {
- iedname := tools.IsEmpty(ied["ied_name"])
- //获取extref
- iedObj := scdNode.GetIed(scdXmlObj, tools.IsEmpty(scdid), iedname)
- if iedObj == nil {
- logger.Logger.Error(errors.New("装置"+iedname+"未找到"), fmt.Sprintf("装置数据:%+v", ied))
- continue
- }
- for _, t1 := range iedObj.AccessPoint {
- if t1.Server == nil || len(t1.Server.LDevice) == 0 {
- continue
- }
- for _, ld := range t1.Server.LDevice {
- if ld.LN0 != nil && ld.LN0.Inputs != nil {
- for _, t2 := range ld.LN0.Inputs.ExtRef {
- doi := scdNodeRule.IedIntAddrExist(iedname, t2.IntAddr)
- if doi == nil {
- logger.Logger.Debug(fmt.Sprintf("未发现装置%s的端子(%+v)名称", iedname, t2.IntAddr))
- continue
- }
- itemRow := orm.Params{}
- for k, v := range ied {
- itemRow[k] = v
- }
- itemRow["doi_desc"] = doi.(*node_attr.NDOI).Desc
- itemRow["doi_addr"] = t2.IntAddr
- //获取外部ied信息
- iniedname := t2.IedName
- inIedObj := scdNode.GetIed(scdXmlObj, tools.IsEmpty(scdid), iniedname)
- indoi, _ := scdNodeRule.IedFcdaExist(t2.IedName, t2.LdInst, t2.LnClass, t2.LnInst, t2.Prefix, t2.DoName, "")
- if inIedObj == nil || indoi == nil {
- logger.Logger.Debug(fmt.Sprintf("未发现装置%s的端子(%+v)名称", iniedname, t2))
- continue
- } else {
- //查找fcda的数据集及类型
- itemRow["gooseorsv"] = getFcdaType(inIedObj, t2)
- itemRow["in_ied_name"] = iniedname
- itemRow["in_ied_desc"] = inIedObj.Desc
- itemRow["in_doi_desc"] = indoi.(*node_attr.NDOI).Desc
- daname := ""
- if t2.DaName != "" {
- daname = "." + t2.DaName
- }
- itemRow["in_doi_addr"] = fmt.Sprintf("%s/%s%s%s.%s%s", t2.LdInst, t2.Prefix, t2.LnClass, t2.LnInst, t2.DoName, daname)
- result = append(result, itemRow)
- }
- }
- }
- for _, ln := range ld.LN {
- if ln.Inputs == nil {
- continue
- }
- for _, t2 := range ln.Inputs.ExtRef {
- doi := scdNodeRule.IedIntAddrExist(iedname, t2.IntAddr)
- if doi == nil {
- logger.Logger.Debug(fmt.Sprintf("未发现装置%s的端子(%+v)名称", iedname, t2.IntAddr))
- continue
- }
- itemRow := orm.Params{}
- for k, v := range ied {
- itemRow[k] = v
- }
- itemRow["doi_desc"] = doi.(*node_attr.NDOI).Desc
- itemRow["doi_addr"] = t2.IntAddr
- //获取外部ied信息
- iniedname := t2.IedName
- inIedObj := scdNode.GetIed(scdXmlObj, tools.IsEmpty(scdid), iniedname)
- indoi, _ := scdNodeRule.IedFcdaExist(t2.IedName, t2.LdInst, t2.LnClass, t2.LnInst, t2.Prefix, t2.DoName, "")
- if inIedObj == nil || indoi == nil {
- logger.Logger.Debug(fmt.Sprintf("未发现装置%s的端子(%+v)名称", iniedname, t2))
- continue
- }
- //查找fcda的数据集及类型
- itemRow["gooseorsv"] = getFcdaType(inIedObj, t2)
- itemRow["in_ied_name"] = iniedname
- itemRow["in_ied_desc"] = inIedObj.Desc
- itemRow["in_doi_desc"] = indoi.(*node_attr.NDOI).Desc
- daname := ""
- if t2.DaName != "" {
- daname = "." + t2.DaName
- }
- itemRow["in_doi_addr"] = fmt.Sprintf("%s/%s%s%s.%s%s", t2.LdInst, t2.Prefix, t2.LnClass, t2.LnInst, t2.DoName, daname)
- result = append(result, itemRow)
- }
- }
- }
- }
- }
- return result, nil
- }
- var areaCheckInfo = sync.Map{}
- //获取解析模型需要的基础数据信息
- func (c *CheckAreaMgr) getAreaCheckInfo() (*node_attr.SCL, []orm.Params, string, error) {
- key := fmt.Sprintf("%d-checkinfo", c.ScdId)
- if v, h := areaCheckInfo.Load(key); h {
- v1 := v.([]interface{})
- return v1[0].(*node_attr.SCL), v1[1].([]orm.Params), v1[2].(string), nil
- }
- arealist := []orm.Params{}
- db := orm.NewOrm()
- _, err := db.Raw("select id,area_name,area_type,model_id from t_data_check_area where scd_id=?", c.ScdId).Values(&arealist)
- if err != nil {
- logger.Logger.Error(err)
- return nil, nil, "", err
- }
- scdNodeRule := new(ScdNodeRule)
- area_ruleid := ""
- area_ruleList, _, _ := scdNodeRule.GetDefList(map[string]interface{}{"check_name": "间隔装置与检查模型不符"}, 1, 1)
- if len(area_ruleList) > 0 {
- area_ruleid = tools.IsEmpty(area_ruleList[0]["id"])
- }
- if area_ruleid == "" {
- return nil, nil, "", errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
- }
- scdParseMgr := new(ScdParse)
- scdXmlObj, serr := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
- if serr != nil {
- return nil, nil, "", serr
- }
- if scdXmlObj == nil {
- return nil, nil, "", errors.New("无效的SCD")
- }
- areaCheckInfo.Store(key, []interface{}{scdXmlObj, arealist, area_ruleid})
- return scdXmlObj, arealist, area_ruleid, nil
- }
- //检测装置端子分析:检测间隔装置关系正确性(已废弃)
- func (c *CheckAreaMgr) CheckAreaIedRelation() error {
- // 获取当前scd中需要检查的间隔
- scdXmlObj, arealist, area_ruleid, err := c.getAreaCheckInfo()
- db := orm.NewOrm()
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- if area_ruleid == "" {
- return errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
- }
- if scdXmlObj == nil {
- return errors.New("无效的SCD")
- }
- scdNodeRule := new(ScdNodeRule)
- scdNode := new(ScdNode)
- model_refs := map[string][]orm.Params{} //模型定义的装置关系定义
- area_ieds := map[string][]orm.Params{} //间隔下的装置列表
- iedRelationMgr := new(SysCheckModelIedRelationMgr)
- for _, row := range arealist {
- //获取间隔标准装置及关系
- modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
- //area_name := tools.IsEmpty(row["area_name"])
- //area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
- area_id := tools.IsEmpty(row["id"])
- s, err := iedRelationMgr.GetListByModelid(modelid)
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- if len(s) == 0 {
- return errors.New(fmt.Sprintf("模型%d还未配置装置关系", modelid))
- }
- model_refs[fmt.Sprintf("%d", modelid)] = s
- /*
- hasIeds := map[string]bool{}
- for _, row1 := range s {
- iedname := tools.IsEmpty(row1["from_ied_code"])
- if !hasIeds[iedname] {
- hasIeds[iedname] = true
- }
- iedname = tools.IsEmpty(row1["to_ied_code"])
- if !hasIeds[iedname] {
- hasIeds[iedname] = true
- }
- }
- */
- s1 := []orm.Params{}
- _, err = db.Raw("select ied_name from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- if len(s) == 0 {
- return errors.New(fmt.Sprintf("间隔%s未发现任何装置", tools.IsEmpty(row["area_name"])))
- }
- area_ieds[area_id] = s1
- }
- //装置关联关系分析
- //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
- HasAreaJ := false
- for _, row := range arealist {
- area_name := tools.IsEmpty(row["area_name"])
- areaCode := tools.IsEmpty(row["area_type"]) //间隔模型类型
- area_id := tools.IsEmpty(row["id"])
- if areaCode == "J" {
- HasAreaJ = true
- modelid := tools.IsEmpty(row["model_id"])
- c.cJ(modelid, scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PE", area_ruleid)
- c.cJ(modelid, scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PJ", area_ruleid)
- c.cJ(modelid, scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PK", area_ruleid)
- c.cJ(modelid, scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], "PF", area_ruleid)
- }
- }
- for _, row := range arealist {
- area_name := tools.IsEmpty(row["area_name"])
- areaCode := tools.IsEmpty(row["area_type"]) //间隔模型类型
- area_id := tools.IsEmpty(row["id"])
- modelid := tools.IsEmpty(row["model_id"])
- if areaCode == "J" {
- continue
- }
- if areaCode == "L" {
- //线路间隔
- c.cL(modelid, scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], area_ruleid)
- }
- if areaCode == "T" {
- //变压器齐间隔
- c.cT(modelid, scdXmlObj, scdNode, scdNodeRule, area_name, model_refs[modelid], area_ieds[area_id], area_ruleid, HasAreaJ)
- }
- }
- scdNodeRule.CheckFinish()
- scdNodeRule.Flush()
- return nil
- }
- //检测装置功能分析
- func (c *CheckAreaMgr) CheckIedFunc() error {
- return nil
- }
- //检测装置端子分析
- func (c *CheckAreaMgr) CheckIedFcda() error {
- scdXmlObj, arealist, area_ruleid, err := c.getAreaCheckInfo()
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- if area_ruleid == "" {
- return errors.New(fmt.Sprintf("未定义间隔装置的检查规则“间隔装置与检查模型不符”"))
- }
- if scdXmlObj == nil {
- return errors.New("无效的SCD")
- }
- scdidStr := fmt.Sprintf("%d", c.ScdId)
- db := orm.NewOrm()
- //获取当前站的各电压等级
- volRows := []orm.Params{}
- _, err = db.Raw("select t.vol, CAST(REPLACE(UPPER(g.name),'KV','') as SIGNED) volname from t_area_ied_relation t,global_const_code g where g.code=CONCAT('v_level_',t.vol) and g.parentcode='voltage_level' and t.vol!=999 and t.scd_id=? GROUP BY t.vol ORDER BY volname desc", c.ScdId).Values(&volRows)
- if err != nil {
- logger.Logger.Error(err)
- return err
- }
- if len(volRows) == 0 {
- logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
- return errors.New("该scd未发现任何电压等级的装置")
- }
- volMap := map[string]string{}
- volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
- if len(volRows) == 2 {
- volMap["middle"] = ""
- volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
- } else {
- volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
- volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
- }
- scdNodeRule := new(ScdNodeRule)
- scdNodeRule.SetScdXmlObject(scdXmlObj)
- scdNodeMgr := new(ScdNode)
- //当前装置的所有信号接收端子列表
- var getIedExtRefs = func(iedname string) map[string]*node_attr.NExtRef {
- iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
- if iedObj == nil {
- logger.Logger.Debug(fmt.Sprintf("在scd:%d中未发现装置%s", c.ScdId, iedname))
- return nil
- }
- fcdaObjList := map[string]*node_attr.NExtRef{}
- for _, t1 := range iedObj.AccessPoint {
- if t1.Server == nil || len(t1.Server.LDevice) == 0 {
- continue
- }
- for _, ld := range t1.Server.LDevice {
- if ld.LN0 != nil && ld.LN0.Inputs != nil {
- for _, t2 := range ld.LN0.Inputs.ExtRef {
- doi := scdNodeRule.IedIntAddrExist(iedname, t2.IntAddr)
- if doi == nil {
- continue
- }
- fcdaObjList[doi.(*node_attr.NDOI).Desc] = t2
- }
- }
- for _, ln := range ld.LN {
- if ln.Inputs == nil {
- continue
- }
- for _, t2 := range ln.Inputs.ExtRef {
- doi := scdNodeRule.IedIntAddrExist(iedname, t2.IntAddr)
- if doi == nil {
- continue
- }
- fcdaObjList[doi.(*node_attr.NDOI).Desc] = t2
- }
- }
- }
- }
- return fcdaObjList
- }
- //当前装置的所有信号发送端子列表
- /*
- var getIedFcdas = func(iedname string) map[string]*node_attr.NFCDA {
- iedObj := scdNodeMgr.GetIed(scdXmlObj, tools.IsEmpty(c.ScdId), iedname)
- if iedObj == nil {
- return nil
- }
- fcdaObjList := map[string]*node_attr.NFCDA{}
- for _, t1 := range iedObj.AccessPoint {
- if t1.Server == nil || len(t1.Server.LDevice) == 0 {
- continue
- }
- for _, ld := range t1.Server.LDevice {
- if ld.LN0 != nil && len(ld.LN0.DataSet) > 0 {
- for _, t2 := range ld.LN0.DataSet {
- for _, t3 := range t2.FCDA {
- re, _ := scdNodeRule.IedFcdaExist(iedname, t3.LdInst, t3.LnClass, t3.LnInst, t3.Prefix, t3.DoName, t3.DaName)
- if re == nil {
- continue
- }
- doi := re.(*node_attr.NDOI)
- fcdaObjList[doi.Desc] = t3
- }
- }
- }
- }
- }
- return fcdaObjList
- }
- */
- //从装置类型code中解析出类型代码和电压等级
- var getIedTypeAndVolCode = func(ied_type string) (string, string) {
- tmp := strings.Split(ied_type, "#")
- ied_type = tmp[0]
- vol := ""
- if len(tmp) == 2 {
- vol = tmp[1] //电压级别
- }
- return ied_type, vol
- }
- //从间隔装置中过滤出指定类型的IED
- var filterAreaIeds = func(ied_type, volLevelCode string, s1 []orm.Params, abCode string, isPm ...bool) []orm.Params {
- iedlst := []orm.Params{}
- if volLevelCode == "" || (volLevelCode != "H" && volLevelCode != "M" && volLevelCode != "L") {
- for _, r := range s1 {
- iedname := tools.IsEmpty(r["ied_name"])
- if strings.HasPrefix(iedname, ied_type) || (abCode != "" && strings.HasSuffix(iedname, abCode)) {
- iedlst = append(iedlst, r)
- }
- }
- } else {
- tmpLst := map[string]orm.Params{}
- for _, r := range s1 {
- iedname := tools.IsEmpty(r["ied_name"])
- if strings.HasPrefix(iedname, ied_type) || (abCode != "" && strings.HasSuffix(iedname, abCode)) {
- tmpLst[iedname] = r
- }
- }
- //PM类型的装置需要单独处理
- if len(isPm) > 0 {
- //只有1台PM装置时,不用区分电压等级直接返回
- if len(tmpLst) == 1 {
- for _, r1 := range tmpLst {
- return []orm.Params{r1}
- }
- }
- }
- h, m, l := c.getIedListByVol(ied_type, tmpLst, volMap, abCode)
- if volLevelCode == "H" {
- iedlst = h
- }
- if volLevelCode == "M" {
- iedlst = m
- }
- if volLevelCode == "L" {
- iedlst = l
- }
- }
- return iedlst
- }
- //iedRelationMgr := new(SysCheckModelIedRelationMgr)
- modelFcda := sync.Map{}
- //已经加载过遥信的装置
- isLoadYxIed := map[string]map[*node_attr.NExtRef][]string{}
- //已经处理过遥信端子的装置
- //isDealYxIed := map[string]int{}
- //已获取端子的装置
- isLoadExtref := map[string]map[string]*node_attr.NExtRef{}
- for _, row := range arealist {
- //获取间隔标准装置及关系
- modelid, _ := strconv.Atoi(tools.IsEmpty(row["model_id"]))
- area_name := tools.IsEmpty(row["area_name"])
- //area_type := tools.IsEmpty(row["area_type"]) //间隔模型类型
- area_id := tools.IsEmpty(row["id"])
- logger.Logger.Debug(fmt.Sprintf("开始检查模型%d的间隔%s", modelid, area_name))
- //获取装置分组信息
- bgm := new(SysCheckModelIedtypeGroupMgr)
- bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
- groupList := bgm.List()
- //获取该间隔模型配置的所有端子关系列表
- tmpMgr := new(SysCheckModelFcdaRalationMgr)
- tmpMgr.Model.ModelId = modelid
- funclist := map[string][]orm.Params{}
- key := fmt.Sprintf("%d-%d", modelid, area_id)
- v, h := modelFcda.Load(key)
- if h {
- funclist = v.(map[string][]orm.Params)
- } else {
- funclist, _ = tmpMgr.GetModelAllFcdaRef()
- if funclist == nil || len(funclist) == 0 {
- logger.Logger.Error(errors.New(fmt.Sprintf("模型%d下的间隔%s还未配置装置端子关联关系", modelid, area_name)))
- continue
- }
- modelFcda.Store(key, funclist)
- }
- //获取该间隔下该类型的装置
- s1 := []orm.Params{}
- _, err = db.Raw("select ied_name,ied_no from t_data_check_area_ied where area_id=?", area_id).Values(&s1)
- typeMappingMgr := new(SysCheckModelIedtypeMappingMgr)
- pmCode := c.getIedTypeCode(modelid, "PM")
- //循环处理关联关系
- for to_ied_type2, refrow := range funclist {
- logger.Logger.Debug(fmt.Sprintf("================正在检查类型%s关系===============", to_ied_type2))
- ts := strings.Split(to_ied_type2, ",")
- //从间隔中获取当前同类型的信号接收装置
- ied_type := c.getIedTypeCode(modelid, ts[0])
- if v, h := groupList[ied_type]; h {
- ied_type = typeMappingMgr.GetMappingType(modelid, v)
- }
- abCode := c.getIedTypeABCode(ied_type)
- ied_type, vol := getIedTypeAndVolCode(ied_type)
- isReceivePm := strings.HasPrefix(ied_type, pmCode) //接收装置是Pm装置
- iedlst := filterAreaIeds(ied_type, vol, s1, abCode, isReceivePm)
- logger.Logger.Debug(fmt.Sprintf("装置类型%s#%s与%s的装置(%+v)端子关系", ied_type, vol, ts[1], iedlst))
- //从间隔中获取当前信号输出装置
- outiedlist := map[string]orm.Params{}
- fromiedcode := c.getIedTypeCode(modelid, ts[1])
- if v, h := groupList[fromiedcode]; h {
- fromiedcode = typeMappingMgr.GetMappingType(modelid, v)
- }
- fromAbCode := c.getIedTypeABCode(fromiedcode)
- from_ied_type, vol2 := getIedTypeAndVolCode(fromiedcode)
- isOutPm := strings.HasPrefix(from_ied_type, pmCode) //输出装置是PM装置
- outiedlist2 := filterAreaIeds(from_ied_type, vol2, s1, fromAbCode, isOutPm)
- for _, iedrow := range outiedlist2 {
- iedname := tools.IsEmpty(iedrow["ied_name"])
- outiedlist[iedname] = iedrow
- }
- if len(outiedlist) == 0 {
- logger.Logger.Debug(fmt.Sprintf("装置类型%s#%s%s未从类型%s%s的任何电压等级%s装置接收信号", ied_type, vol, abCode, from_ied_type, fromAbCode, vol2))
- continue
- }
- logger.Logger.Debug(fmt.Sprintf("当前装置类型:%s%s的装置(%+v)与类型%s#%s%s存在以下信号输出装置:%+v", ied_type, abCode, iedlst, from_ied_type, fromAbCode, vol2, outiedlist))
- //logger.Logger.Debug(fmt.Sprintf("设计端子关联关系:%+v", refrow))
- for _, ied := range iedlst {
- iedname := tools.IsEmpty(ied["ied_name"])
- iedObj := scdNodeMgr.GetIed(scdXmlObj, scdidStr, iedname)
- iedObjDesc := ""
- if iedObj != nil {
- iedObjDesc = iedObj.Desc
- } else {
- logger.Logger.Error(fmt.Sprintf("信号接收装置%s未找到!", iedname))
- continue
- }
- //遥信端子列表:仅根据scd实际配置检查其双方端子的doi名称是否相同
- scdMgr := new(ScdMgr)
- yx, h := isLoadYxIed[iedname]
- if !h {
- yx = scdMgr.GetYxExtref(scdXmlObj, c.ScdId, iedname)
- isLoadYxIed[iedname] = yx
- }
- yxAddrMap := map[string]int{}
- for sg, _ := range yx {
- key := fmt.Sprintf("%s%s%s%s%s%s%s", sg.IedName, sg.IntAddr, sg.LdInst, sg.Prefix, sg.LnClass, sg.LnInst, sg.DoName)
- yxAddrMap[key] = 1
- }
- //所有端子列表
- extreflist := isLoadExtref[iedname]
- if extreflist == nil {
- extreflist = getIedExtRefs(iedname)
- }
- for outiedname, outied := range outiedlist {
- if iedname == outiedname {
- continue
- }
- logger.Logger.Debug(fmt.Sprintf("正在匹配装置%s与%s的端子关联关系", iedname, outiedname))
- outIedObj := scdNodeMgr.GetIed(scdXmlObj, scdidStr, outiedname)
- outIedObjDesc := ""
- if outIedObj == nil {
- logger.Logger.Error(fmt.Sprintf("信号输出装置%s未找到!", outiedname))
- } else {
- outIedObjDesc = outIedObj.Desc
- }
- if iedObj == nil && outIedObj == nil {
- continue
- }
- //outiedFcdaList := getIedFcdas(outiedname) //输入装置的信号输出端子
- //是否设置的端子编号
- noText := tools.IsEmpty(ied["ied_no"])
- if noText == "" {
- noText = tools.IsEmpty(outied["ied_no"])
- }
- //检查是否有错误和缺失的端子
- for _, r := range refrow {
- extref_name := tools.IsEmpty(r["to_fcda_name"])
- fcda_name := tools.IsEmpty(r["from_fcda_name"])
- extref_name_exp := tools.IsEmpty(r["to_fcda_match_exp"])
- fcda_name_exp := tools.IsEmpty(r["from_fcda_match_exp"])
- funcName := tools.IsEmpty(r["to_func_name"])
- //端子编号处理
- if strings.Index(extref_name_exp, "{no}") > -1 {
- extref_name_exp = strings.ReplaceAll(extref_name_exp, "{no}", noText)
- }
- if strings.Index(fcda_name_exp, "{no}") > -1 {
- fcda_name_exp = strings.ReplaceAll(fcda_name_exp, "{no}", noText)
- }
- funcExist := false //判断接收端设计的端子是否存在
- extrefObj := new(node_attr.NExtRef)
- fcda2Exist := false
- isYx := false
- for desc, item := range extreflist {
- if item.IedName != outiedname {
- continue
- }
- //判断是否是遥信端子
- /*
- if strings.Index(funcName, "遥信") > -1 && yxAddrMap[fmt.Sprintf("%s%s%s%s%s%s%s", item.IedName, item.IntAddr, item.LdInst, item.Prefix, item.LnClass, item.LnInst, item.DoName)] == 1 {
- isYx = true
- break
- }
- */
- //logger.Logger.Debug(fmt.Sprintf("接收装置%s的设计端子%s匹配SCD ExtRef DO端子%s", iedname, extref_name_exp, desc))
- macthResult, _ := tools.RexGroupTestMatch(extref_name_exp, desc)
- if macthResult {
- funcExist = true
- extrefObj = item
- extref_name = desc //实际的端子名称
- break
- }
- }
- if isYx {
- //遥信端子不处理
- continue
- }
- if funcExist {
- //判断输出端端子是否存在
- doi, _ := scdNodeRule.IedFcdaExist(extrefObj.IedName, extrefObj.LdInst, extrefObj.LnClass, extrefObj.LnInst, extrefObj.Prefix, extrefObj.DoName, "")
- if doi != nil {
- daname := ""
- if extrefObj.DaName != "" {
- daname = "." + extrefObj.DaName
- }
- fcda2Exist = true
- fcda_name = doi.(*node_attr.NDOI).Desc //实际的端子名称
- if strings.Index(funcName, "遥信") > -1 {
- //2端端子名称需要完全相同
- if extref_name != fcda_name {
- parse_result := fmt.Sprintf("间隔%s的装置%s遥信端子%s与装置%s端子%s关联错误:端子名称不相同", area_name, iedname, extref_name, outiedname, fcda_name)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": outiedname,
- "out_ied_desc": outIedObjDesc,
- "fcda_desc": extref_name,
- "fcda_addr": extrefObj.IntAddr,
- "out_fcda_desc": fcda_name,
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extrefObj.LdInst, extrefObj.Prefix, extrefObj.LnClass, extrefObj.LnInst, extrefObj.DoName, daname),
- "error_type": "2",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- } else {
- //判断是否是双点或单点遥信端子
- extrefDoi := scdNodeRule.IedIntAddrExist(iedname, extrefObj.IntAddr)
- extrefDoiCdcCode := new(ScdMgr).GetDoiCdcInfo(scdXmlObj, c.ScdId, extrefDoi.(*node_attr.NDOI))
- fcdaCdcCode := new(ScdMgr).GetDoiCdcInfo(scdXmlObj, c.ScdId, doi.(*node_attr.NDOI))
- if extrefDoiCdcCode != fcdaCdcCode {
- //错误:cdc类型不一致
- parse_result := fmt.Sprintf("间隔%s的接收装置%s遥信端子%s与输出装置%s端子%s的CDC类型不一致(%s,%s)", area_name, iedname, extrefDoi.(*node_attr.NDOI).Desc, outiedname, doi.(*node_attr.NDOI).Desc, extrefDoiCdcCode, fcdaCdcCode)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": outiedname,
- "out_ied_desc": outIedObjDesc,
- "fcda_desc": extref_name,
- "fcda_addr": extrefObj.IntAddr,
- "out_fcda_desc": fcda_name,
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extrefObj.LdInst, extrefObj.Prefix, extrefObj.LnClass, extrefObj.LnInst, extrefObj.DoName, daname),
- "error_type": "2",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- }
- }
- continue
- }
- macthResult, _ := tools.RexGroupTestMatch(fcda_name_exp, fcda_name)
- if !macthResult {
- parse_result := fmt.Sprintf("间隔%s的装置%s端子%s与装置%s端子%s关联错误", area_name, iedname, extref_name, outiedname, fcda_name)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": outiedname,
- "out_ied_desc": outIedObjDesc,
- "fcda_desc": extref_name,
- "fcda_addr": extrefObj.IntAddr,
- "out_fcda_desc": fcda_name,
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extrefObj.LdInst, extrefObj.Prefix, extrefObj.LnClass, extrefObj.LnInst, extrefObj.DoName, daname),
- "error_type": "2",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- }
- }
- }
- if !funcExist {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失端子%s", area_name, iedname, extref_name)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObjDesc,
- "out_ied_name": "",
- "out_ied_desc": "",
- "fcda_desc": extref_name,
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "3",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- } else if !fcda2Exist {
- //fcda2Exist为false表示实际的端子from ied不是当前设计的ied
- parse_result := fmt.Sprintf("间隔%s下%s的输入装置%s缺失端子%s", area_name, iedname, outiedname, fcda_name)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObjDesc,
- "out_ied_name": outiedname,
- "out_ied_desc": outIedObjDesc,
- "fcda_desc": extref_name,
- "fcda_addr": extrefObj.IntAddr,
- "out_fcda_desc": fcda_name,
- "out_fcda_addr": "",
- "error_type": "3",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- }
- }
- //检查是否有多余(SCD中有不存在于设计中)的端子
- for extrefdesc, r := range extreflist { //scd中的端子关系
- //判断是否是当前输入装置和遥信端子
- if r.IedName != outiedname || yxAddrMap[fmt.Sprintf("%s%s%s%s%s%s%s", r.IedName, r.IntAddr, r.LdInst, r.Prefix, r.LnClass, r.LnInst, r.DoName)] == 1 {
- continue
- }
- extref_name := ""
- fcda_name := ""
- isHave := false
- for _, r1 := range refrow { //设计的端子关系
- extref_name_exp := tools.IsEmpty(r1["to_fcda_match_exp"])
- //端子编号处理
- if strings.Index(extref_name_exp, "{no}") > -1 {
- extref_name_exp = strings.ReplaceAll(extref_name_exp, "{no}", noText)
- }
- macthResult, _ := tools.RexGroupTestMatch(extref_name_exp, extrefdesc)
- if extrefdesc == extref_name_exp || macthResult {
- //端子存在
- isHave = true
- break
- }
- }
- if !isHave {
- daname := ""
- if r.DaName != "" {
- daname = "." + r.DaName
- }
- doi := scdNodeRule.IedIntAddrExist(iedname, r.IntAddr)
- if doi != nil {
- extref_name = doi.(*node_attr.NDOI).Desc
- }
- doi, _ = scdNodeRule.IedFcdaExist(r.IedName, r.LdInst, r.LnClass, r.LnInst, r.Prefix, r.DoName, "")
- if doi != nil {
- fcda_name = doi.(*node_attr.NDOI).Desc
- }
- tmpIedObj := scdNodeMgr.GetIed(scdXmlObj, scdidStr, r.IedName)
- parse_result := fmt.Sprintf("间隔%s下装置(%s)的端子%s在设计中不存在", area_name, iedname, extref_name)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": r.IedName,
- "out_ied_desc": tmpIedObj.Desc,
- "fcda_desc": extref_name,
- "fcda_addr": r.IntAddr,
- "out_fcda_desc": fcda_name,
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", r.LdInst, r.Prefix, r.LnClass, r.LnInst, r.DoName, daname),
- "error_type": "1",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- }
- }
- }
- //判断装置是否具备遥信功能,具备时需要单独处理遥信类端子
- //遥信类端子处理规则:以scd中实际配置为准,通过检查装置双方的端子名称是否完全一致以及单双点类型是否相同,以及是否有缺失和多余的遥信端子
- /*
- if len(yx) > 0 && isDealYxIed[iedname] == 0 {
- //logger.Logger.Debug(fmt.Sprintf("=============正在处理装置%s遥信端子数:%d %+v", iedname, len(yx), isDealYxIed))
- isDealYxIed[iedname] = 1
- for extref, doiinfo := range yx {
- doiDesc := doiinfo[0]
- doiCdc := doiinfo[1]
- daname := ""
- if extref.DaName != "" {
- daname = "." + extref.DaName
- }
- //获取输出端端子名称
- outFcdaDoi, _ := scdNodeRule.IedFcdaExist(extref.IedName, extref.LdInst, extref.LnClass, extref.LnInst, extref.Prefix, extref.DoName, extref.DaName)
- tmpIedObj := scdNodeMgr.GetIed(scdXmlObj, scdidStr, extref.IedName)
- if tmpIedObj == nil || outFcdaDoi == nil {
- //端子缺失
- tmpIedName := ""
- tmpIedDesc := ""
- if tmpIedObj != nil {
- tmpIedName = tmpIedObj.Name
- tmpIedDesc = tmpIedObj.Desc
- }
- parse_result := fmt.Sprintf("间隔%s的装置%s遥信端子%s的关联端子不存在", area_name, iedname, doiDesc)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": tmpIedName,
- "out_ied_desc": tmpIedDesc,
- "fcda_desc": doiDesc,
- "fcda_addr": extref.IntAddr,
- "out_fcda_desc": "",
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extref.LdInst, extref.Prefix, extref.LnClass, extref.LnInst, extref.DoName, daname),
- "error_type": "3",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- continue
- }
- if doiCdc != "" && (!YaoXinDBType[doiCdc] || !YaoXinSiType[doiCdc]) {
- //判断是否是双点或单点遥信端子
- fcdaCdcCode := new(ScdMgr).GetDoiCdcInfo(scdXmlObj, c.ScdId, outFcdaDoi.(*node_attr.NDOI))
- if doiCdc != fcdaCdcCode {
- //错误:cdc类型不一致
- parse_result := fmt.Sprintf("间隔%s的接收装置%s遥信端子%s与输出装置%s端子%s的CDC类型不一致(%s,%s)", area_name, iedname, doiDesc, tmpIedObj.Name, outFcdaDoi.(*node_attr.NDOI).Desc, doiCdc, fcdaCdcCode)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": tmpIedObj.Name,
- "out_ied_desc": tmpIedObj.Desc,
- "fcda_desc": doiDesc,
- "fcda_addr": extref.IntAddr,
- "out_fcda_desc": outFcdaDoi.(*node_attr.NDOI).Desc,
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extref.LdInst, extref.Prefix, extref.LnClass, extref.LnInst, extref.DoName, daname),
- "error_type": "2",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- continue
- }
- }
- if outFcdaDoi.(*node_attr.NDOI).Desc != doiDesc {
- //关联错误
- parse_result := fmt.Sprintf("间隔%s的装置%s遥信端子%s与装置%s端子%s名称不匹配", area_name, iedname, doiDesc, tmpIedObj.Name, outFcdaDoi.(*node_attr.NDOI).Desc)
- re := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": iedname,
- "ied_desc": iedObj.Desc,
- "out_ied_name": tmpIedObj.Name,
- "out_ied_desc": tmpIedObj.Desc,
- "fcda_desc": doiDesc,
- "fcda_addr": extref.IntAddr,
- "out_fcda_desc": outFcdaDoi.(*node_attr.NDOI).Desc,
- "out_fcda_addr": fmt.Sprintf("%s/%s%s%s.%s%s", extref.LdInst, extref.Prefix, extref.LnClass, extref.LnInst, extref.DoName, daname),
- "error_type": "2",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(re)
- }
- }
- }
- */
- yxAddrMap = nil
- extreflist = nil
- }
- }
- }
- isLoadYxIed = nil
- scdNodeRule.CheckFinish()
- scdNodeRule.Flush()
- return nil
- }
- //解析模型间隔。根据模型定义解析出间隔中的装置
- func (c *CheckAreaMgr) ParseModelArea() {
- c.Init(c.ScdId)
- key := fmt.Sprintf("%d-checkinfo", c.ScdId)
- areaCheckInfo.Delete(key)
- // 取得当前scd所有ied及名称解析结果
- dbo := orm.NewOrm()
- sql := "select t.*,t1.name area_name from t_area_ied_relation t,t_substation_area t1 where t.area_id=t1.id and t.scd_id=? order by t.p_type"
- iedlst := []orm.Params{}
- _, err := dbo.Raw(sql, c.ScdId).Values(&iedlst)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- logger.Logger.Debug(fmt.Sprintf("=====总装置数:%d", len(iedlst)))
- iedMap := map[string]orm.Params{}
- for _, r := range iedlst {
- iedMap[tools.IsEmpty(r["ied_name"])] = r
- }
- //先分析母联间隔,如果没有选择母联间隔时,主变间隔中不包含母联终端装置
- HasAreaJ := false
- for _, row := range c.CheckModelList {
- areaCode := tools.IsEmpty(row["area_type_code"])
- if areaCode == "J" {
- HasAreaJ = true
- modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
- //modelname := tools.IsEmpty(row["model_name"])
- iedtypes := tools.IsEmpty(row["ied_types"])
- mapptype := new(SysCheckModelIedtypeMappingMgr)
- mapptype.Model = T_data_model_iedtype_mapping{ModelId: modelid}
- mappresult := mapptype.List()
- if len(mappresult) > 0 {
- tmp := []string{}
- for _, r := range strings.Split(iedtypes, ",") {
- if mappresult[r] != "" {
- tmp = append(tmp, mappresult[r])
- } else {
- tmp = append(tmp, r)
- }
- }
- iedtypes = strings.Join(tmp, ",")
- }
- volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
- c.pJ(modelid, volcode, iedtypes, iedMap, "PE")
- c.pJ(modelid, volcode, iedtypes, iedMap, "PJ")
- c.pJ(modelid, volcode, iedtypes, iedMap, "PK")
- c.pJ(modelid, volcode, iedtypes, iedMap, "PF")
- }
- }
- for _, row := range c.CheckModelList {
- //逐一分析模型定义
- modelid, _ := strconv.Atoi(tools.IsEmpty(row["id"]))
- modelname := tools.IsEmpty(row["model_name"])
- iedtypes := tools.IsEmpty(row["ied_types"])
- //模型对应的间隔代码
- /*
- S 站用变压器
- C 电容器
- B 断路器
- K 母分
- J 母联
- M 母线
- X 电抗器
- L 线路
- T 主变压器
- */
- areaCode := tools.IsEmpty(row["area_type_code"])
- //模型对应的电压等级
- //10:10KV 35:35KV 66:66KV 11:110KV 22:220KV 50:500KV 75:750KV 33:330KV T0:1000KV
- volcode := strings.ReplaceAll(tools.IsEmpty(row["vol_code"]), "v_level_", "")
- if modelname == "" || iedtypes == "" {
- continue
- }
- //母联间隔已经提前分析,如果没有母联间隔时,主变间隔中不包含母联终端装置
- if areaCode == "J" {
- continue
- }
- //获取模型中的自定义装置类型编码
- mapptype := new(SysCheckModelIedtypeMappingMgr)
- mapptype.Model = T_data_model_iedtype_mapping{ModelId: modelid}
- mappresult := mapptype.List()
- if len(mappresult) > 0 {
- tmp := []string{}
- for _, r := range strings.Split(iedtypes, ",") {
- if mappresult[r] != "" {
- tmp = append(tmp, mappresult[r])
- } else {
- tmp = append(tmp, r)
- }
- }
- iedtypes = strings.Join(tmp, ",")
- }
- //获取模型内中装备关系定义
- //主变间隔分析:需要查站内该电压等级下的高中低压侧装置或者高低压装置组成一个间隔,以主变保护装置(PT)为起始
- if areaCode == "T" {
- c.pT(modelid, iedtypes, iedMap, HasAreaJ)
- }
- //线路保护间隔分析:以线路保护测控装置(PL)为开始分析
- if areaCode == "L" {
- c.pL(modelid, volcode, iedtypes, iedMap)
- }
- //母线间隔分析:PM
- if areaCode == "M" {
- c.pM(modelid, volcode, iedtypes, iedMap)
- }
- }
- }
- //根据默认装置类型获取其类型编码。如果没有自定义编码,则返回默认编码。返回编码时已自动去除套别标识
- func (c *CheckAreaMgr) getIedTypeCode(modelid int, iedtype string) string {
- mapptype := new(SysCheckModelIedtypeMappingMgr)
- mappresult := mapptype.GetMappingType(modelid, iedtype)
- ptCode := iedtype
- if mappresult != "" {
- ptCode = mappresult //自定义主变保护编码
- }
- return strings.Split(ptCode, "-")[0]
- }
- //变压器间隔分析
- func (c *CheckAreaMgr) pT(modelid int, iedtypes string, ieds map[string]orm.Params, HasAreaJ bool) {
- scdParseMgr := new(ScdParse)
- scdNodeMgr := new(ScdNode)
- db := orm.NewOrm()
- //获取装置分组信息
- bgm := new(SysCheckModelIedtypeGroupMgr)
- bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
- groupList := bgm.List()
- scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
- //获取当前站的各电压等级
- volRows := []orm.Params{}
- _, err := db.Raw("select t.vol, CAST(REPLACE(UPPER(g.name),'KV','') as SIGNED) volname from t_area_ied_relation t,global_const_code g where g.code=CONCAT('v_level_',t.vol) and g.parentcode='voltage_level' and t.vol!=999 and t.scd_id=? GROUP BY t.vol ORDER BY volname desc", c.ScdId).Values(&volRows)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- if len(volRows) == 0 {
- logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
- return
- }
- volMap := map[string]string{}
- volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
- if len(volRows) == 2 {
- volMap["middle"] = ""
- volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
- } else {
- volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
- volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
- }
- var getIedByDesc = func(iedinfo map[string]orm.Params, iedtpye string, desc string) ([]string, []string) {
- scdParseMgr := new(ScdParse)
- scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
- r1 := []string{}
- r2 := []string{}
- for vn, row := range iedinfo {
- if strings.HasPrefix(vn, iedtpye) {
- v := tools.IsEmpty(row["ied_desc"])
- if v == "" {
- if scdXmlObj == nil {
- continue
- }
- scdNode := new(ScdNode)
- ied := scdNode.GetIed(scdXmlObj, "", vn)
- if ied == nil {
- continue
- }
- v = ied.Desc
- }
- if strings.Contains(v, desc) {
- r1 = append(r1, v)
- r2 = append(r2, vn)
- }
- }
- }
- return r1, r2
- }
- //判断是否将各电压等级的保护装置合并还是分开的间隔
- //如果存在高中低压的保护装置,则说明是分开的主变间隔
- ptCode := c.getIedTypeCode(modelid, "PT")
- volValue := "" //电压等级值
- if strings.Index(","+iedtypes+",", ","+ptCode+",") == -1 {
- //判断主变保护是否是按电压等级分开配置的模型
- h, m, l := c.getIedListByVol(ptCode, ieds, volMap)
- if strings.Contains(iedtypes, ptCode+"#H") && len(h) > 0 {
- //高压侧装置
- volValue = "H"
- } else if strings.Contains(iedtypes, ptCode+"#M") && len(m) > 0 {
- volValue = "M"
- } else if strings.Contains(iedtypes, ptCode+"#L") && len(l) > 0 {
- volValue = "L"
- }
- }
- pmCode := c.getIedTypeCode(modelid, "PM")
- mmCode := c.getIedTypeCode(modelid, "MM")
- ctCode := c.getIedTypeCode(modelid, "CT")
- delPm := false
- delMm := false
- for _, row := range ieds {
- if tools.IsEmpty(row["ied_type"]) != ptCode[0:1] || tools.IsEmpty(row["p_type"]) != ptCode[1:] {
- continue
- }
- if _, h := groupList[ptCode]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- pl_iedname := tools.IsEmpty(row["ied_name"])
- iednameParts := scdParseMgr.ParseIedName(pl_iedname)
- areadesc := tools.IsEmpty(row["ied_desc"])
- if areadesc == "" {
- iedobj := scdNodeMgr.GetIed(scdXmlObj, "", pl_iedname)
- if iedobj != nil {
- areadesc = iedobj.Desc
- } else {
- areadesc = tools.IsEmpty(row["area_name"])
- }
- }
- areadesc = strings.ReplaceAll(areadesc, "装置", "")
- //添加间隔数据
- dbdata := T_data_check_area{
- ModelId: modelid,
- ScdId: c.ScdId,
- AreaType: "T",
- AreaName: areadesc + iednameParts[7],
- }
- newid, err := db.Insert(&dbdata)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
- insvalues := []string{}
- inAreaIedName := ""
- //insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "T"))
- for _, ty := range strings.Split(iedtypes, ",") {
- inAreaIedName = ""
- if _, h := groupList[ty]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- //判断是否指定的套别标识
- abCode := c.getIedTypeABCode(ty)
- if abCode != "" {
- iednameParts[7] = abCode
- }
- tyCode := c.getIedTypeCode(modelid, ty)
- if _, h := groupList[tyCode]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- if tyCode[0:len(pmCode)] == pmCode {
- //PM和MM最后处理
- delPm = true
- continue
- }
- if tyCode[0:len(mmCode)] == mmCode {
- //PM和MM最后处理
- delMm = true
- continue
- }
- ptype := strings.Split(tyCode, "#")[0]
- //判断间隔是否需要包含差动装置
- if strings.Contains(tyCode, "#C") {
- _, iedname := getIedByDesc(ieds, tyCode, "差动")
- if len(iedname) > 0 {
- for _, in := range iedname {
- tmpIednameParts := scdParseMgr.ParseIedName(in)
- if tmpIednameParts[6] == iednameParts[6] && tmpIednameParts[7] == iednameParts[7] {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, in, ptype[0:1], ptype[1:]))
- break
- }
- }
- }
- }
- //判断间隔是否需要包含本体保护装置
- if strings.Contains(tyCode, "#0") {
- _, iedname := getIedByDesc(ieds, tyCode, "本体")
- if len(iedname) > 0 {
- for _, in := range iedname {
- tmpIednameParts := scdParseMgr.ParseIedName(in)
- if tmpIednameParts[6] == iednameParts[6] && tmpIednameParts[7] == iednameParts[7] {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, in, ptype[0:1], ptype[1:]))
- break
- }
- }
- }
- }
- dlIeds := []orm.Params{}
- imtcode := c.getIedTypeCode(modelid, tyCode)
- h, m, l := c.getIedListByVol(imtcode, ieds, volMap, abCode)
- //logger.Logger.Debug(fmt.Sprintf("tyCode:%s H:%+v,M:%+v,L:%+v", tyCode, h, m, l))
- if volValue == "" || volValue == "H" {
- dlIeds = append(dlIeds, h...)
- }
- if volValue == "" || volValue == "M" {
- dlIeds = append(dlIeds, m...)
- }
- if volValue == "" || volValue == "L" {
- dlIeds = append(dlIeds, l...)
- }
- for _, r := range dlIeds {
- inAreaIedName = tools.IsEmpty(r["ied_name"])
- tmpIednameParts := scdParseMgr.ParseIedName(inAreaIedName)
- if tyCode[0:len(ctCode)] == ctCode {
- //CT单独处理。它可能不分AB套
- lastChar := tmpIednameParts[7]
- if tmpIednameParts[6] == iednameParts[6] && (lastChar == "" || lastChar == iednameParts[7]) {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- } else {
- if tmpIednameParts[6] == iednameParts[6] && tmpIednameParts[7] == iednameParts[7] {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- }
- }
- }
- //最后处理PM和MM
- inAreaIedName = c.getPMName(iednameParts, ieds)
- if delPm && inAreaIedName != "" {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "P", "M"))
- //pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
- //使用PM装置的名称去定义MM的名称
- inAreaIedName = c.getMMName(iednameParts, ieds, iednameParts[7])
- if delMm && inAreaIedName != "" {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "M"))
- }
- }
- //写数据库
- if len(insvalues) > 0 {
- _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
- }
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- }
- }
- //线路间隔分析
- //vol:电压等级
- func (c *CheckAreaMgr) pL(modelid int, vol, iedtypes string, ieds map[string]orm.Params) {
- scdParseMgr := new(ScdParse)
- scdNodeMgr := new(ScdNode)
- db := orm.NewOrm()
- //获取装置分组信息
- bgm := new(SysCheckModelIedtypeGroupMgr)
- bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
- groupList := bgm.List()
- scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
- iedCode := c.getIedTypeCode(modelid, "PL")
- for _, row := range ieds {
- if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != iedCode[0:1] || tools.IsEmpty(row["p_type"]) != iedCode[1:] {
- continue
- }
- pmIedName := ""
- mmIedName := ""
- pl_iedname := tools.IsEmpty(row["ied_name"])
- if _, h := groupList[pl_iedname]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- iednameParts := scdParseMgr.ParseIedName(pl_iedname)
- areadesc := tools.IsEmpty(row["ied_desc"])
- if areadesc == "" {
- iedobj := scdNodeMgr.GetIed(scdXmlObj, "", pl_iedname)
- if iedobj != nil {
- areadesc = iedobj.Desc
- } else {
- areadesc = tools.IsEmpty(row["area_name"])
- }
- }
- areadesc = strings.ReplaceAll(areadesc, "装置", "")
- //添加间隔数据
- dbdata := T_data_check_area{
- ModelId: modelid,
- ScdId: c.ScdId,
- AreaType: "L",
- AreaName: areadesc + iednameParts[7],
- }
- newid, err := db.Insert(&dbdata)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
- insvalues := []string{}
- pmCode := c.getIedTypeCode(modelid, "PM")
- mmCode := c.getIedTypeCode(modelid, "MM")
- clCode := c.getIedTypeCode(modelid, "CL")
- for _, ty := range strings.Split(iedtypes, ",") {
- inAreaIedName := ""
- if _, h := groupList[ty]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- abCode := c.getIedTypeABCode(ty)
- if abCode != "" {
- iednameParts[7] = abCode
- }
- tyCode := c.getIedTypeCode(modelid, ty)
- if _, h := groupList[tyCode]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- ptype := strings.Split(tyCode, "#")[0]
- if tyCode == pmCode {
- //母线保护和母线合并单元装置编号跟随变压器
- //查找变压器编号
- //1号变压器->2号变压器->3号
- inAreaIedName = c.getPMName(iednameParts, ieds)
- pmIedName = inAreaIedName
- if mmIedName == "" {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:2]))
- //pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
- //使用PM装置的名称去定义MM的名称
- tyCode = mmCode
- inAreaIedName = c.getMMName(iednameParts, ieds, iednameParts[7])
- mmIedName = inAreaIedName
- }
- } else if tyCode == mmCode {
- if pmIedName != "" && mmIedName == "" {
- //pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
- //使用PM装置的名称去定义MM的名称
- inAreaIedName = c.getMMName(iednameParts, ieds, iednameParts[7])
- mmIedName = inAreaIedName
- } else {
- continue
- }
- } else {
- inAreaIedName = ptype + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
- }
- if strings.Index("ABCDE", iednameParts[7]) > -1 {
- //最后一位是字母则说明是AB套
- switch ptype {
- case clCode:
- if strings.Contains(iedtypes, "PLC") || strings.Contains(iedtypes, "PCL") {
- //不处理CL装置
- } else {
- //测控装置,先判断是否分了AB套,没有标识(ied名称的最后一位是否是字母)则说明是多套共用装置
- if ieds[inAreaIedName] == nil {
- //当前测控装置没有分AB套
- inAreaIedName = ptype + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6]
- }
- }
- break
- default:
- break
- }
- }
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- //如果mm装置还未确定
- if mmIedName == "" {
- //pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
- inAreaIedName := c.getMMName(iednameParts, ieds, iednameParts[7])
- _, err = db.Raw(ins1 + fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, "M", "M")).Exec()
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- }
- }
- }
- //母联间隔分析
- func (c *CheckAreaMgr) pJ(modelid int, vol, iedtypes string, ieds map[string]orm.Params, pjIed string) {
- scdParseMgr := new(ScdParse)
- scdNodeMgr := new(ScdNode)
- db := orm.NewOrm()
- pjIed = c.getIedTypeCode(modelid, pjIed)
- scdXmlObject, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
- for _, row := range ieds {
- if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != pjIed[0:1] || tools.IsEmpty(row["p_type"]) != pjIed[1:2] {
- continue
- }
- pmIedName := ""
- mmIedName := ""
- pl_iedname := tools.IsEmpty(row["ied_name"])
- iednameParts := scdParseMgr.ParseIedName(pl_iedname)
- areadesc := tools.IsEmpty(row["ied_desc"])
- if areadesc == "" {
- iedobj := scdNodeMgr.GetIed(scdXmlObject, "", pl_iedname)
- if iedobj != nil {
- areadesc = iedobj.Desc
- } else {
- areadesc = tools.IsEmpty(row["area_name"])
- }
- }
- areadesc = strings.ReplaceAll(areadesc, "装置", "")
- //添加间隔数据
- dbdata := T_data_check_area{
- ModelId: modelid,
- ScdId: c.ScdId,
- AreaType: "J",
- AreaName: areadesc + iednameParts[7],
- }
- newid, err := db.Insert(&dbdata)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
- insvalues := []string{}
- pmCode := c.getIedTypeCode(modelid, "PM")
- mmCode := c.getIedTypeCode(modelid, "MM")
- for _, ty := range strings.Split(iedtypes, ",") {
- abCode := c.getIedTypeABCode(ty)
- if abCode != "" {
- iednameParts[7] = abCode
- }
- tyCode := c.getIedTypeCode(modelid, ty)
- ptype := strings.Split(tyCode, "#")[0]
- inAreaIedName := ""
- if tyCode == pmCode {
- //母线保护和母线合并单元装置编号跟随变压器
- //查找变压器编号
- //1号变压器->2号变压器->3号
- inAreaIedName = c.getPMName(iednameParts, ieds)
- pmIedName = inAreaIedName
- if mmIedName == "" {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
- //使用PM装置的名称去定义MM的名称
- tyCode = "MM"
- inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
- mmIedName = inAreaIedName
- }
- } else if tyCode == mmCode {
- if pmIedName != "" && mmIedName == "" {
- pmIedNameParts := scdParseMgr.ParseIedName(pmIedName)
- //使用PM装置的名称去定义MM的名称
- inAreaIedName = c.getMMName(pmIedNameParts, ieds, iednameParts[7])
- mmIedName = inAreaIedName
- } else {
- continue
- }
- } else {
- inAreaIedName = ptype + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6] + iednameParts[7]
- //判断与基准保护装置相同套号的装置是否存在
- if ieds[inAreaIedName] == nil {
- //尝试去除套号
- inAreaIedName = ptype + iednameParts[3] + iednameParts[4] + iednameParts[5] + iednameParts[6]
- }
- }
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- }
- }
- //母线间隔装置提取
- func (c *CheckAreaMgr) pM(modelid int, vol, iedtypes string, ieds map[string]orm.Params) {
- scdParseMgr := new(ScdParse)
- scdNodeMgr := new(ScdNode)
- db := orm.NewOrm()
- //获取当前站的各电压等级
- volRows := []orm.Params{}
- _, err := db.Raw("select t.vol, CAST(REPLACE(UPPER(g.name),'KV','') as SIGNED) volname from t_area_ied_relation t,global_const_code g where g.code=CONCAT('v_level_',t.vol) and g.parentcode='voltage_level' and t.vol!=999 and t.scd_id=? GROUP BY t.vol ORDER BY volname desc", c.ScdId).Values(&volRows)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- if len(volRows) == 0 {
- logger.Logger.Error(errors.New("该scd未发现任何电压等级的装置"))
- return
- }
- volMap := map[string]string{}
- volMap["hight"] = tools.IsEmpty(volRows[0]["vol"]) //高压电压
- if len(volRows) == 2 {
- volMap["middle"] = ""
- volMap["low"] = volRows[1]["vol"].(string) //低压电压等级
- } else {
- volMap["middle"] = volRows[1]["vol"].(string) //中压电压等级
- volMap["low"] = volRows[len(volRows)-1]["vol"].(string) //低压电压等级
- }
- //获取装置分组信息
- bgm := new(SysCheckModelIedtypeGroupMgr)
- bgm.Model = T_data_model_iedtype_group{ModelId: modelid}
- groupList := bgm.List()
- scdXmlObj, _ := scdParseMgr.GetScdXmlObjectBySCDID(tools.IsEmpty(c.ScdId))
- iedCode := c.getIedTypeCode(modelid, "PM")
- for _, row := range ieds {
- if tools.IsEmpty(row["vol"]) != vol || tools.IsEmpty(row["ied_type"]) != iedCode[0:1] || tools.IsEmpty(row["p_type"]) != iedCode[1:] {
- continue
- }
- pl_iedname := tools.IsEmpty(row["ied_name"])
- iednameParts := scdParseMgr.ParseIedName(pl_iedname)
- areadesc := tools.IsEmpty(row["ied_desc"])
- if areadesc == "" {
- iedobj := scdNodeMgr.GetIed(scdXmlObj, "", pl_iedname)
- if iedobj != nil {
- areadesc = iedobj.Desc
- } else {
- areadesc = tools.IsEmpty(row["area_name"])
- }
- }
- areadesc = strings.ReplaceAll(areadesc, "装置", "")
- //添加间隔数据
- dbdata := T_data_check_area{
- ModelId: modelid,
- ScdId: c.ScdId,
- AreaType: "M",
- AreaName: areadesc,
- }
- newid, err := db.Insert(&dbdata)
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- pmVol := "" //当前PM装置的电压等级
- for volLevel, volValue := range volMap {
- if volValue == iednameParts[3]+iednameParts[4] {
- pmVol = volLevel
- break
- }
- }
- ins1 := "insert into t_data_check_area_ied(scd_id,area_id,ied_name,ied_type,p_type)values"
- insvalues := []string{}
- mmCode := c.getIedTypeCode(modelid, "MM")
- for _, ty := range strings.Split(iedtypes, ",") {
- inAreaIedName := ""
- if _, h := groupList[ty]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- abCode := c.getIedTypeABCode(ty)
- if abCode == "" {
- //未特别指定套别时,采用主IED装置的套别
- abCode = iednameParts[7]
- }
- tyCode := c.getIedTypeCode(modelid, ty)
- if _, h := groupList[tyCode]; h {
- //装置如果是分组成员装置,则不用检测
- continue
- }
- ptype := strings.Split(tyCode, "#")[0]
- if tyCode == mmCode {
- //MM:母线合并单元
- inAreaIedName = c.getMMName(iednameParts, ieds, abCode)
- if inAreaIedName != "" {
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- } else {
- //需要查找同电压等级的所有同类同套装置
- h, m, l := c.getIedListByVol(tyCode, ieds, volMap, abCode)
- //logger.Logger.Debug(fmt.Sprintf("当前PM装置:%s 电压等级:%s 提取类型:%s 套别:%s h:%+v,m:%+v,l:%+v", pl_iedname, pmVol, ptype, abCode, h, m, l))
- switch pmVol {
- case "hight":
- for _, item := range h {
- inAreaIedName = tools.IsEmpty(item["ied_name"])
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- break
- case "middle":
- for _, item := range m {
- inAreaIedName = tools.IsEmpty(item["ied_name"])
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- break
- case "low":
- for _, item := range l {
- inAreaIedName = tools.IsEmpty(item["ied_name"])
- insvalues = append(insvalues, fmt.Sprintf("(%d,%d,'%s','%s','%s')", c.ScdId, newid, inAreaIedName, ptype[0:1], ptype[1:]))
- }
- break
- }
- }
- }
- if len(insvalues) == 0 {
- continue
- }
- _, err = db.Raw(ins1 + strings.Join(insvalues, ",")).Exec()
- if err != nil {
- logger.Logger.Error(err)
- return
- }
- }
- }
- //母联间隔装置关系检查
- func (c *CheckAreaMgr) cJ(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, pjIed, area_ruleid string) {
- modelidInt, _ := strconv.Atoi(modelid)
- pjIed = c.getIedTypeCode(modelidInt, pjIed)
- masterIed := new(node_attr.NIED)
- findIedName := ""
- for _, row2 := range area_ieds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- if strings.HasPrefix(findIedName, pjIed) {
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
- break
- }
- }
- if masterIed == nil {
- return
- }
- dealFromIed := map[string]int{}
- for _, row := range ied_refs {
- fromiedtype := c.getIedTypeCode(modelidInt, tools.IsEmpty(row["from_ied_code"]))
- toiedtype := c.getIedTypeCode(modelidInt, tools.IsEmpty(row["to_ied_code"]))
- reftype := tools.IsEmpty(row["in_type"])
- tmpFromAreaIeds := []orm.Params{}
- tmpToAreaIeds := []orm.Params{}
- for _, row2 := range area_ieds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- if strings.HasPrefix(findIedName, fromiedtype) {
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
- if masterIed != nil {
- tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
- } else {
- if dealFromIed[findIedName] == 0 {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- dealFromIed[findIedName] = 1
- }
- }
- if strings.HasPrefix(findIedName, toiedtype) {
- tmpToAreaIeds = append(tmpToAreaIeds, row2)
- }
- }
- if len(tmpFromAreaIeds) == 0 {
- continue
- }
- if len(tmpToAreaIeds) == 0 {
- parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- continue
- }
- toIedname := ""
- for _, row2 := range tmpFromAreaIeds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- hasToIedRef := false
- hasToIed := false
- for _, row3 := range tmpToAreaIeds {
- toIedname = tools.IsEmpty(row3["ied_name"])
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", toIedname)
- if masterIed != nil {
- hasToIed = true
- // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
- inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
- logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
- if inout != nil {
- outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
- for _, ieditem := range outiedlist {
- outiedname := ieditem["ref_ied_name"].(string)
- if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
- hasToIedRef = true
- break
- }
- }
- }
- if !hasToIedRef {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- }
- }
- if !hasToIed {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- }
- }
- }
- //线路间隔装置关系检查
- func (c *CheckAreaMgr) cL(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, area_ruleid string) {
- modelidInt, _ := strconv.Atoi(modelid)
- //获取装置分组信息
- bgm := new(SysCheckModelIedtypeGroupMgr)
- bgm.Model = T_data_model_iedtype_group{ModelId: modelidInt}
- groupList := bgm.List()
- plIed := c.getIedTypeCode(modelidInt, "PL")
- if v, h := groupList[plIed]; h {
- //装置如果是分组成员装置
- plIed = v
- }
- masterIed := new(node_attr.NIED)
- findIedName := ""
- for _, row2 := range area_ieds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- if strings.HasPrefix(findIedName, plIed) {
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
- break
- }
- }
- if masterIed == nil {
- return
- }
- logger.Logger.Debug(fmt.Sprintf("开始分析模型%d的线路间隔关系", modelidInt))
- dealFromIed := map[string]int{}
- for _, row := range ied_refs {
- fromiedtype := c.getIedTypeCode(modelidInt, tools.IsEmpty(row["from_ied_code"]))
- toiedtype := c.getIedTypeCode(modelidInt, tools.IsEmpty(row["to_ied_code"]))
- reftype := tools.IsEmpty(row["in_type"])
- tmpFromAreaIeds := []orm.Params{}
- tmpToAreaIeds := []orm.Params{}
- for _, row2 := range area_ieds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- if strings.HasPrefix(findIedName, fromiedtype) {
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
- if masterIed != nil {
- tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
- } else {
- if dealFromIed[findIedName] == 0 {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": "",
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- dealFromIed[findIedName] = 1
- }
- }
- if strings.HasPrefix(findIedName, toiedtype) {
- tmpToAreaIeds = append(tmpToAreaIeds, row2)
- }
- }
- if len(tmpFromAreaIeds) == 0 {
- continue
- }
- if len(tmpToAreaIeds) == 0 {
- parse_result := fmt.Sprintf("间隔%s缺失类型为%s的装置", area_name, toiedtype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result}
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- continue
- }
- toIedname := ""
- for _, row2 := range tmpFromAreaIeds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- hasToIedRef := false
- hasToIed := false
- for _, row3 := range tmpToAreaIeds {
- toIedname = tools.IsEmpty(row3["ied_name"])
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", toIedname)
- if masterIed != nil {
- hasToIed = true
- // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
- inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
- //logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
- if inout != nil {
- outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
- for _, ieditem := range outiedlist {
- outiedname := ieditem["ref_ied_name"].(string)
- if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
- hasToIedRef = true
- break
- }
- }
- }
- if !hasToIedRef {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": toIedname,
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- }
- }
- if !hasToIed {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": toIedname,
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- }
- }
- }
- //变压器间隔装置关系检查
- func (c *CheckAreaMgr) cT(modelid string, scdXmlObj *node_attr.SCL, scdNodeMgr *ScdNode, scdNodeRule *ScdNodeRule, area_name string, ied_refs []orm.Params, area_ieds []orm.Params, area_ruleid string, HasAreaJ bool) {
- masterIed := new(node_attr.NIED)
- findIedName := ""
- modelidInt, _ := strconv.Atoi(modelid)
- ptIed := c.getIedTypeCode(modelidInt, "PT")
- for _, row2 := range area_ieds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- if strings.HasPrefix(findIedName, ptIed) {
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
- break
- }
- }
- if masterIed == nil {
- return
- }
- scdParseMgr := new(ScdParse)
- dealFromIed := map[string]int{}
- for _, row := range ied_refs {
- fromiedtype := c.getIedTypeCode(modelidInt, tools.IsEmpty(row["from_ied_code"]))
- fromiedtype = strings.Split(fromiedtype, "#")[0] //去除后面的电压级别标识
- toiedtype := strings.Split(c.getIedTypeCode(modelidInt, tools.IsEmpty(row["to_ied_code"])), "#")[0] //去除后面的电压级别标识
- reftype := tools.IsEmpty(row["in_type"])
- tmpFromAreaIeds := []orm.Params{}
- tmpToAreaIeds := []orm.Params{}
- for _, row2 := range area_ieds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- if strings.HasPrefix(findIedName, fromiedtype) {
- masterIed = scdNodeMgr.GetIed(scdXmlObj, "", findIedName)
- if masterIed != nil {
- tmpFromAreaIeds = append(tmpFromAreaIeds, row2)
- } else {
- if dealFromIed[findIedName] == 0 {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失", area_name, findIedName)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": "",
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- dealFromIed[findIedName] = 1
- }
- }
- if strings.HasPrefix(findIedName, toiedtype) {
- tmpToAreaIeds = append(tmpToAreaIeds, row2)
- }
- }
- if len(tmpFromAreaIeds) == 0 {
- continue
- }
- if len(tmpToAreaIeds) == 0 {
- logger.Logger.Debug(fmt.Sprintf("缺失类型关联装置 :%+v", row))
- parse_result := fmt.Sprintf("间隔%s缺失类型为%s的%s信号装置", area_name, toiedtype, reftype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": "",
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- continue
- }
- toIedname := ""
- for _, row2 := range tmpFromAreaIeds {
- findIedName = tools.IsEmpty(row2["ied_name"])
- hasToIedRef := false
- hasToIed := false
- t1 := fromiedtype + "->" + toiedtype
- volLevel := "" //电压等级
- if t1 == "CT->IT" || t1 == "IT->CT" || t1 == "CT->IB" || t1 == "IB->CT" || t1 == "MM->MT" || t1 == "PM->IB" || t1 == "IB->PM" || t1 == "PM->IT" || t1 == "IT->PM" {
- ps := scdParseMgr.ParseIedName(findIedName)
- volLevel = ps[3] + ps[4]
- }
- hasSameVolIed := false
- for _, row3 := range tmpToAreaIeds {
- toIedname = tools.IsEmpty(row3["ied_name"])
- if volLevel != "" {
- ps := scdParseMgr.ParseIedName(toIedname)
- if volLevel != ps[3]+ps[4] {
- //排除不是同一电压等级的装置
- continue
- }
- hasSameVolIed = true
- }
- if scdNodeMgr.GetIed(scdXmlObj, "", toIedname) != nil {
- hasToIed = true
- // 获取该ied的输出(ref_type为0)装置,并从中检测是否存在toiedtype类型的装置
- inout, _ := scdNodeMgr.GetIedRelations(map[string]interface{}{"scd_id": c.ScdId, "ied_name": findIedName})
- //logger.Logger.Debug(fmt.Sprintf("ied:%s refs:%+v", findIedName, inout))
- if inout != nil {
- outiedlist := inout[findIedName].(orm.Params)["list"].([]orm.Params)
- for _, ieditem := range outiedlist {
- outiedname := ieditem["ref_ied_name"].(string)
- if outiedname == toIedname && ieditem["ref_type"].(string) == "0" {
- hasToIedRef = true
- break
- }
- }
- }
- if !hasToIedRef {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失与装置%s的%s信号关联", area_name, findIedName, toIedname, reftype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": toIedname,
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- }
- if hasSameVolIed {
- break
- }
- }
- if toiedtype != ptIed {
- if volLevel != "" && !hasSameVolIed {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失同电压等级的关联类型%s装置", area_name, findIedName, toiedtype)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": "",
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- } else if !hasToIed {
- parse_result := fmt.Sprintf("间隔%s的装置%s缺失关联装置%s", area_name, findIedName, toIedname)
- r := map[string]interface{}{"scdid": c.ScdId, "lineno": 0, "ruleid": area_ruleid, "nodeid": 0, "parse_result": parse_result,
- "ied_name": findIedName,
- "ied_desc": "",
- "out_ied_name": toIedname,
- "out_ied_desc": "",
- "fcda_desc": "",
- "fcda_addr": "",
- "out_fcda_desc": "",
- "out_fcda_addr": "",
- "error_type": "9",
- }
- //检查未通过
- scdNodeRule.AppendFcdaCheckResult(r)
- }
- }
- }
- }
- }
- //根据参考ied name找出应该关联PM装置
- //abcode:套别标识代码。可选。不指定时将自动从iedtype识别
- func (c *CheckAreaMgr) getPMName(iednameParts []string, ieds map[string]orm.Params, abcode ...string) string {
- //如果只有一个PM装置,则直接返回该 装置
- pmLst := []string{}
- for n, _ := range ieds {
- if strings.HasPrefix(n, "PM"+iednameParts[3]+iednameParts[4]) {
- pmLst = append(pmLst, n)
- }
- }
- if len(pmLst) == 1 {
- return pmLst[0]
- }
- ab := ""
- if len(abcode) > 0 {
- ab = abcode[0]
- }
- //暴力匹配
- for _, n := range pmLst {
- if ab != "" {
- //优先完全匹配指定套别
- if strings.HasSuffix(n, ab) {
- return n
- }
- continue
- }
- if strings.HasSuffix(n, iednameParts[7]) {
- return n
- }
- }
- return ""
- }
- //根据参考ied name找出应该关联MM装置
- func (c *CheckAreaMgr) getMMName(iednameParts []string, ieds map[string]orm.Params, ab string) string {
- mmLst := []string{}
- for n, _ := range ieds {
- if strings.HasPrefix(n, "MM"+iednameParts[3]+iednameParts[4]) {
- mmLst = append(mmLst, n)
- }
- }
- if len(mmLst) == 1 {
- return mmLst[0]
- }
- for _, n := range mmLst {
- if ab != "" && strings.HasSuffix(n, ab) {
- return n
- }
- if ab == "" && strings.HasSuffix(n, iednameParts[5]+iednameParts[6]) {
- return n
- }
- }
- return ""
- }
- //获取装置编码中的套别代码(A、B..)
- func (c *CheckAreaMgr) getIedTypeABCode(iedtype string) string {
- if strings.Index(iedtype, "-") > 0 {
- return strings.Split(iedtype, "-")[1]
- }
- return ""
- }
- //根据当前设备列表,分析出电压等级(高、中、低)的设备列表
- // CT测控、IT智能终端、MT合并单元需要判断是否是本体装置,是则将其归为主变高压侧
- //iedtype:装置编码
- //ieds:装置筛选范围列表
- //vollevel:电压等级代码。H:高压 M:中压 L:低压
- //abcode:套别标识代码。可选。不指定时将自动从iedtype识别
- func (c *CheckAreaMgr) getIedListByVol(iedtype string, ieds map[string]orm.Params, vollevel map[string]string, abcode ...string) (hightLst, middleLst, lowLst []orm.Params) {
- tmpLst := map[string][]orm.Params{}
- for _, v := range vollevel {
- tmpLst[v] = []orm.Params{}
- }
- ab := ""
- if len(abcode) > 0 {
- ab = abcode[0]
- }
- if strings.Index(iedtype, "-") > 0 {
- //去除套别标识
- iedtype = strings.Split(iedtype, "-")[0]
- if ab == "" {
- ab = strings.Split(iedtype, "-")[1]
- }
- }
- it := strings.Split(iedtype, "#")
- scdParseMgr := new(ScdParse)
- for _, row := range ieds {
- pl_iedname := tools.IsEmpty(row["ied_name"])
- if pl_iedname[0:len(it[0])] != it[0] {
- continue
- }
- iednameParts := scdParseMgr.ParseIedName(pl_iedname)
- if ab != "" && iednameParts[7] != ab {
- //指定了套别时,装置套别必须与指定套别完全相同
- continue
- }
- volvalue := iednameParts[3] + iednameParts[4]
- if tmpLst[volvalue] == nil {
- tmpLst[volvalue] = []orm.Params{row}
- } else {
- tmpLst[volvalue] = append(tmpLst[volvalue], row)
- }
- }
- if len(it) > 1 {
- if it[1] == "H" {
- return tmpLst[vollevel["hight"]], []orm.Params{}, []orm.Params{}
- }
- if it[1] == "M" {
- return []orm.Params{}, tmpLst[vollevel["middle"]], []orm.Params{}
- }
- if it[1] == "L" {
- return []orm.Params{}, []orm.Params{}, tmpLst[vollevel["low"]]
- }
- }
- return tmpLst[vollevel["hight"]], tmpLst[vollevel["middle"]], tmpLst[vollevel["low"]]
- }
- func (c *CheckAreaMgr) GetCheckResult(scdid int64) ([]orm.Params, error) {
- db := orm.NewOrm()
- rowset := []orm.Params{}
- sql := "select *,case error_type when 1 then '多余' when 2 then '错误' when 3 then '缺失' else '其他' end error_type_desc from t_scd_fcda_check_result where scd_id=? order by ied_name,out_ied_name,error_type"
- _, err := db.Raw(sql, scdid).Values(&rowset)
- return rowset, err
- }
|