12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778 |
- 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": "MV",
- "CMV": "CMV",
- "SAV": "SAV",
- "WYE": "WYE",
- "DEL": "DEL",
- "SEQ": "SEQ",
- "INC": "INC",
- "BSC": "BSC",
- "ISC": "ISC",
- "APC": "APC",
- "ENC": "ENC",
- "HMV": "HMV",
- "HWYE": "HWYE",
- "HDEL": "HDEL",
- "BAC": "BAC",
- "ING": "整数状态定值",
- }
- var YaoXinMap = map[string]string{
- "SPS": "SPS",
- "DPS": "DPS",
- "ACT": "ACT",
- "ACD": "ACD",
- "SPC": "SPC",
- "DPC": "DPC",
- "ENS": "ENS",
- "VSS": "VSS",
- "HST": "直方图",
- "LPL": "LPL",
- "DPL": "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": "SPC",
- "DPC": "DPC",
- "INC": "INC",
- "BSC": "BSC",
- "ISC": "ISC",
- "APC": "APC",
- "ENC": "ENC",
- "BAC": "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": "INS",
- "BCR": "BCR",
- }
- //根据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.NLNode).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 ""
- }
|