123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779 |
- package bo
- import (
- "encoding/json"
- "encoding/xml"
- "errors"
- "fmt"
- "io/fs"
- "log"
- "os"
- "os/exec"
- "regexp"
- "runtime"
- "scd_check_tools/conf"
- "scd_check_tools/global"
- "scd_check_tools/logger"
- "scd_check_tools/models/enum"
- "scd_check_tools/models/node_attr"
- "scd_check_tools/mqtt"
- "scd_check_tools/tools"
- "strconv"
- "strings"
- "sync"
- "time"
- "github.com/astaxie/beego/orm"
- )
- //SCD管理
- type ScdMgr struct {
- DeviceBaseModel
- //设置删除scd数据时是否是同步模式,同步模式下会等待数据删除完成时才返回结果;反之为后台删除模式.默认为异步删除模式
- SyncDeleteMod bool
- }
- func (c *ScdMgr) IedTotal(stationid string) (int, error) {
- dblog := new(SystemLog)
- dblog.SetUserInfo(c.GetUserInfo())
- dblog.Audittype = enum.AuditType_scd_show
- dblog.Logtype = enum.LogType_datastat
- dblog.Eventtype = enum.OptEventType_Bus
- dblog.Eventlevel = enum.OptEventLevel_Low
- db := orm.NewOrm()
- sql := "select count(0) cnt from t_scd_node_scl t,(select max(id) scd_id from t_scd_scl where enable=1 and station_id=?) t1 where t.scd_id=t1.scd_id and t.node_name='IED'"
- rowset := []orm.Params{}
- _, err := db.Raw(sql, stationid).Values(&rowset)
- dblog.Description = fmt.Sprintf("SQL:%s,参数:%+v", sql, stationid)
- if err != nil {
- logger.Logger.Error(err, dblog.Description)
- dblog.Fail2()
- return 0, err
- }
- dblog.Success2()
- if len(rowset) == 0 {
- return 0, nil
- }
- cnt, _ := strconv.Atoi(tools.IsEmpty(rowset[0]["cnt"]))
- return cnt, nil
- }
- func (c *ScdMgr) IedStat(param map[string]interface{}) (map[string]interface{}, error) {
- var result = map[string]interface{}{}
- result["data"] = []orm.Params{}
- constCode := new(Global)
- list, _ := constCode.GetChildrenGlobalCode("device_type")
- result["comments"] = list
- db := orm.NewOrm()
- sqlParams := []interface{}{}
- uaObj := new(UserAreaRelationObject)
- uaObj.SetUserInfo(c.GetUserInfo())
- areaFilerWhere := uaObj.MakeAreaFilerIds("station_id", "and")
- scdSql := "select max(id) scd_id from t_scd_scl where enable=1 " + areaFilerWhere + " group by station_id"
- station_id := tools.IsEmpty(param["station_id"])
- if station_id != "" {
- scdSql = "select max(id) scd_id from t_scd_scl where enable=1 and station_id=?"
- sqlParams = append(sqlParams, station_id)
- }
- sql := `
- select t.ied_type,count(0) cnt from t_area_ied_relation t ,
- (` + scdSql + `) t1
- where t.scd_id=t1.scd_id GROUP BY t.ied_type`
- rowset := []orm.Params{}
- _, err := db.Raw(sql, sqlParams).Values(&rowset)
- dblog := new(SystemLog)
- dblog.SetUserInfo(c.GetUserInfo())
- dblog.Audittype = enum.AuditType_scd_show
- dblog.Logtype = enum.LogType_datastat
- dblog.Eventtype = enum.OptEventType_Bus
- dblog.Eventlevel = enum.OptEventLevel_Low
- dblog.Description = fmt.Sprintf("SQL:%s,参数:%+v", sql, sqlParams)
- if err != nil {
- logger.Logger.Error(err, dblog.Description)
- dblog.Fail2()
- return nil, err
- }
- dblog.Success2()
- result["data"] = rowset
- return result, nil
- }
- func (c *ScdMgr) GetLastScd(stationid string) (orm.Params, error) {
- dblog := new(SystemLog)
- dblog.SetUserInfo(c.GetUserInfo())
- dblog.Audittype = enum.AuditType_scd_show
- dblog.Logtype = enum.LogType_Query
- dblog.Eventtype = enum.OptEventType_Bus
- dblog.Eventlevel = enum.OptEventLevel_Low
- db := orm.NewOrm()
- lst := []orm.Params{}
- sql := "select * from t_scd_scl where station_id=? order by id desc limit 0,1"
- _, err := db.Raw(sql, stationid).Values(&lst)
- dblog.Description = fmt.Sprintf("SQL:%s,参数:%+v", sql, stationid)
- if err != nil {
- logger.Logger.Error(err, dblog.Description)
- dblog.Fail2()
- return nil, err
- }
- dblog.Success2()
- if len(lst) == 0 {
- return nil, nil
- }
- return lst[0], err
- }
- //指定scd解析完成
- //isdefaultRun:是否立即启用为在运版本。1 立即启用 0 不启用
- func (c *ScdMgr) ParseFinish(scdid int64, isdefaultRun ...int) {
- scdidStr := tools.IsEmpty(scdid)
- c.SetParseStateByID(scdidStr, 1)
- v_isdefaultRun := 0
- if len(isdefaultRun) > 0 {
- v_isdefaultRun = isdefaultRun[0]
- }
- if v_isdefaultRun == 1 {
- //解除当前站下的所有scd锁定状态
- c.SetLock("", scdidStr, 0)
- c.SetStateByID(scdidStr, 1)
- c.UpdateScdVersion(scdid, "", "", "")
- c.UpdateRtCrc(scdid)
- }
- go c.CrcCheck(scdidStr)
- }
- //获取并更新唯一校验码
- func (c *ScdMgr) UpdateRtCrc(scdid int64) {
- scdobj, h := global.GoCahce.Get(tools.IsEmpty(scdid))
- if !h {
- logger.Logger.Error(errors.New("未找到scd解析结果缓存!"))
- return
- }
- crc := ""
- for _, item := range scdobj.(*node_attr.SCL).Private {
- if item.Type == global.SCD_CheckoutCrcKey {
- crc = item.InnerText
- break
- }
- }
- if crc == "" {
- return
- }
- //更新scl的签入crc,该crc为通过本系统签出的scd才有
- sql := "update t_scd_scl set in_rt_crc=? where scd_id=? "
- _, err := orm.NewOrm().Raw(sql, crc, scdid).Exec()
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", sql, []interface{}{crc, scdid}))
- }
- }
- func (c *ScdMgr) SetStateByID(scdid string, isenable int) error {
- db := orm.NewOrm()
- _, err := db.Raw("update t_scd_scl set enable=? where id=?", isenable, scdid).Exec()
- return err
- }
- func (c *ScdMgr) SetParseStateByID(scdid string, isenable int) error {
- db := orm.NewOrm()
- _, err := db.Raw("update t_scd_scl set is_parse=? where id=?", isenable, scdid).Exec()
- return err
- }
- //锁定/解锁指定scd
- func (c *ScdMgr) SetLock(stationid, scdid string, islock int) error {
- dblog := new(SystemLog)
- dblog.SetUserInfo(c.GetUserInfo())
- dblog.Audittype = enum.AuditType_scd_parse
- dblog.Logtype = enum.LogType_lock
- dblog.Eventtype = enum.OptEventType_Bus
- dblog.Eventlevel = enum.OptEventLevel_Hight
- db := orm.NewOrm()
- var err error
- sql := ""
- sqlParameters := []interface{}{}
- if scdid == "" {
- sql = "update t_scd_scl set checkout_lock=? where station_id=?"
- sqlParameters = []interface{}{islock, stationid}
- _, err = db.Raw(sql, sqlParameters).Exec()
- } else {
- sql = "update t_scd_scl set checkout_lock=? where station_id=? and id=?"
- sqlParameters = []interface{}{islock, stationid, scdid}
- _, err = db.Raw(sql, sqlParameters).Exec()
- }
- dblog.Description = fmt.Sprintf("SQL:%s,参数:%+v", sql, sqlParameters)
- if err != nil {
- logger.Logger.Error(err, dblog.Description)
- dblog.Fail2()
- return err
- }
- dblog.Success2()
- return nil
- }
- //锁定/解锁指定scd
- func (c *ScdMgr) IsDispose(scdid string) error {
- dblog := new(SystemLog)
- dblog.SetUserInfo(c.GetUserInfo())
- dblog.Audittype = enum.AuditType_scd_parse
- dblog.Logtype = enum.LogType_unlock
- dblog.Eventtype = enum.OptEventType_Bus
- dblog.Eventlevel = enum.OptEventLevel_Hight
- db := orm.NewOrm()
- sql := "update t_scd_scl set checkout_lock=0 where id=?"
- _, err := db.Raw(sql, scdid).Exec()
- dblog.Description = fmt.Sprintf("SQL:%s,参数:%s", sql, scdid)
- if err != nil {
- logger.Logger.Error(err, dblog.Description)
- dblog.Fail2()
- return err
- }
- dblog.Success2()
- return err
- }
- //获取指定站下的已做签出锁定的scd信息
- func (c *ScdMgr) GetCheckoutLockScd(stationid string) ([]orm.Params, error) {
- db := orm.NewOrm()
- sql := "select * from t_scd_scl where station_id=? and checkout_lock=1"
- rowset := []orm.Params{}
- _, err := db.Raw(sql, stationid).Values(&rowset)
- if err != nil {
- log.Println(err)
- return nil, err
- }
- return rowset, nil
- }
- //更新指定scd的版本号
- func (c *ScdMgr) UpdateScdVersion(scdid int64, stationid, scdname, scdpath string) error {
- db := orm.NewOrm()
- var err error
- var err2 error
- db.Begin()
- if scdid > 0 {
- _, err = db.Raw("update t_scd_scl set checkout_lock=0,enable=0, version=replace(version,'在运版','历史版') where id=?", scdid).Exec()
- _, err2 = db.Raw("update t_scd_scl a set a.enable=1,a.version='在运版' where a.id=?", scdid).Exec()
- } else {
- fileFirstChar := scdpath[0:1]
- fline := string(os.PathSeparator)
- if fileFirstChar != "." {
- if fileFirstChar == fline {
- scdpath = "." + scdpath
- } else {
- scdpath = "." + fline + scdpath
- }
- }
- _, err = db.Raw("update t_scd_scl set checkout_lock=0,enable=0, version=replace(version,'在运版','历史版') where station_id=? and version like '在运版%'", stationid).Exec()
- _, err2 = db.Raw("update t_scd_scl a set a.enable=1, a.version='在运版' where a.station_id=? and a.scd_name=? and a.path=?", stationid, scdname, scdpath).Exec()
- }
- if err != nil || err2 != nil {
- db.Rollback()
- if err != nil {
- return err
- }
- if err2 != nil {
- return err2
- }
- }
- db.Commit()
- return nil
- }
- func (c *ScdMgr) SetStateByNamePath(scdname, scdpath string, isenable int) error {
- fileFirstChar := scdpath[0:1]
- fline := string(os.PathSeparator)
- if fileFirstChar != "." {
- if fileFirstChar == fline {
- scdpath = "." + scdpath
- } else {
- scdpath = "." + fline + scdpath
- }
- }
- db := orm.NewOrm()
- _, err := db.Raw("update t_scd_scl set enable=? where scd_name=? and path=?", isenable, scdname, scdpath).Exec()
- return err
- }
- func (c *ScdMgr) List(param map[string]interface{}) ([]orm.Params, int, error) {
- c.ModelTableName = "t_scd_scl"
- db := orm.NewOrm()
- sql := "select t.*,u.name user_name,s.area_name station_name from " + c.ModelTableName + " t left join t_data_user u on t.CREATED_BY=u.id left join t_data_area s on t.station_id=s.id where 1=1 "
- where := []string{}
- sqlParas := []interface{}{}
- //状态默认查询
- if v, ok := param["enable"]; ok {
- v1 := tools.IsEmpty(v)
- if v1 != "" {
- sqlParas = append(sqlParas, v1)
- where = append(where, "t.enable=?")
- }
- }
- if v, ok := param["ischeckinscd"]; ok {
- v1 := tools.IsEmpty(v)
- if v1 != "" {
- sqlParas = append(sqlParas, v1)
- where = append(where, "t.is_checkin_scd=?")
- }
- }
- if v, ok := param["stationid"]; ok {
- v1 := tools.IsEmpty(v)
- if v1 != "" {
- where = append(where, "t.station_id=?")
- sqlParas = append(sqlParas, v)
- } else {
- usObj := new(UserAreaRelationObject)
- usObj.SetUserInfo(c.GetUserInfo())
- usScope := usObj.MakeAreaFilerWhere("t.station_id", "and")
- if usScope != "" {
- where = append(where, usScope)
- }
- }
- }
- if v, ok := param["id"]; ok {
- v1 := tools.IsEmpty(v)
- if v1 != "" {
- where = append(where, "t.id=?")
- sqlParas = append(sqlParas, v)
- }
- }
- if v, ok := param["name"]; ok {
- v1 := tools.IsEmpty(v)
- if v1 != "" {
- where = append(where, "t.name like ?")
- sqlParas = append(sqlParas, "%"+tools.IsEmpty(v)+"%")
- }
- }
- rowset := []orm.Params{}
- if len(where) > 0 {
- where = append([]string{""}, where...)
- }
- pageno, _ := strconv.Atoi(tools.IsEmpty(param["pageno"], "1"))
- pagesize, _ := strconv.Atoi(tools.IsEmpty(param["pagesize"], "100"))
- limit := fmt.Sprintf(" order by t.CREATED_TIME desc limit %d,%d", (pageno-1)*pagesize, pagesize)
- _, err := db.Raw(sql+strings.Join(where, " and ")+limit, sqlParas).Values(&rowset)
- totalCnt := 0
- if err != nil {
- log.Println(err)
- } else {
- totalSql := "select count(1) cnt from " + c.ModelTableName + " t where 1=1 " + strings.Join(where, " and ")
- tmpRowset := []orm.Params{}
- _, err = db.Raw(totalSql, sqlParas).Values(&tmpRowset)
- if err != nil {
- logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", totalSql, sqlParas))
- return nil, 0, err
- }
- totalCnt, _ = strconv.Atoi(tools.IsEmpty(tmpRowset[0]["cnt"]))
- }
- return rowset, totalCnt, err
- }
- //获取指定scd的间隔信息
- func (c *ScdMgr) GetAreaList(scdid string) ([]orm.Params, error) {
- db := orm.NewOrm()
- sql := "select * from t_substation_area where scdid=? order by voltage_level, id"
- rowset := []orm.Params{}
- _, err := db.Raw(sql, scdid).Values(&rowset)
- if err != nil {
- log.Println(err)
- return nil, err
- }
- return rowset, nil
- }
- func (c *ScdMgr) One(id string) (orm.Params, error) {
- key := fmt.Sprintf("scd_info_%s", id)
- if v, h := global.GoCahce.Get(key); h {
- return v.(orm.Params), nil
- }
- para := map[string]interface{}{"id": id}
- rowset, _, err := c.List(para)
- if err == nil && len(rowset) > 0 {
- global.GoCahce.Set(key, rowset[0], -1)
- return rowset[0], nil
- }
- return nil, err
- }
- //检查当前正在解析中的scd是否超过并发解析限制
- //返回true表示当前并发数已满,系统不能接收新的解析请求;false表示允许进行解析新的scd
- //从2方面进行限制:一是设置的最大并发解析数 二是当前服务器性能指标大于80%时不接收新的解析
- func (c *ScdMgr) CheckParseMaxLimit() (bool, string) {
- cpuHC, _ := strconv.Atoi(tools.IsEmpty(conf.GlobalConfig["alarm_cpu_value"], "90")) //cpu高耗用率
- memHC, _ := strconv.Atoi(tools.IsEmpty(conf.GlobalConfig["alarm_mem_value"], "90")) //内存高耗用率
- diskHCC, _ := strconv.Atoi(tools.IsEmpty(conf.GlobalConfig["alarm_disk_value"], "90")) //C磁盘高耗用率
- //内存检查
- if ishc, h := global.PerformanceRuntimeMonitorResult.Load("mem"); h {
- if ishc.(int) > memHC {
- return true, fmt.Sprintf("内存耗用率%d", ishc.(int))
- }
- }
- if ishc, h := global.PerformanceRuntimeMonitorResult.Load("cpu"); h {
- if ishc.(int) > cpuHC {
- return true, fmt.Sprintf("CPU耗用率%d", ishc.(int))
- }
- }
- if ishc, h := global.PerformanceRuntimeMonitorResult.Load("disk"); h {
- if ishc.(int) > diskHCC {
- return true, fmt.Sprintf("磁盘空间耗用率%d", ishc.(int))
- }
- }
- scdparse_max_count, _ := GetSysParamValue("scdparse_max_count", "5")
- db := orm.NewOrm()
- sql := "select 'cnt' cnt, count(1) value from t_scd_scl where is_parse=0 and CREATED_TIME<date_sub(now(),interval 30 MINUTE)"
- result := orm.Params{}
- _, err := db.Raw(sql).RowsToMap(&result, "cnt", "value")
- if err != nil {
- logger.Logger.Error(err)
- return true, err.Error()
- }
- if result == nil {
- return false, ""
- }
- if tools.IsEmpty(result["value"]) >= scdparse_max_count {
- return true, fmt.Sprintf("正在解析SCD数为%d", tools.IsEmpty(result["value"]))
- }
- return false, ""
- }
- //根据scd名称和path返回scd信息
- func (c *ScdMgr) OneByName(scdname, scdpath string) (orm.Params, error) {
- if scdpath == "" || scdname == "" {
- return nil, errors.New("无效的参数!")
- }
- fileFirstChar := scdpath[0:1]
- fline := string(os.PathSeparator)
- if fileFirstChar != "." {
- if fileFirstChar == fline {
- scdpath = "." + scdpath
- } else {
- scdpath = "." + fline + scdpath
- }
- }
- db := orm.NewOrm()
- rowset := []orm.Params{}
- _, err := db.Raw("select t.*,s.area_name station_id from t_scd_scl t,t_data_area s where t.station_id=s.id and t.scd_name=? and t.path=?", scdname, scdpath).Values(&rowset)
- if err == nil && len(rowset) > 0 {
- return rowset[0], nil
- }
- if err != nil {
- logger.Logger.Error(err)
- }
- return nil, err
- }
- //重新解析指定SCD
- func (c *ScdMgr) AginParse(scdid string) error {
- if scdid == "" {
- return errors.New("SCD编号不能为空")
- }
- if h, msg := c.CheckParseMaxLimit(); h {
- return errors.New("系统繁忙:" + msg + ",请稍候(约5分钟)再试")
- }
- //获取scd基本信息
- db := orm.NewOrm()
- sql := "select * from t_scd_scl where id=? "
- rowset := []orm.Params{}
- db.Raw(sql, scdid).Values(&rowset)
- if len(rowset) == 0 {
- return errors.New("无效的SCD编号")
- }
- go func(row orm.Params) {
- db.Raw("update t_scd_scl set is_parse=0 where id=?", scdid).Exec()
- //先清除旧数据
- c.SyncDeleteMod = true
- c.DeleteScd(scdid, false)
- //log.Println("====================清理完成")
- scdObj := GetScdParseInstance()
- ischeckinscd, _ := strconv.Atoi(tools.IsEmpty(row["is_checkin_scd"], "1"))
- scdObj.IsCheckinScd = ischeckinscd
- scdObj.Idseq, _ = strconv.ParseInt(scdid, 10, 64)
- scdObj.Idseq = scdObj.Idseq - 1 //新生成 的SCD ID是在该变量基础上加1,为了保持原ID不变,所以先减1
- //log.Println(fmt.Sprintf("%v", rowset[0]))
- err := scdObj.XmlParse(tools.IsEmpty(row["station_id"]), tools.IsEmpty(row["path"]), tools.IsEmpty(row["scd_name"]), 0)
- if err != nil {
- log.Println(err)
- }
- if ischeckinscd == 1 {
- db.Raw("update t_scd_scl set version=?,enable=?,checkout_lock=? where id=?",
- tools.IsEmpty(row["version"]),
- tools.IsEmpty(row["enable"]),
- tools.IsEmpty(row["checkout_lock"]),
- scdid).Exec()
- }
- new(SystemLog).Success(enum.AuditType_scd_resetparse,
- enum.LogType_Execute,
- enum.OptEventType_System,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("对变电站[id=%s]scd文件%s重新进行了解析", tools.IsEmpty(row["station_id"]), tools.IsEmpty(row["scd_name"])),
- c.GetUserInfo(),
- )
- //SaveSyslog(, "SCD管理", true, tools.IsEmpty(c.UserInfo["name"]), tools.IsEmpty(c.UserInfo["ip"]))
- }(rowset[0])
- return nil
- }
- //删除指定scd的所有数据
- //isall:true 包含流转数据、签入时的其他上传文件等 false:只清除scd本身数据
- func (c *ScdMgr) DeleteScd(scdid string, isall ...bool) error {
- scdidInt64, _ := strconv.ParseInt(scdid, 10, 64)
- db := orm.NewOrm()
- sql := "select t.*,a.area_name station_name,s1.check_flag from t_scd_scl t left join t_data_area a on t.station_id=a.id left JOIN t_sys_attachment s1 on t.id=s1.scd_id and s1.file_suffix='scd' where t.id=? "
- rowset0 := []orm.Params{}
- db.Raw(sql, scdidInt64).Values(&rowset0)
- if len(rowset0) == 0 {
- new(SystemLog).Fail(enum.AuditType_scd_show,
- enum.LogType_Delete,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("SQL:%s,参数:%s", sql, scdid),
- c.GetUserInfo(),
- )
- return errors.New("无效的SCD编号")
- }
- //如果当前scd是签入的,需要解锁该scd所属变电站的签入锁定
- if tools.IsEmpty(rowset0[0]["check_flag"]) == "1" {
- checkinLockKey := fmt.Sprintf("%s%s", tools.IsEmpty(rowset0[0]["station_id"]), "scdin")
- global.CheckingInInfo.Delete(checkinLockKey)
- }
- scd_name := tools.IsEmpty(rowset0[0]["scd_name"])
- scd_path := tools.IsEmpty(rowset0[0]["path"])
- //获取scd属性表
- sql = "select table_name , table_comment from information_schema.tables where table_schema = (select database()) and table_name like 't_scd_%' "
- rowset := []orm.Params{}
- _, err := db.Raw(sql).Values(&rowset)
- if err != nil {
- logger.Logger.Error(err)
- new(SystemLog).Fail(enum.AuditType_scd_show,
- enum.LogType_Delete,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("SQL:%s", sql),
- c.GetUserInfo(),
- )
- return err
- }
- go new(ScdParse).RemoveScdCache(scdid)
- go mqtt.PublishMessage("/jujutong/scd_check_tools/delete/"+scdid, `{"state":0,"scd_name":"`+tools.IsEmpty(rowset0[0]["scd_name"])+`","user":"`+c.GetUserName()+`"}`)
- deleteAll := true
- if len(isall) > 0 {
- deleteAll = isall[0]
- }
- var wg = sync.WaitGroup{}
- if c.SyncDeleteMod {
- wg.Add(1)
- }
- go func() {
- if c.SyncDeleteMod {
- defer func() {
- wg.Done()
- }()
- }
- dirChar := string(os.PathSeparator)
- for _, row := range rowset {
- tb := tools.IsEmpty(row["TABLE_NAME"]) + tools.IsEmpty(row["table_name"])
- if tb == "t_scd_scl" {
- continue
- }
- for {
- sql = "delete from " + tb + " where scd_id=? limit 10000"
- r, _ := db.Raw(sql, scdidInt64).Exec()
- if r != nil {
- cnt, _ := r.RowsAffected()
- if cnt == 0 || cnt < 10000 {
- break
- }
- } else {
- break
- }
- }
- }
- db.Raw("delete from t_ied_relation where scd_id=?", scdidInt64).Exec()
- db.Raw("delete from t_ied_ctrl_relation where scd_id=?", scdidInt64).Exec()
- db.Raw("delete from t_area_ied_relation where area_id in(select id from t_substation_area where scd_id=?)", scdidInt64).Exec()
- db.Raw("delete from t_substation_area where scd_id=?", scdidInt64).Exec()
- db.Raw("delete from t_scd_diff_compare_detail where compare_id=(select id from t_scd_diff_compare where source_id=?)", scdidInt64).Exec()
- db.Raw("delete from t_scd_node_rule_parse where scd_id=?", scdidInt64).Exec()
- os.Remove(scd_path + ".parsed.xml")
- os.Remove(strings.Join([]string{".", "static", "upload", scdid + ".scd.crc"}, dirChar))
- os.Remove(strings.Join([]string{".", "static", "upload", scdid + ".schema_valid"}, dirChar))
- if deleteAll {
- db.Raw("delete from t_scd_diff_compare where source_id=? or target_id=?", scdidInt64, scdidInt64).Exec()
- db.Raw("delete from t_scd_scl where id=?", scdidInt64).Exec()
- os.Remove(scd_path)
- attachmentlist := []orm.Params{}
- //清除相关附件
- db.Raw("select save_path from t_sys_attachment where scd_id=?", scdidInt64).Values(&attachmentlist)
- for _, fr := range attachmentlist {
- savepath := tools.IsEmpty(fr["save_path"])
- if savepath != "" {
- savepath = "." + strings.ReplaceAll(savepath, "\\", dirChar)
- os.Remove(savepath)
- }
- }
- db.Raw("delete from t_sys_attachment where scd_id=?", scdidInt64).Exec()
- if len(scd_path) > 0 && scd_path[0:1] == "." {
- scd_path = scd_path[1:]
- }
- db.Raw("delete from t_sys_flow_run_detail where flow_run_id in(select t.id from t_sys_flow_run t where t.scd_name=? and t.scd_path=?)", scd_name, scd_path).Exec()
- db.Raw("delete from t_sys_flow_run where scd_name=? and scd_path=?", scd_name, scd_path).Exec()
- }
- db.Raw("delete from t_sys_attachment where check_flag=2 and scd_id=?", scdidInt64).Exec() //删除裁剪文件记录
- db.Raw("update t_sys_attachment set scd_id=0 where scd_id=?", scdidInt64).Exec()
- //删除该scd相关文件,包括每个装置配置ied、crc等文件
- tmpPart := []string{".", "static", "upload", "ied", scdid}
- iedpath := strings.Join(tmpPart, dirChar)
- os.RemoveAll(iedpath)
- new(SystemLog).Success(enum.AuditType_scd_show,
- enum.LogType_Delete,
- enum.OptEventType_Bus,
- enum.OptEventLevel_Hight,
- fmt.Sprintf("清除了变电站[id=%s]scd文件%s的所有数据", tools.IsEmpty(rowset0[0]["station_name"]), tools.IsEmpty(rowset0[0]["scd_name"])),
- c.GetUserInfo(),
- )
- go mqtt.PublishMessage("/jujutong/scd_check_tools/delete/"+scdid, `{"state":1,"station_name":"`+tools.IsEmpty(rowset0[0]["station_name"])+`","scd_name":"`+tools.IsEmpty(rowset0[0]["scd_name"])+`","user":"`+c.GetUserName()+`"}`)
- }()
- if c.SyncDeleteMod {
- wg.Wait()
- }
- //如果当前删除的是签入SCD,则需要把当前站最后签出记录的签出锁定状态更改为1,否则该站将无法再次签入了
- if deleteAll && tools.IsEmpty(rowset0[0]["is_checkin_scd"]) == "1" {
- station_id := tools.IsEmpty(rowset0[0]["station_id"])
- //判断该站有没有签出记录
- rowset0 = []orm.Params{}
- sql = "select id from t_scd_scl where station_id=? order by id desc limit 1"
- db.Raw(sql, station_id).Values(&rowset0)
- if len(rowset0) > 0 {
- db.Raw("update t_scd_scl set checkout_lock=1 where id=?", tools.IsEmpty(rowset0[0]["id"])).Exec()
- }
- }
- return nil
- }
- //获取指定scd中装置网络地址
- func (c *ScdMgr) GetIedNetAddr(scdid string) ([]orm.Params, error) {
- key := fmt.Sprintf("scd_netinfo_%d", scdid)
- if v, h := global.GoCahce.Get(key); h {
- return v.([]orm.Params), nil
- }
- scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
- if serr != nil {
- return nil, serr
- }
- if scdXmlObj == nil {
- return nil, errors.New("无效的SCD")
- }
- rowset := []orm.Params{}
- for _, item := range scdXmlObj.Communication.SubNetwork {
- for _, c1 := range item.ConnectedAP {
- if c1.Address != nil {
- for _, p1 := range c1.Address.P {
- if p1.Type == "IP" || p1.Type == "MAC-Address" {
- p1type := "ip"
- if p1.Type == "MAC-Address" {
- p1type = "mac"
- }
- rowobj := orm.Params{
- "id": p1.NodeId,
- "node_name": "P",
- "node_value": p1.InnerText,
- "parent_node_id": c1.NodeId,
- "addrtype": p1type,
- "attr_ied_name": c1.IedName,
- "attr_ap_name": c1.ApName,
- }
- rowset = append(rowset, rowobj)
- }
- }
- }
- }
- }
- global.GoCahce.Set(key, rowset, -1)
- return rowset, nil
- }
- //对scd进行crc校验
- func (c *ScdMgr) CrcCheck(scdid string) (bool, error) {
- crcFilePath := fmt.Sprintf(strings.Join([]string{".", "static", "upload", ""}, string(os.PathSeparator))+"%s.scd.crc", scdid)
- f, _ := os.Stat(crcFilePath)
- if f != nil {
- crcmap := map[string]string{}
- txt, _ := os.ReadFile(crcFilePath)
- err := json.Unmarshal(txt, &crcmap)
- if err == nil {
- global.CachedScdCrc.Store(fmt.Sprintf("crc_%s", scdid), crcmap)
- //crc提取完成
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "2")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 2)
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 2)
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 2)
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 2)
- return true, nil
- }
- }
- scdInfo, err := c.One(scdid)
- if err != nil {
- //crc提取失败
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "0")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 3, err.Error())
- return false, err
- }
- if scdInfo == nil {
- //crc提取失败
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "0")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 3, "无效的scd名称和路径")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 3, "无效的scd名称和路径")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 3, "无效的scd名称和路径")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 3, "无效的scd名称和路径")
- return false, errors.New("无效的scd名称和路径")
- }
- scdpath := scdInfo["path"].(string)
- scdname := scdInfo["scd_name"].(string)
- station_id := tools.IsEmpty(scdInfo["station_id"])
- data := map[string]string{"name": scdname, "stationid": station_id, "rootid": scdid, "state": "0", "node": "crc-file", "msg": ""}
- dataMsg, _ := json.Marshal(data)
- mqtt.PublishMessage(fmt.Sprintf("/jujutong/scd_check_tools/parse/%s/%s", station_id, scdid), string(dataMsg))
- //crc提取开始
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 1)
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "1")
- osname := string(runtime.GOOS)
- var subProcess *exec.Cmd
- if osname == "windows" {
- subProcess = exec.Command("cmd", "/c", "crclibtest.exe")
- } else {
- subProcess = exec.Command("bash", "-c", "./crctestdemo")
- }
- stdin, err := subProcess.StdinPipe()
- if err != nil {
- logger.Logger.Error(err)
- //crc提取失败
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "0")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 3, err.Error())
- return false, err
- }
- defer stdin.Close()
- stdout, _ := subProcess.StdoutPipe()
- //subProcess.Stdout = os.Stdout
- //subProcess.Stderr = os.Stderr
- logger.Logger.Debug("====正在提取IED校验码!")
- if err = subProcess.Start(); err != nil {
- logger.Logger.Error(err)
- //crc提取失败
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "0")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 3, err.Error())
- return false, err
- }
- txt := make([]byte, 1024)
- for {
- time.Sleep(100 * time.Millisecond)
- n, _ := stdout.Read(txt)
- str := string(txt[0:n])
- if strings.Index(str, "number(1-3)") > 1 {
- break
- }
- }
- _, err = stdin.Write([]byte("1\n"))
- if err != nil {
- logger.Logger.Error(err)
- //crc提取失败
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "0")
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 3, err.Error())
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 3, err.Error())
- return false, err
- }
- txt = make([]byte, 1024)
- for {
- time.Sleep(100 * time.Millisecond)
- n, _ := stdout.Read(txt)
- if n == 0 {
- break
- }
- str := string(txt[0:n])
- if strings.Index(str, "SCD file") > -1 {
- break
- }
- }
- stdin.Write([]byte(scdpath + "\n"))
- //io.WriteString(stdin, scdpath+"\n") //输入scd路径
- outContent := ""
- for {
- time.Sleep(1 * time.Second)
- n, _ := stdout.Read(txt)
- str := tools.ConvertByte2String(txt[0:n], "GB18030")
- outContent = outContent + str
- if strings.Index(str, "The CRC of SCD is") > -1 {
- break
- }
- }
- stdin.Write([]byte("\n"))
- stdin.Close()
- logger.Logger.Debug("====IED校验码提取完成!")
- crclist := strings.Split(outContent, "\n")
- logger.Logger.Debug(fmt.Sprintf("%+v", crclist))
- crcmap := map[string]string{}
- for _, crc := range crclist {
- if crc == "" {
- continue
- }
- if crc[0:6] == "Please" {
- continue
- }
- if strings.Index(crc, "The CRC of SCD is") > -1 {
- crcmap["scdcrc"] = strings.Trim(strings.Split(crc, ":")[1], "\r") //根据所有IED生成的scd校验码
- continue
- }
- v_crc := strings.Split(crc, ":")
- if len(v_crc) > 1 {
- if len(v_crc[0]) > 2 && v_crc[0][0:3] == "SCD" {
- continue
- }
- crcmap[v_crc[0]] = strings.Trim(v_crc[1], "\r")
- }
- }
- global.CachedScdCrc.Store(fmt.Sprintf("crc_%s", scdid), crcmap)
- //crc提取完成
- global.IedCrcMakeState.Store(fmt.Sprintf("crc_%s", scdid), "2")
- crcdata, _ := json.Marshal(crcmap)
- err = os.WriteFile(crcFilePath, crcdata, fs.ModePerm)
- if err != nil {
- logger.Logger.Error(err)
- }
- data = map[string]string{"name": scdname, "stationid": station_id, "rootid": scdid, "state": "1", "node": "crc-file", "msg": ""}
- dataMsg, _ = json.Marshal(data)
- mqtt.PublishMessage(fmt.Sprintf("/jujutong/scd_check_tools/parse/%s/%s", station_id, scdid), string(dataMsg))
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_crc_extract.Code(), 2)
- dirChar := string(os.PathSeparator)
- tmpPart := []string{".", "static", "upload", "ied", scdid}
- ccdpath := strings.Join(tmpPart, dirChar)
- os.MkdirAll(ccdpath, fs.ModePerm)
- go func(scdid, scdname, station_id, scdpath, ccdpath string) {
- //提取CCD文件
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 1)
- logger.Logger.Debug("====开始提取IED装置CCD文件...")
- ccdFileSqls := []string{}
- for iedname, _ := range crcmap {
- if iedname == "scdcrc" {
- continue
- }
- var subProcess *exec.Cmd
- logger.Logger.Debug("====正在提取IED装置" + iedname + "的CCD文件到" + ccdpath)
- if osname == "windows" {
- subProcess = exec.Command("cmd", "/c", "crclibtest.exe")
- } else {
- subProcess = exec.Command("bash", "-c", "./crctestdemo")
- }
- stdin, err := subProcess.StdinPipe()
- if err != nil {
- logger.Logger.Error(err)
- continue
- }
- stdout, _ := subProcess.StdoutPipe()
- if err = subProcess.Start(); err != nil {
- logger.Logger.Error(err)
- stdin.Close()
- continue
- }
- txt := make([]byte, 1024)
- for {
- time.Sleep(10 * time.Millisecond)
- n, _ := stdout.Read(txt)
- str := string(txt[0:n])
- if n > 0 {
- logger.Logger.Debug(str)
- }
- if strings.Index(str, "number(1-3)") > 1 {
- break
- }
- }
- _, err = stdin.Write([]byte("3\n"))
- if err != nil {
- logger.Logger.Error(err)
- stdin.Close()
- continue
- }
- txt = make([]byte, 1024)
- for {
- time.Sleep(10 * time.Millisecond)
- n, _ := stdout.Read(txt)
- str := string(txt[0:n])
- if n > 0 {
- logger.Logger.Debug(str)
- }
- if strings.Index(str, "SCD file") > 0 {
- break
- }
- }
- _, err = stdin.Write([]byte(scdpath + "\n"))
- if err != nil {
- logger.Logger.Error(err)
- stdin.Close()
- continue
- }
- txt = make([]byte, 1024)
- for {
- time.Sleep(10 * time.Millisecond)
- n, _ := stdout.Read(txt)
- str := string(txt[0:n])
- if n > 0 {
- logger.Logger.Debug(str)
- }
- if strings.Index(str, "IED:") > 0 {
- break
- }
- }
- _, err = stdin.Write([]byte(iedname + "\n"))
- if err != nil {
- logger.Logger.Error(err)
- stdin.Close()
- continue
- }
- txt = make([]byte, 1024)
- for {
- time.Sleep(10 * time.Millisecond)
- n, _ := stdout.Read(txt)
- str := string(txt[0:n])
- if n > 0 {
- logger.Logger.Debug(str)
- }
- if strings.Index(str, "directory:") > 0 {
- break
- }
- }
- _, err = stdin.Write([]byte(ccdpath + "\n"))
- if err != nil {
- logger.Logger.Error(err)
- stdin.Close()
- continue
- }
- txt = make([]byte, 1024)
- for i := 0; i < 10; i++ {
- time.Sleep(10 * time.Millisecond)
- n, _ := stdout.Read(txt)
- if n > 0 {
- logger.Logger.Debug(string(txt[0:n]))
- break
- }
- }
- stdin.Write([]byte(" \n"))
- logger.Logger.Debug("====IED装置" + iedname + "的CCD文件提取完成!")
- stdin.Close()
- tmpF, e := os.Stat(ccdpath + dirChar + iedname + ".ccd")
- if e != nil {
- logger.Logger.Error(e)
- } else {
- ccdFileType, _ := global.GoCahce.Get("global_code_file_typesfile_ccd") //ccd文件类型的字典id
- //(station_id,scd_id,ied_name,file_name,file_size,save_path,file_type,file_suffix,check_flag)
- ccdFileSqls = append(ccdFileSqls, fmt.Sprintf("(%s,%s,'%s','%s','%s','%s','%s','%s',%d,now())",
- station_id, scdid, iedname, iedname+".ccd",
- tools.FormatFileSize(tmpF.Size()),
- strings.ReplaceAll(ccdpath+dirChar+iedname+".ccd", "\\", "/")[1:],
- tools.IsEmpty(ccdFileType.(orm.Params)["id"]), "ccd", 2))
- }
- }
- if len(ccdFileSqls) > 0 {
- odb := orm.NewOrm()
- odb.Raw("insert into t_sys_attachment(station_id,scd_id,ied_name,file_name,file_size,save_path,file_type,file_suffix,check_flag,created_time)values" + strings.Join(ccdFileSqls, ",")).Exec()
- ccdFileSqls = nil
- }
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_ccd_extract.Code(), 2)
- logger.Logger.Debug("====IED装置CCD文件提取完成!")
- data := map[string]string{"name": scdname, "stationid": station_id, "rootid": scdid, "state": "1", "node": "ccd-file", "msg": ""}
- dataMsg, _ := json.Marshal(data)
- mqtt.PublishMessage(fmt.Sprintf("/jujutong/scd_check_tools/parse/%s/%s", station_id, scdid), string(dataMsg))
- }(scdid, scdname, station_id, scdpath, ccdpath)
- //icd,cid提取
- go func(scdid, savepath string) {
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 1)
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 1)
- logger.Logger.Debug("====开始提取SCD【" + scdid + "】的IED装置ICD、CID文件...")
- scdXmlObj, serr := new(ScdParse).GetScdXmlObjectBySCDID(scdid)
- if serr != nil {
- logger.Logger.Error(serr)
- return
- }
- if scdXmlObj == nil {
- return
- }
- lnodetypes := c.GetLNodeType(scdXmlObj)
- dotypes := c.GetDOType(scdXmlObj)
- dirChar := string(os.PathSeparator)
- xxxFileSqls := []string{}
- icdFileType, _ := global.GoCahce.Get("global_code_file_typesfile_icd") //icd文件类型的字典id
- cidFileType, _ := global.GoCahce.Get("global_code_file_typesfile_cid") //cid文件类型的字典id
- for iedname, _ := range crcmap {
- if iedname == "scdcrc" {
- continue
- }
- iedObj := new(ScdNode).GetIed(scdXmlObj, scdid, iedname)
- if iedObj == nil {
- logger.Logger.Error(errors.New(fmt.Sprintf("scd【%s】中未发现装置%s", scdid, iedname)))
- continue
- }
- xmllines := []string{`<?xml version="1.0" encoding="UTF-8"?>` + "\r\n"}
- xmllines = append(xmllines, `<SCL xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">`+"\r\n")
- //icd提取
- xmlbytes, err := xml.MarshalIndent(iedObj, "", " ")
- if err == nil {
- xmlStr := string(xmlbytes)
- pattern := `( lineno="\d{1,}" nodeid="\d{1,}")|(
)|( ix="")|(<ext:eOption.*?>.*?</ext:eOption>)` //替换其中的lineno和nodeid属性
- reg := regexp.MustCompile(pattern)
- xmlStr = reg.ReplaceAllString(xmlStr, "")
- xmlStr = "<IED" + xmlStr[5:]
- xmlStr = xmlStr[0:len(xmlStr)-7] + "</IED>\r\n"
- xmlStr = xmlStr + "<DataTypeTemplates>\r\n"
- //提取LNodeType
- isSub := map[string]bool{}
- for _, apt := range iedObj.AccessPoint {
- if apt.Server == nil {
- continue
- }
- for _, ld := range apt.Server.LDevice {
- lnnode := lnodetypes[ld.LN0.LnType]
- if lnnode != nil && isSub[ld.LN0.LnType] == false {
- xmlbytes, _ = xml.MarshalIndent(lnnode, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-13] + "</LNodeType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[ld.LN0.LnType] = true
- for _, do := range lnnode.DO {
- if isSub[do.Type] == false {
- dotype := dotypes[do.Type]
- xmlbytes, _ = xml.MarshalIndent(dotype, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-10] + "</DOType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[do.Type] = true
- }
- }
- }
- for _, ln := range ld.LN {
- lnnode = lnodetypes[ln.LnType]
- if lnnode != nil && isSub[ln.LnType] == false {
- xmlbytes, _ = xml.MarshalIndent(lnnode, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-13] + "</LNodeType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[ln.LnType] = true
- for _, do := range lnnode.DO {
- if isSub[do.Type] == false {
- dotype := dotypes[do.Type]
- xmlbytes, _ = xml.MarshalIndent(dotype, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-10] + "</DOType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[do.Type] = true
- }
- }
- }
- }
- }
- }
- xmlStr = xmlStr + "</DataTypeTemplates>\r\n</SCL>"
- //生成解析完成结果副本文件
- os.WriteFile(savepath+dirChar+iedname+".icd", []byte(strings.Join(xmllines, "")+xmlStr), fs.ModePerm)
- tmpF, e := os.Stat(savepath + dirChar + iedname + ".icd")
- if e != nil {
- logger.Logger.Error(e)
- } else {
- xxxFileSqls = append(xxxFileSqls, fmt.Sprintf("(%s,%s,'%s','%s','%s','%s','%s','%s',%d,now())",
- station_id, scdid, iedname, iedname+".icd",
- tools.FormatFileSize(tmpF.Size()),
- strings.ReplaceAll(savepath+dirChar+iedname+".icd", "\\", "/")[1:],
- tools.IsEmpty(icdFileType.(orm.Params)["id"]), "icd", 2))
- }
- xmlStr = ""
- } else {
- logger.Logger.Error(err)
- }
- //cid提取
- xmlbytes, err = xml.MarshalIndent(iedObj, "", " ")
- if err == nil {
- //生成解析完成结果副本文件
- xmlStr := string(xmlbytes)
- pattern := `( lineno="\d{1,}" nodeid="\d{1,}")|(
)|( ix="")|(<ext:eOption.*?>.*?</ext:eOption>)` //替换其中的lineno和nodeid属性
- reg := regexp.MustCompile(pattern)
- //提取通讯参数
- commXml := "<Communication>\r\n"
- subnetworkXml := []string{}
- for _, comm := range scdXmlObj.Communication.SubNetwork {
- apXml := []string{}
- for _, ap := range comm.ConnectedAP {
- if ap.IedName == iedname {
- apxmlbytes, _ := xml.MarshalIndent(ap, "", " ")
- lnnodeXmlStr := string(apxmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-15] + "</ConnectedAP>\r\n"
- apXml = append(apXml, lnnodeXmlStr)
- }
- }
- if len(apXml) > 0 {
- subnetworkXml = append(subnetworkXml, fmt.Sprintf("<SubNetwork name=\"%s\" type=\"%s\">\r\n", comm.Name, comm.Type))
- if comm.BitRate != nil {
- subnetworkXml = append(subnetworkXml, fmt.Sprintf("<BitRate unit=\"%s\" multiplier=\"%s\">%s</BitRate>\r\n", comm.BitRate.Unit, comm.BitRate.Multiplier, comm.BitRate.InnerText))
- }
- subnetworkXml = append(subnetworkXml, reg.ReplaceAllString(strings.Join(apXml, ""), "")+"\r\n")
- subnetworkXml = append(subnetworkXml, "</SubNetwork>\r\n")
- }
- }
- if len(subnetworkXml) > 0 {
- commXml += strings.Join(subnetworkXml, "")
- commXml += "</Communication>\r\n"
- } else {
- commXml = ""
- }
- xmlStr = reg.ReplaceAllString(xmlStr, "")
- xmlStr = reg.ReplaceAllString(xmlStr, "")
- xmlStr = commXml + "<IED" + xmlStr[5:]
- xmlStr = xmlStr[0:len(xmlStr)-7] + "</IED>\r\n"
- xmlStr = xmlStr + "<DataTypeTemplates>\r\n"
- //提取LNodeType
- isSub := map[string]bool{}
- for _, apt := range iedObj.AccessPoint {
- if apt.Server == nil {
- continue
- }
- for _, ld := range apt.Server.LDevice {
- lnnode := lnodetypes[ld.LN0.LnType]
- if lnnode != nil && isSub[ld.LN0.LnType] == false {
- xmlbytes, _ = xml.MarshalIndent(lnnode, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-13] + "</LNodeType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[ld.LN0.LnType] = true
- for _, do := range lnnode.DO {
- if isSub[do.Type] == false {
- dotype := dotypes[do.Type]
- xmlbytes, _ = xml.MarshalIndent(dotype, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-10] + "</DOType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[do.Type] = true
- }
- }
- }
- for _, ln := range ld.LN {
- lnnode = lnodetypes[ln.LnType]
- if lnnode != nil && isSub[ln.LnType] == false {
- xmlbytes, _ = xml.MarshalIndent(lnnode, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-13] + "</LNodeType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[ln.LnType] = true
- for _, do := range lnnode.DO {
- if isSub[do.Type] == false {
- dotype := dotypes[do.Type]
- xmlbytes, _ = xml.MarshalIndent(dotype, "", " ")
- lnnodeXmlStr := string(xmlbytes)
- lnnodeXmlStr = "<" + lnnodeXmlStr[2:]
- lnnodeXmlStr = lnnodeXmlStr[0:len(lnnodeXmlStr)-10] + "</DOType>\r\n"
- xmlStr += reg.ReplaceAllString(lnnodeXmlStr, "")
- isSub[do.Type] = true
- }
- }
- }
- }
- }
- }
- xmlStr = xmlStr + "</DataTypeTemplates>\r\n</SCL>"
- os.WriteFile(savepath+dirChar+iedname+".cid", []byte(strings.Join(xmllines, "")+xmlStr), fs.ModePerm)
- tmpF, e := os.Stat(savepath + dirChar + iedname + ".cid")
- if e != nil {
- logger.Logger.Error(e)
- } else {
- xxxFileSqls = append(xxxFileSqls, fmt.Sprintf("(%s,%s,'%s','%s','%s','%s','%s','%s',%d,now())",
- station_id, scdid, iedname, iedname+".cid",
- tools.FormatFileSize(tmpF.Size()),
- strings.ReplaceAll(savepath+dirChar+iedname+".cid", "\\", "/")[1:],
- tools.IsEmpty(cidFileType.(orm.Params)["id"]), "cid", 2))
- }
- xmlStr = ""
- } else {
- logger.Logger.Error(err)
- continue
- }
- }
- if len(xxxFileSqls) > 0 {
- odb := orm.NewOrm()
- odb.Raw("insert into t_sys_attachment(station_id,scd_id,ied_name,file_name,file_size,save_path,file_type,file_suffix,check_flag,created_time)values" + strings.Join(xxxFileSqls, ",")).Exec()
- xxxFileSqls = nil
- }
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_cid_extract.Code(), 2)
- new(TaskMgr).SetStep(scdid, enum.TaskStep_SCD_icd_extract.Code(), 2)
- data := map[string]string{"name": scdname, "stationid": station_id, "rootid": scdid, "state": "1", "node": "cid-file", "msg": ""}
- dataMsg, _ := json.Marshal(data)
- mqtt.PublishMessage(fmt.Sprintf("/jujutong/scd_check_tools/parse/%s/%s", station_id, scdid), string(dataMsg))
- }(scdid, ccdpath)
- return true, nil
- }
- var YaoCeMap = map[string]string{
- "MV": "测量值",
- "CMV": "复数测量值",
- "SAV": "呆样值",
- "WYE": "三相项系统中相对地相关测量值",
- "DEL": "三相项系统中相对相相关测量值",
- "SEQ": "顺序值",
- "INC": "可控整数状态",
- "BSC": "二进制受控步位置信息",
- "ISC": "整数受控步位置信息",
- "APC": "可控模拟过程信息",
- "ENC": "可控枚举状态",
- "HMV": "谐波值",
- "HWYE": "WYE谐波值",
- "HDEL": "DEL谐波值",
- "BAC": "可控的二进制模拟过程值",
- "ING": "整数状态定值",
- }
- var YaoXinMap = map[string]string{
- "SPS": "单点状态信息",
- "DPS": "双点状态信息",
- "ACT": "保护激活信息",
- "ACD": "方向保护激活信息",
- "SPC": "可控的单点",
- "DPC": "可控的双点",
- "ENS": "枚举状态",
- "VSS": "可见字符串状态",
- "HST": "直方图",
- "LPL": "逻辑节点铭牌",
- "DPL": "设备铭牌",
- "SEC": "安全违例计数",
- }
- //双点遥信类型
- var YaoXinDBType = map[string]bool{
- "DPS": true,
- "DPC": true,
- }
- //单点遥信类型
- var YaoXinSiType = map[string]bool{
- "SPS": true,
- "SPC": true,
- }
- var YaoKongMap = map[string]string{
- "SPC": "可控的单点",
- "DPC": "可控的双点",
- "INC": "可控的整数状态",
- "BSC": "二进制受控步位置信息",
- "ISC": "整数受控步位置信息",
- "APC": "可控模拟过程信息",
- "ENC": "可控枚举状态",
- "BAC": "可控的二进制模拟过程值",
- }
- var DingZhiMap = map[string]string{
- "SPG": "单点定值",
- "ING": "整数状态定值",
- "ASG": "模拟定值",
- "STG": "STG",
- "ENG": "枚举状态定值",
- "ORG": "对象引用定值",
- "TSG": "时间定值组",
- "CSG": "曲线形状定值",
- "CUG": "可见字符串定值",
- "VSG": "VSG",
- "CURVE": "定值曲线",
- }
- var OtherCdcTypeMap = map[string]string{
- "INS": "整数状态",
- "BCR": "二进制计数器读数",
- "CSD": "曲线形状描述",
- }
- //根据cdc返回对应的数据类型名称
- func (c *ScdMgr) GetCdcDataTypeName(cdccode string) string {
- name := DingZhiMap[cdccode]
- if name == "" {
- name = YaoKongMap[cdccode]
- }
- if name == "" {
- name = YaoXinMap[cdccode]
- }
- if name == "" {
- name = YaoCeMap[cdccode]
- }
- if name == "" {
- name = OtherCdcTypeMap[cdccode]
- }
- return name
- }
- //获取指定scd的数据模板LNodeType集合
- func (c *ScdMgr) GetLNodeType(scdXmlObj *node_attr.SCL) map[string]*node_attr.NLNodeType {
- key := fmt.Sprintf("%d%s", scdXmlObj.NodeId, "lnodetype")
- if v, h := global.GoCahce.Get(key); h {
- return v.(map[string]*node_attr.NLNodeType)
- }
- mapSourceLNodeType := map[string]*node_attr.NLNodeType{}
- for _, lnnodetpye := range scdXmlObj.DataTypeTemplates.LNodeType {
- mapSourceLNodeType[lnnodetpye.Id] = lnnodetpye
- }
- global.GoCahce.Set(key, mapSourceLNodeType, 30*time.Minute)
- return mapSourceLNodeType
- }
- //获取指定scd的数据模板DOType集合
- func (c *ScdMgr) GetDOType(scdXmlObj *node_attr.SCL) map[string]*node_attr.NDOType {
- key := fmt.Sprintf("%d%s", scdXmlObj.NodeId, "dotype")
- if v, h := global.GoCahce.Get(key); h {
- return v.(map[string]*node_attr.NDOType)
- }
- mapSourceDOType := map[string]*node_attr.NDOType{}
- for _, lnnodetpye := range scdXmlObj.DataTypeTemplates.DOType {
- mapSourceDOType[lnnodetpye.Id] = lnnodetpye
- }
- global.GoCahce.Set(key, mapSourceDOType, 30*time.Minute)
- return mapSourceDOType
- }
- //获取遥控DOType集合
- //遥控测点规则:模型模板中,DOType包含cdc为"SPC", "DPC", "INC", "BSC", "ISC", "APC",”ENC”,”BAC”,同时DOType的DA子节点中含有name为Oper元素
- func (c *ScdMgr) GetYaoKongDoTypeMap(scdXmlObj *node_attr.SCL) map[string]*node_attr.NDOType {
- result := map[string]*node_attr.NDOType{}
- for _, lnnodetpye := range scdXmlObj.DataTypeTemplates.DOType {
- if _, h := YaoKongMap[lnnodetpye.Cdc]; h {
- for _, da := range lnnodetpye.DA {
- if da.Name == "Oper" {
- result[lnnodetpye.Id] = lnnodetpye
- break
- }
- }
- }
- }
- return result
- }
- //获取指定IED下的遥控测点DOI实例
- func (c *ScdMgr) GetYaoKongDOIMap(scdXmlObj *node_attr.SCL, iedname string) map[string]*node_attr.NDOI {
- result := map[string]*node_attr.NDOI{}
- yaokongDOType := c.GetYaoKongDoTypeMap(scdXmlObj)
- if len(yaokongDOType) == 0 {
- //集合为空,则全文遥控数据为空
- return nil
- }
- key := fmt.Sprintf("%d%s%s", scdXmlObj.NodeId, iedname, "yaoking")
- if v, h := global.GoCahce.Get(key); h {
- return v.(map[string]*node_attr.NDOI)
- }
- lnnodetype := c.GetLNodeType(scdXmlObj)
- daiTxtKey := map[string]bool{
- "1": true,
- "2": true,
- "3": true,
- "4": true,
- "direct-with-normal-security": true,
- "sbo-with-normal-security": true,
- "direct-with-enhanced-security": true,
- "sbo-with-enhanced-security": true,
- }
- iedObj := new(ScdNode).GetIed(scdXmlObj, "", iedname)
- var getdoicdc = func(lntype, doiname string) string {
- doNames := lnnodetype[lntype]
- if doNames == nil {
- return ""
- }
- for _, do := range doNames.DO {
- if do.Name == doiname && yaokongDOType[do.Type] != nil {
- return yaokongDOType[do.Type].Cdc
- }
- }
- return ""
- }
- //遍历模型实例化中,所有步骤1集合中的DOI实例
- for _, ap := range iedObj.AccessPoint {
- if ap.Server == nil {
- continue
- }
- for _, ld := range ap.Server.LDevice {
- if ld.LN0 != nil {
- for _, doi := range ld.LN0.DOI {
- //获取doi的cdc
- cdc := getdoicdc(ld.LN0.LnType, doi.Name)
- if cdc == "" {
- continue
- }
- key := fmt.Sprintf("%s.%s.%s", ld.Inst, ld.LN0.Inst, doi.Name)
- //检查DOI下是否含有name为ctlModel的DAI,若不含DAI,则默认为遥控,
- //若含有DAI,则判断ctlModel的txt值,当text值为1、2、3、4或”direct-with-normal-security”、“sbo-with-normal-security”、“direct-with-enhanced-security”、“sbo-with-enhanced-security”时,认为该点为遥控
- hasctlModel := false
- for _, dai := range doi.DAI {
- if dai.Name == "ctlModel" {
- hasctlModel = true
- if dai.Val != nil {
- txt := dai.Val.InnerText
- if _, h := daiTxtKey[txt]; h {
- result[key] = doi
- }
- }
- break
- }
- }
- if !hasctlModel {
- result[key] = doi
- }
- }
- }
- for _, ln := range ld.LN {
- for _, doi := range ln.DOI {
- //获取doi的cdc
- cdc := getdoicdc(ld.LN0.LnType, doi.Name)
- if cdc == "" {
- continue
- }
- key := fmt.Sprintf("%s.%s.%s", ld.Inst, ln.Inst, doi.Name)
- hasctlModel := false
- for _, dai := range doi.DAI {
- if dai.Name == "ctlModel" {
- hasctlModel = true
- if dai.Val != nil {
- txt := dai.Val.InnerText
- if _, h := daiTxtKey[txt]; h {
- result[key] = doi
- }
- }
- break
- }
- }
- if !hasctlModel {
- result[key] = doi
- }
- }
- }
- }
- }
- global.GoCahce.Set(key, result, 31*time.Minute)
- return result
- }
- //获取指定IED下的定值测点DOI实例
- func (c *ScdMgr) GetDingZhiDOIMap(scdXmlObj *node_attr.SCL, iedname string) map[string]*node_attr.NDOI {
- result := map[string]*node_attr.NDOI{}
- dingzhiDOType := c.GetDingZhiDoTypeMap(scdXmlObj)
- if len(dingzhiDOType) == 0 {
- //集合为空,则全文定值数据为空
- return nil
- }
- key := fmt.Sprintf("%d%s%s", scdXmlObj.NodeId, iedname, "dingzhi")
- if v, h := global.GoCahce.Get(key); h {
- return v.(map[string]*node_attr.NDOI)
- }
- lnnodetype := c.GetLNodeType(scdXmlObj)
- iedObj := new(ScdNode).GetIed(scdXmlObj, "", iedname)
- ldList := map[string]*node_attr.NLDevice{}
- for _, ap := range iedObj.AccessPoint {
- if ap.Server == nil {
- continue
- }
- for _, ld := range ap.Server.LDevice {
- ldList[ld.Inst] = ld
- }
- }
- var foundFcdaDingZhi = func(dst *node_attr.NDataSet) map[string]*node_attr.NDOI {
- result := map[string]*node_attr.NDOI{}
- for _, fcda := range dst.FCDA {
- if fcda.Fc == "SP" || fcda.Fc == "SG" || fcda.Fc == "SE" {
- ld := ldList[fcda.LdInst]
- if fcda.LnClass == "LLN0" && ld.LN0.LnClass == fcda.LnClass {
- lnodetype := lnnodetype[ld.LN0.LnType]
- if lnodetype == nil {
- continue
- }
- for _, doi := range ld.LN0.DOI {
- if doi.Name == fcda.DoName {
- for _, do := range lnodetype.DO {
- if do.Name == doi.Name && dingzhiDOType[do.Type] != nil {
- key := fmt.Sprintf("%s/%s%s%s.%s/%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName, fcda.Fc)
- result[key] = doi
- break
- }
- }
- break
- }
- }
- } else {
- for _, ln := range ld.LN {
- lnodetype := lnnodetype[ln.LnType]
- if lnodetype == nil {
- continue
- }
- if ln.LnClass == fcda.LnClass && ln.Inst == fcda.LnInst {
- for _, doi := range ln.DOI {
- if doi.Name == fcda.DoName {
- for _, do := range lnodetype.DO {
- if do.Name == doi.Name && dingzhiDOType[do.Type] != nil {
- key := fmt.Sprintf("%s/%s%s%s.%s/%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName, fcda.Fc)
- result[key] = doi
- break
- }
- }
- break
- }
- }
- break
- }
- }
- }
- }
- }
- return result
- }
- //遍历模型实例化中,所有步骤1集合中的DOI实例
- for _, ld := range ldList {
- if ld.LN0 != nil && ld.LN0.SettingControl != nil {
- for _, dst := range ld.LN0.DataSet {
- dingzhi := foundFcdaDingZhi(dst)
- for k, v := range dingzhi {
- result[k] = v
- }
- }
- }
- for _, ln := range ld.LN {
- if ln.SettingControl == nil {
- continue
- }
- for _, dst := range ln.DataSet {
- dingzhi := foundFcdaDingZhi(dst)
- for k, v := range dingzhi {
- result[k] = v
- }
- }
- }
- }
- global.GoCahce.Set(key, result, 31*time.Minute)
- return result
- }
- //获取指定IED下的遥测、遥信、遥脉测点
- func (c *ScdMgr) GetYcYkYmMap(scdXmlObj *node_attr.SCL, iedname string) (yc map[string]interface{}, yx map[string]interface{}, ym map[string]interface{}) {
- key := fmt.Sprintf("%d%s%s", scdXmlObj.NodeId, iedname, "YcYkYm")
- if v, h := global.GoCahce.Get(key); h {
- v1 := v.([]interface{})
- return v1[0].(map[string]interface{}), v1[1].(map[string]interface{}), v1[2].(map[string]interface{})
- }
- targetIedObj := new(ScdNode).GetIed(scdXmlObj, "", iedname)
- //IED内的遥信
- targetYaoXin := map[string]interface{}{}
- //IED内的遥测
- targetYaoCe := map[string]interface{}{}
- //IED内的遥脉
- targetYaoMai := map[string]interface{}{}
- mapTargetLNodeType := c.GetLNodeType(scdXmlObj)
- mapTargetLDoType := c.GetDOType(scdXmlObj)
- for _, ap := range targetIedObj.AccessPoint {
- if ap.Server == nil {
- continue
- }
- for _, ld := range ap.Server.LDevice {
- if ld.LN0 == nil {
- break
- }
- for _, rpb := range ld.LN0.ReportControl {
- if rpb.DatSet != "dsLog" {
- //处理遥信、遥测、遥脉数据
- for _, dst := range ld.LN0.DataSet {
- if dst.Name == rpb.DatSet {
- for _, fcda := range dst.FCDA {
- if fcda.Fc == "" {
- //数据集成员的fc为空或为"",跳过
- continue
- }
- key := fmt.Sprintf("%s/%s%s%s.%s.%s", fcda.LdInst, fcda.Prefix, fcda.LnClass, fcda.LnInst, fcda.DoName, fcda.DaName)
- //根据FCDA的prefix、lnClass、lnInst在DataSet所属的LDevice的LN0、LN中找到对应的节点,取到节点的lnType
- lnType := ""
- if ld.LN0.Prefix == fcda.Prefix && ld.LN0.LnClass == fcda.LnClass && ld.LN0.Inst == fcda.LnInst {
- lnType = ld.LN0.LnType
- } else {
- for _, lnitem := range ld.LN {
- if lnitem.Prefix == fcda.Prefix && lnitem.LnClass == fcda.LnClass && lnitem.Inst == fcda.LnInst {
- lnType = lnitem.LnType
- break
- }
- }
- }
- if lnType != "" {
- if lnnodetpye, h := mapTargetLNodeType[lnType]; h {
- for _, doitem := range lnnodetpye.DO {
- if doitem.Name == fcda.DoName {
- dotype := doitem.Type
- if dotypeobj, h := mapTargetLDoType[dotype]; h {
- cdctype := new(ScdMgr).GetDoTypePointType(dotypeobj, fcda)
- switch cdctype {
- case "YC":
- targetYaoCe[key] = fcda
- break
- case "YX":
- targetYaoXin[key] = fcda
- break
- case "YM":
- targetYaoMai[key] = fcda
- break
- }
- }
- break
- }
- }
- }
- }
- }
- break
- }
- }
- }
- }
- }
- }
- global.GoCahce.Set(key, []interface{}{targetYaoCe, targetYaoXin, targetYaoMai}, 30*time.Minute)
- return targetYaoCe, targetYaoXin, targetYaoMai
- }
- //获取指定IED下遥信接收端子
- //return: map对象。key为端子对象地址,value为字符串数组,固定2个元素。第一个元素为端子描述,第二个元素为端子的cdc类型码
- func (c *ScdMgr) GetYxExtref(scdXmlObj *node_attr.SCL, scdid int64, iedname string) map[*node_attr.NExtRef][]string {
- result := map[*node_attr.NExtRef][]string{}
- targetIedObj := new(ScdNode).GetIed(scdXmlObj, "", iedname)
- mapTargetLNodeType := c.GetLNodeType(scdXmlObj)
- mapTargetLDoType := c.GetDOType(scdXmlObj)
- tmpdata, _ := GlobalNodeMap.Load(scdid)
- nodeCacheMap := tmpdata.(map[int64]NodeCacheMap)
- scdNode := new(ScdNodeRule)
- scdNode.scdXmlObject = scdXmlObj
- for _, ap := range targetIedObj.AccessPoint {
- if ap.Server == nil {
- continue
- }
- for _, ld := range ap.Server.LDevice {
- if ld.LN0 != nil && ld.LN0.Inputs != nil {
- for _, extref := range ld.LN0.Inputs.ExtRef {
- doi := scdNode.IedIntAddrExist(iedname, extref.IntAddr)
- if doi == nil {
- continue
- }
- doiObj := doi.(*node_attr.NDOI)
- lnnode := nodeCacheMap[nodeCacheMap[doiObj.NodeId].ParentNodeId]
- lnType := lnnode.ObjAddr.(*node_attr.NLN).LnType
- if lnType != "" {
- if lnnodetpye, h := mapTargetLNodeType[lnType]; h {
- for _, doitem := range lnnodetpye.DO {
- if doitem.Name == doiObj.Name {
- dotype := doitem.Type
- if dotypeobj, h := mapTargetLDoType[dotype]; h {
- cdctype := new(ScdMgr).GetDoTypePointType(dotypeobj, nil)
- if cdctype == "YX" {
- result[extref] = []string{doiObj.Desc, dotypeobj.Cdc}
- }
- }
- break
- }
- }
- }
- }
- }
- break
- }
- }
- }
- return result
- }
- //获取定值DOType集合
- //规则:模型模板中,DOType包含cdc为"SPG", "ING", "ASG", "STG", "ENG", "ORG",”TSG”,”CSG”,”CUG”,”VSG”,”CURVE”
- //同时DOType的DA子节点中含有name为setVal或setMag元素的DOType
- func (c *ScdMgr) GetDingZhiDoTypeMap(scdXmlObj *node_attr.SCL) map[string]*node_attr.NDOType {
- result := map[string]*node_attr.NDOType{}
- for _, lnnodetpye := range scdXmlObj.DataTypeTemplates.DOType {
- if _, h := DingZhiMap[lnnodetpye.Cdc]; h {
- for _, da := range lnnodetpye.DA {
- if da.Name == "setVal" || da.Name == "setMag" {
- result[lnnodetpye.Id] = lnnodetpye
- break
- }
- }
- }
- }
- return result
- }
- //判断cdc对应的测点数据类型。YX:遥信、YC:遥测、YM:遥脉、YK:遥控、DZ:定值
- func (c *ScdMgr) GetDoTypePointType(dotype *node_attr.NDOType, fcda *node_attr.NFCDA) string {
- if dotype == nil {
- return ""
- }
- if _, h := YaoCeMap[dotype.Cdc]; h {
- return "YC"
- }
- if _, h := YaoXinMap[dotype.Cdc]; h {
- return "YX"
- }
- if dotype.Cdc == "INS" && fcda != nil {
- //判断DOType下DA中的name等于FCDA的daName的元素的bType值,如果bType值小写后为enum,分两种情况:
- //1. DOType下DA中含有type,并且type值为fltloop,类型为遥测
- //2. 不满足1为遥信;
- //3. 如果bType值小写后不为enum,类型为遥测
- for _, daitem := range dotype.DA {
- if daitem.Name == fcda.DaName {
- if daitem.BType == "Enum" {
- if daitem.Type == "fltloop" {
- return "YC"
- } else {
- return "YX"
- }
- } else {
- return "YC"
- }
- }
- }
- }
- if dotype.Cdc == "BCR" && fcda != nil {
- //判断LnClass,若LnClass为MMTR,则认为是遥脉,否则认为是遥测
- if fcda.LnClass == "MMTR" {
- return "YM"
- } else {
- return "YC"
- }
- }
- return ""
- }
- //根据doi对象获取对应的cdc代码及名称
- func (c *ScdMgr) GetDoiCdcInfo(scdXmlObj *node_attr.SCL, scdid int64, doiObj *node_attr.NDOI) string {
- mapTargetLNodeType := c.GetLNodeType(scdXmlObj)
- mapTargetLDoType := c.GetDOType(scdXmlObj)
- tmpdata, _ := GlobalNodeMap.Load(scdid)
- nodeCacheMap := tmpdata.(map[int64]NodeCacheMap)
- lnnode := nodeCacheMap[nodeCacheMap[doiObj.NodeId].ParentNodeId]
- lnType := lnnode.ObjAddr.(*node_attr.NLN).LnType
- if lnnodetpye, h := mapTargetLNodeType[lnType]; h {
- for _, doitem := range lnnodetpye.DO {
- if doitem.Name == doiObj.Name {
- dotype := doitem.Type
- if dotypeobj, h := mapTargetLDoType[dotype]; h {
- return dotypeobj.Cdc
- }
- break
- }
- }
- }
- return ""
- }
|