complete the function of loading topology information and circuit diagram information

This commit is contained in:
douxu 2024-11-27 09:11:48 +08:00
parent 945669c85e
commit 42e7d02625
10 changed files with 203 additions and 181 deletions

View File

@ -13,6 +13,9 @@ import (
// ModelRTConfig define config stuct of model runtime server // ModelRTConfig define config stuct of model runtime server
type ModelRTConfig struct { type ModelRTConfig struct {
GridID int64
ZoneID int64
StationID int64
ParseConcurrentQuantity int // parse comtrade file concurrent quantity ParseConcurrentQuantity int // parse comtrade file concurrent quantity
PostgresDBURI string PostgresDBURI string
LCfg log.CutLogConfig // log config LCfg log.CutLogConfig // log config
@ -46,6 +49,10 @@ func ReadAndInitConfig(configDir, configName, configType string) (modelRTConfig
modelRTConfig.LCfg.MaxBackups = config.GetInt("log_maxbackups") modelRTConfig.LCfg.MaxBackups = config.GetInt("log_maxbackups")
modelRTConfig.LCfg.MaxAge = config.GetInt("log_maxage") modelRTConfig.LCfg.MaxAge = config.GetInt("log_maxage")
// init model base config from config.yaml
modelRTConfig.GridID = config.GetInt64("grid_id")
modelRTConfig.GridID = config.GetInt64("zone_id")
modelRTConfig.GridID = config.GetInt64("station_id")
modelRTConfig.ParseConcurrentQuantity = config.GetInt("parse_concurrent_quantity") modelRTConfig.ParseConcurrentQuantity = config.GetInt("parse_concurrent_quantity")
return modelRTConfig return modelRTConfig

View File

@ -29,13 +29,11 @@ func QueryCircuitDiagramComponentFromDB(ctx context.Context, pool *ants.PoolWith
} }
for _, component := range Components { for _, component := range Components {
fmt.Println(component)
pool.Invoke(config.ModelParseConfig{ pool.Invoke(config.ModelParseConfig{
ComponentInfo: component, ComponentInfo: component,
Context: ctx, Context: ctx,
}) })
} }
// TODO 加载 Topologic表拓扑关系
return nil return nil
} }

View File

@ -3,11 +3,12 @@ package database
import ( import (
"context" "context"
"fmt"
"time" "time"
"modelRT/diagram"
"modelRT/orm" "modelRT/orm"
"github.com/gofrs/uuid"
"go.uber.org/zap" "go.uber.org/zap"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
) )
@ -39,14 +40,46 @@ func QueryTopologicByPageID(ctx context.Context, logger *zap.Logger, pageID int6
// InitCircuitDiagramTopologic return circuit diagram topologic info from postgres // InitCircuitDiagramTopologic return circuit diagram topologic info from postgres
func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic) error { func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic) error {
// find root node var rootVertex uuid.UUID
var rootNode orm.Topologic
for index, node := range topologicNodes { for _, node := range topologicNodes {
if node.UUIDFrom.IsNil() { if node.UUIDFrom.IsNil() {
rootNode = topologicNodes[index] rootVertex = node.UUIDTo
break
} }
} }
fmt.Println(rootNode) topologicSet := diagram.NewGraph(rootVertex)
for _, node := range topologicNodes {
if node.UUIDFrom.IsNil() {
continue
}
topologicSet.AddEdge(node.UUIDFrom, node.UUIDTo)
}
return nil
}
// QueryTopologicFromDB return the result of query topologic info from postgresDB
func QueryTopologicFromDB(ctx context.Context, logger *zap.Logger, gridID, zoneID, stationID int64) error {
allPages, err := QueryAllPages(ctx, logger, gridID, zoneID, stationID)
if err != nil {
logger.Error("query all pages info failed", zap.Int64("gridID", gridID), zap.Int64("zoneID", zoneID), zap.Int64("stationID", stationID), zap.Error(err))
return err
}
for _, page := range allPages {
topologicInfos, err := QueryTopologicByPageID(ctx, logger, page.ID)
if err != nil {
logger.Error("query topologic info by pageID failed", zap.Int64("pageID", page.ID), zap.Error(err))
return err
}
err = InitCircuitDiagramTopologic(topologicInfos)
if err != nil {
logger.Error("init topologic failed", zap.Error(err))
return err
}
}
return nil return nil
} }

View File

@ -2,6 +2,7 @@ package diagram
import ( import (
"errors" "errors"
"fmt"
"sync" "sync"
cmap "github.com/orcaman/concurrent-map/v2" cmap "github.com/orcaman/concurrent-map/v2"
@ -12,12 +13,11 @@ var DiagramsOverview sync.Map
func GetComponentMap(key string) (*cmap.ConcurrentMap[string, any], error) { func GetComponentMap(key string) (*cmap.ConcurrentMap[string, any], error) {
value, ok := DiagramsOverview.Load(key) value, ok := DiagramsOverview.Load(key)
if !ok { if !ok {
newMap := cmap.New[any]() return nil, fmt.Errorf("can not find graph by pageID:%s", key)
return &newMap, nil
} }
paramsMap, ok := value.(*cmap.ConcurrentMap[string, any]) paramsMap, ok := value.(*cmap.ConcurrentMap[string, any])
if !ok { if !ok {
return nil, errors.New("") return nil, errors.New("convert to component map struct failed")
} }
return paramsMap, nil return paramsMap, nil
} }

136
diagram/graph.go Normal file
View File

@ -0,0 +1,136 @@
package diagram
import (
"errors"
"fmt"
"sync"
"github.com/gofrs/uuid"
)
// Graph represents a topological structure using an adjacency list
type Graph struct {
sync.RWMutex
// 根节点
RootVertex uuid.UUID
// 游离节点
FreeVertexs map[string]struct{}
VerticeLinks map[string][]uuid.UUID
// 存储多个上级节点同时指向同一下级节点的情况,key为下级节点,value为上级节点集合
BackLinks map[string][]uuid.UUID
}
// NewGraph creates a new graph
func NewGraph(root uuid.UUID) *Graph {
return &Graph{
RootVertex: root,
FreeVertexs: make(map[string]struct{}),
VerticeLinks: make(map[string][]uuid.UUID),
BackLinks: make(map[string][]uuid.UUID),
}
}
// AddNode adds a node to the graph
func (g *Graph) AddNode(vertex string) {
if _, exists := g.VerticeLinks[vertex]; !exists {
g.VerticeLinks[vertex] = []uuid.UUID{}
}
}
// CreateBackLink adds a node to the graph
func (g *Graph) CreateBackLink(vertex string) {
if _, exists := g.BackLinks[vertex]; !exists {
g.BackLinks[vertex] = []uuid.UUID{}
}
}
// AddEdge adds an edge between two VerticeLinks
func (g *Graph) AddEdge(from, to uuid.UUID) {
g.Lock()
defer g.Unlock()
fromKey := from.String()
toKey := to.String()
g.CreateBackLink(toKey)
g.BackLinks[toKey] = append(g.BackLinks[toKey], from)
g.AddNode(fromKey)
g.AddNode(toKey)
g.VerticeLinks[fromKey] = append(g.VerticeLinks[fromKey], to)
// 创建新的拓扑信息时,如果被链接的点已经存在于游离节点中
// 则将其移除
if _, exist := g.FreeVertexs[toKey]; exist {
delete(g.FreeVertexs, toKey)
}
}
// DelNode delete a node to the graph
func (g *Graph) DelNode(vertex string) error {
childNodes, exists := g.VerticeLinks[vertex]
if exists {
if len(childNodes) > 1 {
return errors.New("delete node failed,that vertex contains more than one child node")
}
delete(g.VerticeLinks, vertex)
}
parentNodes, exists := g.BackLinks[vertex]
if exists {
if len(parentNodes) > 1 {
return errors.New("delete node failed,that vertex contains more than one parent node")
}
delete(g.BackLinks, vertex)
} else {
return errors.New("that vertex don't have parent node")
}
return nil
}
// DelEdge delete an edge between two VerticeLinks
func (g *Graph) DelEdge(from, to uuid.UUID) error {
g.Lock()
defer g.Unlock()
toKey := to.String()
var fromKeys []uuid.UUID
if _, exist := g.BackLinks[toKey]; exist {
fromKeys = g.BackLinks[toKey]
} else {
fromKeys = []uuid.UUID{from}
}
childvertex := g.VerticeLinks[toKey]
err := g.DelNode(toKey)
if err != nil {
return fmt.Errorf("delete edge failed: %w", err)
}
for _, fromUUID := range fromKeys {
fromKey := fromUUID.String()
var delIndex int
for index, vertex := range g.VerticeLinks[fromKey] {
if vertex == to {
delIndex = index
}
}
vertex := g.VerticeLinks[fromKey]
copy(vertex[delIndex:], vertex[delIndex+1:])
vertex = vertex[:len(vertex)-1]
g.VerticeLinks[fromKey] = vertex
}
fromKey := from.String()
g.VerticeLinks[fromKey] = append(g.VerticeLinks[fromKey], childvertex...)
return nil
}
// PrintGraph prints the graph in adjacency list format
func (g *Graph) PrintGraph() {
g.RLock() // 读锁
defer g.RUnlock()
for vertex, edges := range g.VerticeLinks {
fmt.Printf("%s -> %v\n", vertex, edges)
}
}

View File

@ -4,148 +4,18 @@ import (
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
"github.com/gofrs/uuid"
) )
// Graph represents a topological structure using an adjacency list var GraphOverview sync.Map
type Graph struct {
sync.RWMutex func GetGraphMap(key string) (*Graph, error) {
// 根节点 value, ok := GraphOverview.Load(key)
rootVertex uuid.UUID if !ok {
// 游离节点 return nil, fmt.Errorf("can not find graph by pageID:%s", key)
freeVertexs map[string]struct{} }
verticeLinks map[string][]uuid.UUID graph, ok := value.(*Graph)
// 存储多个上级节点同时指向同一下级节点的情况,key为下级节点,value为上级节点集合 if !ok {
backLinks map[string][]uuid.UUID return nil, errors.New("convert to graph struct failed")
}
return graph, nil
} }
// NewGraph creates a new graph
func NewGraph(root uuid.UUID) *Graph {
return &Graph{
rootVertex: root,
freeVertexs: make(map[string]struct{}),
verticeLinks: make(map[string][]uuid.UUID),
backLinks: make(map[string][]uuid.UUID),
}
}
// AddNode adds a node to the graph
func (g *Graph) AddNode(vertex string) {
if _, exists := g.verticeLinks[vertex]; !exists {
g.verticeLinks[vertex] = []uuid.UUID{}
}
}
// CreateBackLink adds a node to the graph
func (g *Graph) CreateBackLink(vertex string) {
if _, exists := g.backLinks[vertex]; !exists {
g.backLinks[vertex] = []uuid.UUID{}
}
}
// AddEdge adds an edge between two verticeLinks
func (g *Graph) AddEdge(from, to uuid.UUID) {
g.Lock()
defer g.Unlock()
fromKey := from.String()
toKey := to.String()
g.CreateBackLink(toKey)
g.backLinks[toKey] = append(g.backLinks[toKey], from)
g.AddNode(fromKey)
g.AddNode(toKey)
g.verticeLinks[fromKey] = append(g.verticeLinks[fromKey], to)
// 创建新的拓扑信息时,如果被链接的点已经存在于游离节点中
// 则将其移除
if _, exist := g.freeVertexs[toKey]; exist {
delete(g.freeVertexs, toKey)
}
}
// DelNode delete a node to the graph
func (g *Graph) DelNode(vertex string) error {
childNodes, exists := g.verticeLinks[vertex]
if exists {
if len(childNodes) > 1 {
return errors.New("delete node failed,that vertex contains more than one child node")
}
delete(g.verticeLinks, vertex)
}
parentNodes, exists := g.backLinks[vertex]
if exists {
if len(parentNodes) > 1 {
return errors.New("delete node failed,that vertex contains more than one parent node")
}
delete(g.backLinks, vertex)
} else {
return errors.New("that vertex don't have parent node")
}
return nil
}
// DelEdge delete an edge between two verticeLinks
func (g *Graph) DelEdge(from, to uuid.UUID) error {
g.Lock()
defer g.Unlock()
toKey := to.String()
var fromKeys []uuid.UUID
if _, exist := g.backLinks[toKey]; exist {
fromKeys = g.backLinks[toKey]
} else {
fromKeys = []uuid.UUID{from}
}
childvertex := g.verticeLinks[toKey]
err := g.DelNode(toKey)
if err != nil {
return fmt.Errorf("delete edge failed: %w", err)
}
for _, fromUUID := range fromKeys {
fromKey := fromUUID.String()
var delIndex int
for index, vertex := range g.verticeLinks[fromKey] {
if vertex == to {
delIndex = index
}
}
vertex := g.verticeLinks[fromKey]
copy(vertex[delIndex:], vertex[delIndex+1:])
vertex = vertex[:len(vertex)-1]
g.verticeLinks[fromKey] = vertex
}
fromKey := from.String()
g.verticeLinks[fromKey] = append(g.verticeLinks[fromKey], childvertex...)
return nil
}
// PrintGraph prints the graph in adjacency list format
func (g *Graph) PrintGraph() {
g.RLock() // 读锁
defer g.RUnlock()
for vertex, edges := range g.verticeLinks {
fmt.Printf("%s -> %v\n", vertex, edges)
}
}
// func main() {
// graph := NewGraph()
// // Add verticeLinks and edges
// graph.AddEdge("A", "B")
// graph.AddEdge("A", "C")
// graph.AddEdge("B", "D")
// graph.AddEdge("C", "D")
// graph.AddEdge("C", "E")
// graph.AddEdge("E", "F")
// // Print the graph
// graph.PrintGraph()
// }

View File

@ -73,6 +73,12 @@ func main() {
panic(err) panic(err)
} }
err = database.QueryTopologicFromDB(ctx, logger, modelRTConfig.GridID, modelRTConfig.ZoneID, modelRTConfig.StationID)
if err != nil {
logger.Error("load topologic info from postgres failed", zap.Error(err))
panic(err)
}
engine := gin.Default() engine := gin.Default()
engine.Use(limiter.Middleware) engine.Use(limiter.Middleware)
engine.GET("/model/model_load", handler.ModelLoad) engine.GET("/model/model_load", handler.ModelLoad)

View File

@ -1,12 +0,0 @@
// Package orm define database data struct
package orm
type CircuitDiagram struct {
ID int64 `gorm:""`
ParentID int64
Type int
UUID string
OtherParams string
CreatedTime int64
UpdateTime int64
}

View File

@ -1,16 +0,0 @@
// Package orm define database data struct
package orm
import "time"
type CircuitDiagramOverview struct {
ID int64 `gorm:""`
Name string
CreatedTime time.Time
UpdateTime time.Time
}
// TableName func respresent return table name of circuit diagram overview
func (co *CircuitDiagramOverview) TableName() string {
return "circuit_diagram_overview"
}