complete the function of loading topology information and circuit diagram information
This commit is contained in:
parent
945669c85e
commit
42e7d02625
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
6
main.go
6
main.go
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue