refactor(orm/circuit_diagram_component): fix compilation issues caused by structure field changes

http://server.baseware.net:9000/project/datart/task/47
This commit is contained in:
douxu 2025-08-15 16:25:48 +08:00
parent f7a1ea2540
commit f4ab4e4ea4
27 changed files with 442 additions and 445 deletions

View File

@ -16,7 +16,7 @@ var (
// Event define alert event struct // Event define alert event struct
type Event struct { type Event struct {
ComponentID int64 ComponentUUID string
AnchorName string AnchorName string
Level constants.AlertLevel Level constants.AlertLevel
Message string Message string

View File

@ -15,7 +15,7 @@ type AnchorParamListConfig struct {
// AnchorParamBaseConfig define anchor params base config struct // AnchorParamBaseConfig define anchor params base config struct
type AnchorParamBaseConfig struct { type AnchorParamBaseConfig struct {
ComponentID int64 // component表 ID ComponentUUID string // componentUUID
AnchorName string // 锚定参量名称 AnchorName string // 锚定参量名称
CompareValUpperLimit float64 // 比较值上限 CompareValUpperLimit float64 // 比较值上限
CompareValLowerLimit float64 // 比较值下限 CompareValLowerLimit float64 // 比较值下限

View File

@ -16,13 +16,13 @@ import (
) )
// CreateComponentIntoDB define create component info of the circuit diagram into DB // CreateComponentIntoDB define create component info of the circuit diagram into DB
func CreateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo network.ComponentCreateInfo) (int64, error) { func CreateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo network.ComponentCreateInfo) (string, error) {
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second) cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() defer cancel()
globalUUID, err := uuid.FromString(componentInfo.UUID) globalUUID, err := uuid.FromString(componentInfo.UUID)
if err != nil { if err != nil {
return -1, fmt.Errorf("format uuid from string type failed:%w", err) return "", fmt.Errorf("format uuid from string type failed:%w", err)
} }
component := orm.Component{ component := orm.Component{
@ -31,7 +31,6 @@ func CreateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo netwo
ZoneID: strconv.FormatInt(componentInfo.ZoneID, 10), ZoneID: strconv.FormatInt(componentInfo.ZoneID, 10),
StationID: strconv.FormatInt(componentInfo.StationID, 10), StationID: strconv.FormatInt(componentInfo.StationID, 10),
Tag: componentInfo.Tag, Tag: componentInfo.Tag,
ComponentType: componentInfo.ComponentType,
Name: componentInfo.Name, Name: componentInfo.Name,
Context: componentInfo.Context, Context: componentInfo.Context,
Op: componentInfo.Op, Op: componentInfo.Op,
@ -44,7 +43,7 @@ func CreateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo netwo
if result.RowsAffected == 0 { if result.RowsAffected == 0 {
err = fmt.Errorf("%w:please check insert component slice", errcode.ErrInsertRowUnexpected) err = fmt.Errorf("%w:please check insert component slice", errcode.ErrInsertRowUnexpected)
} }
return -1, fmt.Errorf("insert component info failed:%w", err) return "", fmt.Errorf("insert component info failed:%w", err)
} }
return component.ID, nil return component.GlobalUUID.String(), nil
} }

View File

@ -5,42 +5,37 @@ import (
"context" "context"
"time" "time"
"modelRT/config"
"modelRT/logger"
"modelRT/orm" "modelRT/orm"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"github.com/panjf2000/ants/v2"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
) )
// QueryCircuitDiagramComponentFromDB return the result of query circuit diagram component info order by page id from postgresDB // QueryCircuitDiagramComponentFromDB return the result of query circuit diagram component info order by page id from postgresDB
func QueryCircuitDiagramComponentFromDB(ctx context.Context, tx *gorm.DB, pool *ants.PoolWithFunc) (map[uuid.UUID]int, error) { // func QueryCircuitDiagramComponentFromDB(ctx context.Context, tx *gorm.DB, pool *ants.PoolWithFunc) (map[uuid.UUID]string, error) {
var components []orm.Component // var components []orm.Component
// ctx超时判断 // // ctx超时判断
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second) // cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() // defer cancel()
result := tx.WithContext(cancelCtx).Clauses(clause.Locking{Strength: "UPDATE"}).Find(&components) // result := tx.WithContext(cancelCtx).Clauses(clause.Locking{Strength: "UPDATE"}).Find(&components)
if result.Error != nil { // if result.Error != nil {
logger.Error(ctx, "query circuit diagram component info failed", "error", result.Error) // logger.Error(ctx, "query circuit diagram component info failed", "error", result.Error)
return nil, result.Error // return nil, result.Error
} // }
// TODO 优化componentTypeMap输出 // componentTypeMap := make(map[uuid.UUID]string, len(components))
componentTypeMap := make(map[uuid.UUID]int, len(components)) // for _, component := range components {
// pool.Invoke(config.ModelParseConfig{
// ComponentInfo: component,
// Ctx: ctx,
// })
for _, component := range components { // componentTypeMap[component.GlobalUUID] = component.GlobalUUID.String()
pool.Invoke(config.ModelParseConfig{ // }
ComponentInfo: component, // return componentTypeMap, nil
Ctx: ctx, // }
})
componentTypeMap[component.GlobalUUID] = component.ComponentType
}
return componentTypeMap, nil
}
// QueryComponentByUUID return the result of query circuit diagram component info by uuid from postgresDB // QueryComponentByUUID return the result of query circuit diagram component info by uuid from postgresDB
func QueryComponentByUUID(ctx context.Context, tx *gorm.DB, uuid uuid.UUID) (orm.Component, error) { func QueryComponentByUUID(ctx context.Context, tx *gorm.DB, uuid uuid.UUID) (orm.Component, error) {

View File

@ -33,14 +33,14 @@ func QueryTopologic(ctx context.Context, tx *gorm.DB) ([]orm.Topologic, error) {
} }
// QueryTopologicFromDB return the result of query topologic info from DB // QueryTopologicFromDB return the result of query topologic info from DB
func QueryTopologicFromDB(ctx context.Context, tx *gorm.DB, componentTypeMap map[uuid.UUID]int) (*diagram.MultiBranchTreeNode, error) { func QueryTopologicFromDB(ctx context.Context, tx *gorm.DB) (*diagram.MultiBranchTreeNode, error) {
topologicInfos, err := QueryTopologic(ctx, tx) topologicInfos, err := QueryTopologic(ctx, tx)
if err != nil { if err != nil {
logger.Error(ctx, "query topologic info failed", "error", err) logger.Error(ctx, "query topologic info failed", "error", err)
return nil, err return nil, err
} }
tree, err := BuildMultiBranchTree(topologicInfos, componentTypeMap) tree, err := BuildMultiBranchTree(topologicInfos)
if err != nil { if err != nil {
logger.Error(ctx, "init topologic failed", "error", err) logger.Error(ctx, "init topologic failed", "error", err)
return nil, err return nil, err
@ -49,17 +49,11 @@ func QueryTopologicFromDB(ctx context.Context, tx *gorm.DB, componentTypeMap map
} }
// InitCircuitDiagramTopologic return circuit diagram topologic info from postgres // InitCircuitDiagramTopologic return circuit diagram topologic info from postgres
func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic, componentTypeMap map[uuid.UUID]int) error { func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic) error {
var rootVertex *diagram.MultiBranchTreeNode var rootVertex *diagram.MultiBranchTreeNode
for _, node := range topologicNodes { for _, node := range topologicNodes {
if node.UUIDFrom == constants.UUIDNil { if node.UUIDFrom == constants.UUIDNil {
// rootVertex = node.UUIDTo rootVertex = diagram.NewMultiBranchTree(node.UUIDFrom)
var componentType int
componentType, ok := componentTypeMap[node.UUIDFrom]
if !ok {
return fmt.Errorf("can not get component type by uuid: %s", node.UUIDFrom)
}
rootVertex = diagram.NewMultiBranchTree(node.UUIDFrom, componentType)
break break
} }
} }
@ -70,13 +64,7 @@ func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic, componentTypeMa
for _, node := range topologicNodes { for _, node := range topologicNodes {
if node.UUIDFrom == constants.UUIDNil { if node.UUIDFrom == constants.UUIDNil {
var componentType int nodeVertex := diagram.NewMultiBranchTree(node.UUIDTo)
componentType, ok := componentTypeMap[node.UUIDTo]
if !ok {
return fmt.Errorf("can not get component type by uuid: %s", node.UUIDTo)
}
nodeVertex := diagram.NewMultiBranchTree(node.UUIDTo, componentType)
rootVertex.AddChild(nodeVertex) rootVertex.AddChild(nodeVertex)
} }
} }
@ -91,9 +79,7 @@ func InitCircuitDiagramTopologic(topologicNodes []orm.Topologic, componentTypeMa
// TODO 电流互感器不单独划分间隔,以母线、浇筑母线、变压器为间隔原件 // TODO 电流互感器不单独划分间隔,以母线、浇筑母线、变压器为间隔原件
func IntervalBoundaryDetermine(uuid uuid.UUID) bool { func IntervalBoundaryDetermine(uuid uuid.UUID) bool {
fmt.Println(uuid) diagram.GetComponentMap(uuid.String())
var componentID int64
diagram.GetComponentMap(componentID)
// TODO 判断 component 的类型是否为间隔 // TODO 判断 component 的类型是否为间隔
// TODO 0xA1B2C3D4,高四位表示可以成为间隔的compoent类型的值为FFFF,普通 component 类型的值为 0000。低四位中前二位表示component的一级类型例如母线 PT、母联/母分、进线等,低四位中后二位表示一级类型中包含的具体类型,例如母线 PT中包含的电压互感器、隔离开关、接地开关、避雷器、带电显示器等。 // TODO 0xA1B2C3D4,高四位表示可以成为间隔的compoent类型的值为FFFF,普通 component 类型的值为 0000。低四位中前二位表示component的一级类型例如母线 PT、母联/母分、进线等,低四位中后二位表示一级类型中包含的具体类型,例如母线 PT中包含的电压互感器、隔离开关、接地开关、避雷器、带电显示器等。
num := uint32(0xA1B2C3D4) // 八位16进制数 num := uint32(0xA1B2C3D4) // 八位16进制数
@ -104,22 +90,15 @@ func IntervalBoundaryDetermine(uuid uuid.UUID) bool {
} }
// BuildMultiBranchTree return the multi branch tree by topologic info and component type map // BuildMultiBranchTree return the multi branch tree by topologic info and component type map
func BuildMultiBranchTree(topologics []orm.Topologic, componentTypeMap map[uuid.UUID]int) (*diagram.MultiBranchTreeNode, error) { func BuildMultiBranchTree(topologics []orm.Topologic) (*diagram.MultiBranchTreeNode, error) {
nodeMap := make(map[uuid.UUID]*diagram.MultiBranchTreeNode, len(topologics)*2) nodeMap := make(map[uuid.UUID]*diagram.MultiBranchTreeNode, len(topologics)*2)
for _, topo := range topologics { for _, topo := range topologics {
if _, exists := nodeMap[topo.UUIDFrom]; !exists { if _, exists := nodeMap[topo.UUIDFrom]; !exists {
// skip special uuid // skip special uuid
if topo.UUIDTo != constants.UUIDNil { if topo.UUIDTo != constants.UUIDNil {
var ok bool
componentType, ok := componentTypeMap[topo.UUIDFrom]
if !ok {
return nil, fmt.Errorf("can not get component type by uuid: %s", topo.UUIDFrom)
}
nodeMap[topo.UUIDFrom] = &diagram.MultiBranchTreeNode{ nodeMap[topo.UUIDFrom] = &diagram.MultiBranchTreeNode{
ID: topo.UUIDFrom, ID: topo.UUIDFrom,
NodeComponentType: componentType,
Children: make([]*diagram.MultiBranchTreeNode, 0), Children: make([]*diagram.MultiBranchTreeNode, 0),
} }
} }
@ -128,15 +107,8 @@ func BuildMultiBranchTree(topologics []orm.Topologic, componentTypeMap map[uuid.
if _, exists := nodeMap[topo.UUIDTo]; !exists { if _, exists := nodeMap[topo.UUIDTo]; !exists {
// skip special uuid // skip special uuid
if topo.UUIDTo != constants.UUIDNil { if topo.UUIDTo != constants.UUIDNil {
var ok bool
componentType, ok := componentTypeMap[topo.UUIDTo]
if !ok {
return nil, fmt.Errorf("can not get component type by uuid: %s", topo.UUIDTo)
}
nodeMap[topo.UUIDTo] = &diagram.MultiBranchTreeNode{ nodeMap[topo.UUIDTo] = &diagram.MultiBranchTreeNode{
ID: topo.UUIDTo, ID: topo.UUIDTo,
NodeComponentType: componentType,
Children: make([]*diagram.MultiBranchTreeNode, 0), Children: make([]*diagram.MultiBranchTreeNode, 0),
} }
} }
@ -146,10 +118,8 @@ func BuildMultiBranchTree(topologics []orm.Topologic, componentTypeMap map[uuid.
for _, topo := range topologics { for _, topo := range topologics {
var parent *diagram.MultiBranchTreeNode var parent *diagram.MultiBranchTreeNode
if topo.UUIDFrom == constants.UUIDNil { if topo.UUIDFrom == constants.UUIDNil {
var componentType int
parent = &diagram.MultiBranchTreeNode{ parent = &diagram.MultiBranchTreeNode{
ID: constants.UUIDNil, ID: constants.UUIDNil,
NodeComponentType: componentType,
} }
nodeMap[constants.UUIDNil] = parent nodeMap[constants.UUIDNil] = parent
} else { } else {
@ -158,10 +128,8 @@ func BuildMultiBranchTree(topologics []orm.Topologic, componentTypeMap map[uuid.
var child *diagram.MultiBranchTreeNode var child *diagram.MultiBranchTreeNode
if topo.UUIDTo == constants.UUIDNil { if topo.UUIDTo == constants.UUIDNil {
var componentType int
child = &diagram.MultiBranchTreeNode{ child = &diagram.MultiBranchTreeNode{
ID: topo.UUIDTo, ID: topo.UUIDTo,
NodeComponentType: componentType,
} }
} else { } else {
child = nodeMap[topo.UUIDTo] child = nodeMap[topo.UUIDTo]

View File

@ -16,13 +16,13 @@ import (
) )
// UpdateComponentIntoDB define update component info of the circuit diagram into DB // UpdateComponentIntoDB define update component info of the circuit diagram into DB
func UpdateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo network.ComponentUpdateInfo) (int64, error) { func UpdateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo network.ComponentUpdateInfo) (string, error) {
cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second) cancelCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() defer cancel()
globalUUID, err := uuid.FromString(componentInfo.UUID) globalUUID, err := uuid.FromString(componentInfo.UUID)
if err != nil { if err != nil {
return -1, fmt.Errorf("format uuid from string type failed:%w", err) return "", fmt.Errorf("format uuid from string type failed:%w", err)
} }
var component orm.Component var component orm.Component
@ -32,7 +32,7 @@ func UpdateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo netwo
if result.RowsAffected == 0 { if result.RowsAffected == 0 {
err = fmt.Errorf("%w:please check update component conditions", errcode.ErrUpdateRowZero) err = fmt.Errorf("%w:please check update component conditions", errcode.ErrUpdateRowZero)
} }
return -1, fmt.Errorf("query component info failed:%w", err) return "", fmt.Errorf("query component info failed:%w", err)
} }
updateParams := orm.Component{ updateParams := orm.Component{
@ -41,21 +41,20 @@ func UpdateComponentIntoDB(ctx context.Context, tx *gorm.DB, componentInfo netwo
ZoneID: strconv.FormatInt(componentInfo.ZoneID, 10), ZoneID: strconv.FormatInt(componentInfo.ZoneID, 10),
StationID: strconv.FormatInt(componentInfo.StationID, 10), StationID: strconv.FormatInt(componentInfo.StationID, 10),
Tag: componentInfo.Tag, Tag: componentInfo.Tag,
ComponentType: componentInfo.ComponentType,
Name: componentInfo.Name, Name: componentInfo.Name,
Context: componentInfo.Context, Context: componentInfo.Context,
Op: componentInfo.Op, Op: componentInfo.Op,
Ts: time.Now(), Ts: time.Now(),
} }
result = tx.Model(&orm.Component{}).WithContext(cancelCtx).Where("id = ?", component.ID).Updates(&updateParams) result = tx.Model(&orm.Component{}).WithContext(cancelCtx).Where("GLOBAL_UUID = ?", component.GlobalUUID).Updates(&updateParams)
if result.Error != nil || result.RowsAffected == 0 { if result.Error != nil || result.RowsAffected == 0 {
err := result.Error err := result.Error
if result.RowsAffected == 0 { if result.RowsAffected == 0 {
err = fmt.Errorf("%w:please check update component conditions", errcode.ErrUpdateRowZero) err = fmt.Errorf("%w:please check update component conditions", errcode.ErrUpdateRowZero)
} }
return -1, fmt.Errorf("update component info failed:%w", err) return "", fmt.Errorf("update component info failed:%w", err)
} }
return component.ID, nil return component.GlobalUUID.String(), nil
} }

View File

@ -10,10 +10,10 @@ import (
var anchorValueOverview sync.Map var anchorValueOverview sync.Map
// GetAnchorValue define func of get circuit diagram data by componentID // GetAnchorValue define func of get circuit diagram data by componentID
func GetAnchorValue(componentID int64) (string, error) { func GetAnchorValue(componentUUID string) (string, error) {
value, ok := diagramsOverview.Load(componentID) value, ok := diagramsOverview.Load(componentUUID)
if !ok { if !ok {
return "", fmt.Errorf("can not find anchor value by componentID:%d", componentID) return "", fmt.Errorf("can not find anchor value by componentUUID:%s", componentUUID)
} }
anchorValue, ok := value.(string) anchorValue, ok := value.(string)
if !ok { if !ok {
@ -22,20 +22,20 @@ func GetAnchorValue(componentID int64) (string, error) {
return anchorValue, nil return anchorValue, nil
} }
// UpdateAnchorValue define func of update anchor value by componentID and anchor name // UpdateAnchorValue define func of update anchor value by componentUUID and anchor name
func UpdateAnchorValue(componentID int64, anchorValue string) bool { func UpdateAnchorValue(componentUUID string, anchorValue string) bool {
_, result := anchorValueOverview.Swap(componentID, anchorValue) _, result := anchorValueOverview.Swap(componentUUID, anchorValue)
return result return result
} }
// StoreAnchorValue define func of store anchor value with componentID and anchor name // StoreAnchorValue define func of store anchor value with componentUUID and anchor name
func StoreAnchorValue(componentID int64, anchorValue string) { func StoreAnchorValue(componentUUID string, anchorValue string) {
anchorValueOverview.Store(componentID, anchorValue) anchorValueOverview.Store(componentUUID, anchorValue)
return return
} }
// DeleteAnchorValue define func of delete anchor value with componentID // DeleteAnchorValue define func of delete anchor value with componentUUID
func DeleteAnchorValue(componentID int64) { func DeleteAnchorValue(componentUUID string) {
anchorValueOverview.Delete(componentID) anchorValueOverview.Delete(componentUUID)
return return
} }

View File

@ -4,38 +4,40 @@ import (
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
"modelRT/orm"
) )
// diagramsOverview define struct of storage all circuit diagram data // diagramsOverview define struct of storage all circuit diagram data
var diagramsOverview sync.Map var diagramsOverview sync.Map
// GetComponentMap define func of get circuit diagram data by component id // GetComponentMap define func of get circuit diagram data by component uuid
func GetComponentMap(componentID int64) (map[string]interface{}, error) { func GetComponentMap(componentUUID string) (*orm.Component, error) {
value, ok := diagramsOverview.Load(componentID) value, ok := diagramsOverview.Load(componentUUID)
if !ok { if !ok {
return nil, fmt.Errorf("can not find graph by global uuid:%d", componentID) return nil, fmt.Errorf("can not find graph by global uuid:%s", componentUUID)
} }
paramsMap, ok := value.(map[string]interface{}) componentInfo, ok := value.(*orm.Component)
if !ok { if !ok {
return nil, errors.New("convert to component map struct failed") return nil, errors.New("convert to component map struct failed")
} }
return paramsMap, nil return componentInfo, nil
} }
// UpdateComponentMap define func of update circuit diagram data by component id and component info // UpdateComponentMap define func of update circuit diagram data by component uuid and component info
func UpdateComponentMap(componentID int64, componentInfo map[string]interface{}) bool { func UpdateComponentMap(componentID int64, componentInfo *orm.Component) bool {
_, result := diagramsOverview.Swap(componentID, componentInfo) _, result := diagramsOverview.Swap(componentID, componentInfo)
return result return result
} }
// StoreComponentMap define func of store circuit diagram data with component id and component info // StoreComponentMap define func of store circuit diagram data with component uuid and component info
func StoreComponentMap(componentID int64, componentInfo map[string]interface{}) { func StoreComponentMap(componentUUID string, componentInfo *orm.Component) {
diagramsOverview.Store(componentID, componentInfo) diagramsOverview.Store(componentUUID, componentInfo)
return return
} }
// DeleteComponentMap define func of delete circuit diagram data with component id // DeleteComponentMap define func of delete circuit diagram data with component uuid
func DeleteComponentMap(componentID int64) { func DeleteComponentMap(componentUUID string) {
diagramsOverview.Delete(componentID) diagramsOverview.Delete(componentUUID)
return return
} }

View File

@ -11,15 +11,13 @@ var GlobalTree *MultiBranchTreeNode
// MultiBranchTreeNode represents a topological structure using an multi branch tree // MultiBranchTreeNode represents a topological structure using an multi branch tree
type MultiBranchTreeNode struct { type MultiBranchTreeNode struct {
ID uuid.UUID // 节点唯一标识 ID uuid.UUID // 节点唯一标识
NodeComponentType int // 节点组件类型
Parent *MultiBranchTreeNode // 指向父节点的指针 Parent *MultiBranchTreeNode // 指向父节点的指针
Children []*MultiBranchTreeNode // 指向所有子节点的指针切片 Children []*MultiBranchTreeNode // 指向所有子节点的指针切片
} }
func NewMultiBranchTree(id uuid.UUID, componentType int) *MultiBranchTreeNode { func NewMultiBranchTree(id uuid.UUID) *MultiBranchTreeNode {
return &MultiBranchTreeNode{ return &MultiBranchTreeNode{
ID: id, ID: id,
NodeComponentType: componentType,
Children: make([]*MultiBranchTreeNode, 0), Children: make([]*MultiBranchTreeNode, 0),
} }
} }
@ -58,7 +56,7 @@ func (n *MultiBranchTreeNode) PrintTree(level int) {
fmt.Print(" ") fmt.Print(" ")
} }
fmt.Printf("- ComponentType:%d,(ID: %s)\n", n.NodeComponentType, n.ID) fmt.Printf("-ID: %s\n", n.ID)
for _, child := range n.Children { for _, child := range n.Children {
child.PrintTree(level + 1) child.PrintTree(level + 1)

View File

@ -8,11 +8,9 @@ import (
"time" "time"
"modelRT/common/errcode" "modelRT/common/errcode"
"modelRT/constants"
"modelRT/database" "modelRT/database"
"modelRT/diagram" "modelRT/diagram"
"modelRT/logger" "modelRT/logger"
"modelRT/model"
"modelRT/network" "modelRT/network"
"modelRT/orm" "modelRT/orm"
@ -65,40 +63,7 @@ func ComponentAnchorReplaceHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp) c.JSON(http.StatusOK, resp)
return return
} }
diagram.UpdateAnchorValue(componentInfo.GlobalUUID.String(), anchorName)
cancelCtx, cancel = context.WithTimeout(c, 5*time.Second)
defer cancel()
unmarshalMap := make(map[string]interface{})
tableName := model.SelectModelNameByType(componentInfo.ComponentType)
result = pgClient.WithContext(cancelCtx).Table(tableName).Where("global_uuid = ?", uuid).Find(&unmarshalMap)
if result.Error != nil {
logger.Error(c, "query model detail info failed", "error", result.Error)
resp := network.FailureResponse{
Code: http.StatusBadRequest,
Msg: result.Error.Error(),
}
c.JSON(http.StatusOK, resp)
return
}
if unmarshalMap == nil {
err := fmt.Errorf("query model detail info by uuid failed:%w", errcode.ErrQueryRowZero)
logger.Error(c, "query model detail info from table is empty", "table_name", tableName)
resp := network.FailureResponse{
Code: http.StatusBadRequest,
Msg: err.Error(),
}
c.JSON(http.StatusOK, resp)
return
}
componentType := unmarshalMap["component_type"].(int)
if componentType != constants.DemoType {
logger.Error(c, "can not process real time data of component type not equal DemoType", "component_id", componentInfo.ID)
}
diagram.UpdateAnchorValue(componentInfo.ID, anchorName)
resp := network.SuccessResponse{ resp := network.SuccessResponse{
Code: http.StatusOK, Code: http.StatusOK,

View File

@ -9,8 +9,8 @@ import (
"modelRT/diagram" "modelRT/diagram"
"modelRT/logger" "modelRT/logger"
"modelRT/network" "modelRT/network"
"modelRT/orm"
"github.com/bitly/go-simplejson"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
) )
@ -102,8 +102,8 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
graph.AddEdge(topologicCreateInfo.UUIDFrom, topologicCreateInfo.UUIDTo) graph.AddEdge(topologicCreateInfo.UUIDFrom, topologicCreateInfo.UUIDTo)
} }
for index, componentInfo := range request.ComponentInfos { for index, info := range request.ComponentInfos {
componentID, err := database.CreateComponentIntoDB(c, tx, componentInfo) componentUUID, err := database.CreateComponentIntoDB(c, tx, info)
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
@ -119,64 +119,48 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp) c.JSON(http.StatusOK, resp)
return return
} }
request.ComponentInfos[index].ID = componentID request.ComponentInfos[index].UUID = componentUUID
err = database.CreateModelIntoDB(c, tx, componentID, componentInfo.ComponentType, componentInfo.Params)
if err != nil {
tx.Rollback()
logger.Error(c, "create component model into DB failed", "component_infos", request.ComponentInfos, "error", err)
resp := network.FailureResponse{
Code: http.StatusBadRequest,
Msg: err.Error(),
PayLoad: map[string]interface{}{
"uuid": request.PageID,
"component_infos": request.ComponentInfos,
},
}
c.JSON(http.StatusOK, resp)
return
}
} }
for _, componentInfo := range request.ComponentInfos { for _, info := range request.ComponentInfos {
paramsJSON, err := simplejson.NewJson([]byte(componentInfo.Params)) component := &orm.Component{
if err != nil { GlobalUUID: uuid.FromStringOrNil(info.UUID),
tx.Rollback() // NsPath
// Tag string `gorm:"column:TAG"`
logger.Error(c, "unmarshal component params info failed", "component_params", componentInfo.Params, "error", err) Name: info.Name,
// ModelName string `gorm:"column:MODEL_NAME"`
resp := network.FailureResponse{ // Description: info.Description,
Code: http.StatusBadRequest, // GridID: info.GridID,
Msg: err.Error(), // ZoneID: info.ZoneID,
PayLoad: map[string]interface{}{ // StationID: info.StationID,
"uuid": componentInfo.UUID, // Type int `gorm:"column:TYPE"`
"component_params": componentInfo.Params, // InService bool `gorm:"column:IN_SERVICE"`
}, // State int `gorm:"column:STATE"`
} // Status int `gorm:"column:STATUS"`
c.JSON(http.StatusOK, resp) // Connection map[string]interface{} `gorm:"column:CONNECTION;type:jsonb;default:'{}'"`
return // Label map[string]interface{} `gorm:"column:LABEL;type:jsonb;default:'{}'"`
// Context string `gorm:"column:CONTEXT"`
// Op: info.Op,
// Ts: info.Ts,
} }
// paramsJSON, err := simplejson.NewJson([]byte(info.Params))
// if err != nil {
// tx.Rollback()
componentMap, err := paramsJSON.Map() // logger.Error(c, "unmarshal component params info failed", "component_params", info.Params, "error", err)
if err != nil {
tx.Rollback()
logger.Error(c, "format params json info to map failed", "error", err) // resp := network.FailureResponse{
// Code: http.StatusBadRequest,
resp := network.FailureResponse{ // Msg: err.Error(),
Code: http.StatusBadRequest, // PayLoad: map[string]interface{}{
Msg: err.Error(), // "uuid": info.UUID,
PayLoad: map[string]interface{}{ // "component_params": info.Params,
"uuid": componentInfo.UUID, // },
"component_params": componentInfo.Params, // }
}, // c.JSON(http.StatusOK, resp)
} // return
c.JSON(http.StatusOK, resp) // }
return diagram.StoreComponentMap(info.UUID, component)
}
diagram.StoreComponentMap(componentInfo.ID, componentMap)
} }
if len(request.FreeVertexs) > 0 { if len(request.FreeVertexs) > 0 {

View File

@ -11,7 +11,6 @@ import (
"modelRT/database" "modelRT/database"
"modelRT/diagram" "modelRT/diagram"
"modelRT/logger" "modelRT/logger"
"modelRT/model"
"modelRT/network" "modelRT/network"
"modelRT/orm" "modelRT/orm"
@ -192,32 +191,7 @@ func CircuitDiagramDeleteHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp) c.JSON(http.StatusOK, resp)
return return
} }
diagram.DeleteComponentMap(component.GlobalUUID.String())
modelStruct := model.SelectModelByType(component.ComponentType)
modelStruct.SetComponentID(component.ID)
result = tx.WithContext(cancelCtx).Where("component_id = ?", component.ID).Delete(modelStruct)
if result.Error != nil || result.RowsAffected == 0 {
tx.Rollback()
err := result.Error
if result.RowsAffected == 0 {
err = fmt.Errorf("%w:please check uuid conditions", errcode.ErrDeleteRowZero)
}
msg := fmt.Sprintf("delete component info from table %s failed", modelStruct.ReturnTableName())
logger.Error(c, msg, "component_global_uuid", componentInfo.UUID, "error", err)
resp := network.FailureResponse{
Code: http.StatusBadRequest,
Msg: err.Error(),
PayLoad: map[string]interface{}{
"uuid": componentInfo.UUID,
},
}
c.JSON(http.StatusOK, resp)
return
}
diagram.DeleteComponentMap(component.ID)
} }
if len(request.FreeVertexs) > 0 { if len(request.FreeVertexs) > 0 {

View File

@ -77,7 +77,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
return return
} }
componentParams, err := diagram.GetComponentMap(component.ID) componentParams, err := diagram.GetComponentMap(component.GlobalUUID.String())
if err != nil { if err != nil {
logger.Error(c, "get component data from set by uuid failed", "error", err) logger.Error(c, "get component data from set by uuid failed", "error", err)
@ -111,7 +111,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
return return
} }
rootComponentParam, err := diagram.GetComponentMap(rootComponent.ID) rootComponentParam, err := diagram.GetComponentMap(rootComponent.GlobalUUID.String())
if err != nil { if err != nil {
logger.Error(c, "get component data from set by uuid failed", "error", err) logger.Error(c, "get component data from set by uuid failed", "error", err)

View File

@ -8,9 +8,10 @@ import (
"modelRT/diagram" "modelRT/diagram"
"modelRT/logger" "modelRT/logger"
"modelRT/network" "modelRT/network"
"modelRT/orm"
"github.com/bitly/go-simplejson"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
) )
// CircuitDiagramUpdateHandler define circuit diagram update process API // CircuitDiagramUpdateHandler define circuit diagram update process API
@ -103,7 +104,7 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
} }
for index, componentInfo := range request.ComponentInfos { for index, componentInfo := range request.ComponentInfos {
componentID, err := database.UpdateComponentIntoDB(c, tx, componentInfo) componentUUID, err := database.UpdateComponentIntoDB(c, tx, componentInfo)
if err != nil { if err != nil {
logger.Error(c, "udpate component info into DB failed", "error", err) logger.Error(c, "udpate component info into DB failed", "error", err)
@ -118,59 +119,47 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp) c.JSON(http.StatusOK, resp)
return return
} }
request.ComponentInfos[index].UUID = componentUUID
request.ComponentInfos[index].ID = componentID
err = database.UpdateModelIntoDB(c, tx, componentID, componentInfo.ComponentType, componentInfo.Params)
if err != nil {
logger.Error(c, "udpate component model info into DB failed", "error", err)
resp := network.FailureResponse{
Code: http.StatusBadRequest,
Msg: err.Error(),
PayLoad: map[string]interface{}{
"page_id": request.PageID,
"component_info": request.ComponentInfos,
},
}
c.JSON(http.StatusOK, resp)
return
}
} }
for _, componentInfo := range request.ComponentInfos { for _, info := range request.ComponentInfos {
paramsJSON, err := simplejson.NewJson([]byte(componentInfo.Params)) component := &orm.Component{
if err != nil { GlobalUUID: uuid.FromStringOrNil(info.UUID),
logger.Error(c, "unmarshal component info by concurrent map failed", "component_params", componentInfo.Params, "error", err) // NsPath
// Tag string `gorm:"column:TAG"`
resp := network.FailureResponse{ Name: info.Name,
Code: http.StatusBadRequest, // ModelName string `gorm:"column:MODEL_NAME"`
Msg: err.Error(), // Description: info.Description,
PayLoad: map[string]interface{}{ // GridID: info.GridID,
"uuid": componentInfo.UUID, // ZoneID: info.ZoneID,
"component_params": componentInfo.Params, // StationID: info.StationID,
}, // Type int `gorm:"column:TYPE"`
} // InService bool `gorm:"column:IN_SERVICE"`
c.JSON(http.StatusOK, resp) // State int `gorm:"column:STATE"`
return // Status int `gorm:"column:STATUS"`
// Connection map[string]interface{} `gorm:"column:CONNECTION;type:jsonb;default:'{}'"`
// Label map[string]interface{} `gorm:"column:LABEL;type:jsonb;default:'{}'"`
// Context string `gorm:"column:CONTEXT"`
Op: info.Op,
// Ts: info.Ts,
} }
componentMap, err := paramsJSON.Map() // paramsJSON, err := simplejson.NewJson([]byte(info.Params))
if err != nil { // if err != nil {
logger.Error(c, "format params json info to map failed", "error", err) // logger.Error(c, "unmarshal component info by concurrent map failed", "component_params", info.Params, "error", err)
resp := network.FailureResponse{ // resp := network.FailureResponse{
Code: http.StatusBadRequest, // Code: http.StatusBadRequest,
Msg: err.Error(), // Msg: err.Error(),
PayLoad: map[string]interface{}{ // PayLoad: map[string]interface{}{
"uuid": componentInfo.UUID, // "uuid": info.UUID,
"component_params": componentInfo.Params, // "component_params": info.Params,
}, // },
} // }
c.JSON(http.StatusOK, resp) // c.JSON(http.StatusOK, resp)
return // return
} // }
diagram.UpdateComponentMap(componentInfo.ID, componentMap) diagram.UpdateComponentMap(info.ID, component)
} }
if len(request.FreeVertexs) > 0 { if len(request.FreeVertexs) > 0 {

View File

@ -65,7 +65,7 @@ func RealTimeDataReceivehandler(c *gin.Context) {
realtimedata.RealTimeDataChan <- request realtimedata.RealTimeDataChan <- request
payload := map[string]interface{}{ payload := map[string]interface{}{
"component_id": request.PayLoad.ComponentID, "component_uuid": request.PayLoad.ComponentUUID,
"point": request.PayLoad.Point, "point": request.PayLoad.Point,
} }
respByte := processResponse(0, "success", payload) respByte := processResponse(0, "success", payload)

12
main.go
View File

@ -102,14 +102,14 @@ func main() {
postgresDBClient.Transaction(func(tx *gorm.DB) error { postgresDBClient.Transaction(func(tx *gorm.DB) error {
// load circuit diagram from postgres // load circuit diagram from postgres
componentTypeMap, err := database.QueryCircuitDiagramComponentFromDB(cancelCtx, tx, parsePool) // componentTypeMap, err := database.QueryCircuitDiagramComponentFromDB(cancelCtx, tx, parsePool)
if err != nil { // if err != nil {
logger.Error(ctx, "load circuit diagrams from postgres failed", "error", err) // logger.Error(ctx, "load circuit diagrams from postgres failed", "error", err)
panic(err) // panic(err)
} // }
// TODO 暂时屏蔽完成 swagger 启动测试 // TODO 暂时屏蔽完成 swagger 启动测试
tree, err := database.QueryTopologicFromDB(ctx, tx, componentTypeMap) tree, err := database.QueryTopologicFromDB(ctx, tx)
if err != nil { if err != nil {
logger.Error(ctx, "load topologic info from postgres failed", "error", err) logger.Error(ctx, "load topologic info from postgres failed", "error", err)
panic(err) panic(err)

View File

@ -21,7 +21,6 @@ type TopologicUUIDCreateInfo struct {
// ComponentCreateInfo defines circuit diagram component create index info // ComponentCreateInfo defines circuit diagram component create index info
type ComponentCreateInfo struct { type ComponentCreateInfo struct {
ID int64 `json:"id"`
UUID string `json:"uuid"` UUID string `json:"uuid"`
Name string `json:"name"` Name string `json:"name"`
Context string `json:"context"` Context string `json:"context"`
@ -30,7 +29,6 @@ type ComponentCreateInfo struct {
StationID int64 `json:"station_id"` StationID int64 `json:"station_id"`
PageID int64 `json:"page_id"` PageID int64 `json:"page_id"`
Tag string `json:"tag"` Tag string `json:"tag"`
ComponentType int `json:"component_type"`
Params string `json:"params"` Params string `json:"params"`
Op int `json:"op"` Op int `json:"op"`
} }

View File

@ -41,7 +41,6 @@ type ComponentUpdateInfo struct {
GridID int64 `json:"grid_id"` GridID int64 `json:"grid_id"`
ZoneID int64 `json:"zone_id"` ZoneID int64 `json:"zone_id"`
StationID int64 `json:"station_id"` StationID int64 `json:"station_id"`
ComponentType int `json:"component_type"`
Params string `json:"params"` Params string `json:"params"`
Op int `json:"op"` Op int `json:"op"`
Tag string `json:"tag"` Tag string `json:"tag"`

View File

@ -8,7 +8,7 @@ type RealTimeDataReceiveRequest struct {
// RealTimeDataReceivePayload defines request payload of real time data receive api // RealTimeDataReceivePayload defines request payload of real time data receive api
type RealTimeDataReceivePayload struct { type RealTimeDataReceivePayload struct {
ComponentID int64 `json:"component_id"` ComponentUUID string `json:"component_uuid"`
Point string `json:"point"` Point string `json:"point"`
Values []RealTimeDataReceiveParam `json:"values"` Values []RealTimeDataReceiveParam `json:"values"`
} }

View File

@ -1,3 +1,4 @@
// Package orm define database data struct
package orm package orm
import ( import (

View File

@ -27,10 +27,6 @@ type Component struct {
Context string `gorm:"column:CONTEXT"` Context string `gorm:"column:CONTEXT"`
Op int `gorm:"column:OP"` Op int `gorm:"column:OP"`
Ts time.Time `gorm:"column:TS"` Ts time.Time `gorm:"column:TS"`
// TODO 解决删除ID、ComponentType 后的报错
ID int64 `gorm:"column:id;primaryKey"`
ComponentType int `gorm:"column:TYPE"`
} }
// TableName func respresent return table name of Component // TableName func respresent return table name of Component

View File

@ -2,6 +2,7 @@ package pool
import ( import (
"context" "context"
"fmt"
"sync" "sync"
"modelRT/config" "modelRT/config"
@ -13,7 +14,10 @@ func init() {
} }
} }
var globalComponentChanSet *ComponentChanSet var (
globalComponentChanMap sync.Map
globalComponentChanSet *ComponentChanSet
)
// ComponentChanSet defines component anchor real time data process channel set // ComponentChanSet defines component anchor real time data process channel set
type ComponentChanSet struct { type ComponentChanSet struct {
@ -21,36 +25,21 @@ type ComponentChanSet struct {
AnchorChans []chan config.AnchorParamConfig AnchorChans []chan config.AnchorParamConfig
} }
func GetComponentChan(ctx context.Context, componentID int64) chan config.AnchorParamConfig { func GetAnchorParamChan(ctx context.Context, componentUUID string) (chan config.AnchorParamConfig, error) {
globalComponentChanSet.RLock() paramChan, ok := globalComponentChanMap.Load(componentUUID)
componentChan := globalComponentChanSet.AnchorChans[componentID] if !ok {
if componentChan == nil { return CreateNewAnchorParamChan(ctx, componentUUID), nil
globalComponentChanSet.RUnlock()
globalComponentChanSet.Lock()
defer globalComponentChanSet.Unlock()
return CreateNewComponentChan(ctx, componentID)
}
globalComponentChanSet.RUnlock()
return componentChan
} }
func CreateNewComponentChan(ctx context.Context, componentID int64) chan config.AnchorParamConfig { anchorParamChan, ok := paramChan.(chan config.AnchorParamConfig)
componentChan := globalComponentChanSet.AnchorChans[componentID] if !ok {
if componentChan == nil { return nil, fmt.Errorf("conversion component anchor param chan type failed for componentUUID: %s", componentUUID)
componentChan = make(chan config.AnchorParamConfig, 100) }
globalComponentChanSet.AnchorChans[componentID] = componentChan return anchorParamChan, nil
readyChan := make(chan struct{})
chanConfig := config.AnchorChanConfig{
Ctx: ctx,
AnchorChan: componentChan,
ReadyChan: readyChan,
} }
AnchorRealTimePool.Invoke(chanConfig) func CreateNewAnchorParamChan(ctx context.Context, componentUUID string) chan config.AnchorParamConfig {
anchorParamChan := make(chan config.AnchorParamConfig, 100)
<-readyChan globalComponentChanMap.Store(componentUUID, anchorParamChan)
return componentChan return anchorParamChan
}
return componentChan
} }

View File

@ -48,13 +48,13 @@ var AnchorFunc = func(poolConfig interface{}) {
firstStart = false firstStart = false
} }
componentID := anchorParaConfig.ComponentID componentUUID := anchorParaConfig.ComponentUUID
anchorRealTimeDatas := anchorParaConfig.AnchorRealTimeData anchorRealTimeDatas := anchorParaConfig.AnchorRealTimeData
for _, value := range anchorRealTimeDatas { for _, value := range anchorRealTimeDatas {
anchorName, err := diagram.GetAnchorValue(componentID) anchorName, err := diagram.GetAnchorValue(componentUUID)
if err != nil { if err != nil {
logger.Error(anchorChanConfig.Ctx, "can not get anchor value from map by uuid", "component_id", componentID, "error", err) logger.Error(anchorChanConfig.Ctx, "can not get anchor value from map by uuid", "component_uuid", componentUUID, "error", err)
continue continue
} }
@ -70,7 +70,7 @@ var AnchorFunc = func(poolConfig interface{}) {
message := fmt.Sprintf("anchor param %s value out of range, value:%f, upper limit:%f, lower limit:%f", anchorName, message := fmt.Sprintf("anchor param %s value out of range, value:%f, upper limit:%f, lower limit:%f", anchorName,
compareValue, upperLimitVal, lowerlimitVal) compareValue, upperLimitVal, lowerlimitVal)
event := alert.Event{ event := alert.Event{
ComponentID: componentID, ComponentUUID: componentUUID,
AnchorName: anchorName, AnchorName: anchorName,
Level: constants.InfoAlertLevel, Level: constants.InfoAlertLevel,
Message: message, Message: message,

View File

@ -9,7 +9,6 @@ import (
"modelRT/database" "modelRT/database"
"modelRT/diagram" "modelRT/diagram"
"modelRT/logger" "modelRT/logger"
"modelRT/model"
) )
// ParseFunc defines func that parses the model data from postgres // ParseFunc defines func that parses the model data from postgres
@ -23,42 +22,16 @@ var ParseFunc = func(parseConfig interface{}) {
cancelCtx, cancel := context.WithTimeout(modelParseConfig.Ctx, 5*time.Second) cancelCtx, cancel := context.WithTimeout(modelParseConfig.Ctx, 5*time.Second)
defer cancel() defer cancel()
pgClient := database.GetPostgresDBClient() pgClient := database.GetPostgresDBClient()
component, err := database.QueryComponentByUUID(cancelCtx, pgClient, modelParseConfig.ComponentInfo.GlobalUUID)
unmarshalMap := make(map[string]interface{}) if err != nil {
tableName := model.SelectModelNameByType(modelParseConfig.ComponentInfo.ComponentType) logger.Error(modelParseConfig.Ctx, "query component info failed", "error", err)
result := pgClient.WithContext(cancelCtx).Table(tableName).Where("component_id = ?", modelParseConfig.ComponentInfo.ID).Find(&unmarshalMap)
if result.Error != nil {
logger.Error(modelParseConfig.Ctx, "query component detail info failed", "error", result.Error)
return
} else if result.RowsAffected == 0 {
logger.Error(modelParseConfig.Ctx, "query component detail info from table is empty", "table_name", tableName)
return return
} }
var anchorName string diagram.StoreAnchorValue(modelParseConfig.ComponentInfo.GlobalUUID.String(), "")
if anchoringV := unmarshalMap["anchor_v"].(bool); anchoringV {
anchorName = "voltage"
} else {
anchorName = "current"
}
diagram.StoreAnchorValue(modelParseConfig.ComponentInfo.ID, anchorName)
GetComponentChan(modelParseConfig.Ctx, modelParseConfig.ComponentInfo.ID) GetAnchorParamChan(modelParseConfig.Ctx, modelParseConfig.ComponentInfo.GlobalUUID.String())
uuid := modelParseConfig.ComponentInfo.GlobalUUID.String() diagram.StoreComponentMap(modelParseConfig.ComponentInfo.GlobalUUID.String(), &component)
unmarshalMap["id"] = modelParseConfig.ComponentInfo.ID
unmarshalMap["uuid"] = uuid
unmarshalMap["uuid"] = modelParseConfig.ComponentInfo.Tag
unmarshalMap["grid_id"] = modelParseConfig.ComponentInfo.GridID
unmarshalMap["zone_id"] = modelParseConfig.ComponentInfo.ZoneID
unmarshalMap["station_id"] = modelParseConfig.ComponentInfo.StationID
unmarshalMap["component_type"] = modelParseConfig.ComponentInfo.ComponentType
unmarshalMap["name"] = modelParseConfig.ComponentInfo.Name
unmarshalMap["context"] = modelParseConfig.ComponentInfo.Context
unmarshalMap["op"] = modelParseConfig.ComponentInfo.Op
unmarshalMap["ts"] = modelParseConfig.ComponentInfo.Ts
diagram.StoreComponentMap(modelParseConfig.ComponentInfo.ID, unmarshalMap)
return return
} }

View File

@ -26,17 +26,16 @@ func ReceiveChan(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
case realTimeData := <-RealTimeDataChan: case realTimeData := <-RealTimeDataChan:
// TODO 根据 componentID 缓存到来的实时数据 componentUUID := realTimeData.PayLoad.ComponentUUID
componentID := realTimeData.PayLoad.ComponentID component, err := diagram.GetComponentMap(componentUUID)
component, err := diagram.GetComponentMap(componentID)
if err != nil { if err != nil {
logger.Error(ctx, "query component info from diagram map by componet id failed", "component_id", componentID, "error", err) logger.Error(ctx, "query component info from diagram map by componet id failed", "component_uuid", componentUUID, "error", err)
continue continue
} }
componentType := component["component_type"].(int) componentType := component.Type
if componentType != constants.DemoType { if componentType != constants.DemoType {
logger.Error(ctx, "can not process real time data of component type not equal DemoType", "component_id", componentID) logger.Error(ctx, "can not process real time data of component type not equal DemoType", "component_uuid", componentUUID)
continue continue
} }
@ -44,21 +43,8 @@ func ReceiveChan(ctx context.Context) {
var compareValUpperLimit, compareValLowerLimit float64 var compareValUpperLimit, compareValLowerLimit float64
var anchorRealTimeData []float64 var anchorRealTimeData []float64
var calculateFunc func(archorValue float64, args ...float64) float64 var calculateFunc func(archorValue float64, args ...float64) float64
if anchoringV := component["anchor_v"].(bool); anchoringV {
anchorName = "voltage"
compareValUpperLimit = component["uv_alarm"].(float64)
compareValLowerLimit = component["ov_alarm"].(float64)
} else {
anchorName = "current"
compareValUpperLimit = component["ui_alarm"].(float64)
compareValLowerLimit = component["oi_alarm"].(float64)
}
componentData := map[string]interface{}{ // calculateFunc, params := config.SelectAnchorCalculateFuncAndParams(componentType, anchorName, componentData)
"resistance": component["resistance"].(float64),
}
calculateFunc, params := config.SelectAnchorCalculateFuncAndParams(componentType, anchorName, componentData)
for _, param := range realTimeData.PayLoad.Values { for _, param := range realTimeData.PayLoad.Values {
anchorRealTimeData = append(anchorRealTimeData, param.Value) anchorRealTimeData = append(anchorRealTimeData, param.Value)
@ -66,16 +52,21 @@ func ReceiveChan(ctx context.Context) {
anchorConfig := config.AnchorParamConfig{ anchorConfig := config.AnchorParamConfig{
AnchorParamBaseConfig: config.AnchorParamBaseConfig{ AnchorParamBaseConfig: config.AnchorParamBaseConfig{
ComponentID: componentID, ComponentUUID: componentUUID,
AnchorName: anchorName, AnchorName: anchorName,
CompareValUpperLimit: compareValUpperLimit, CompareValUpperLimit: compareValUpperLimit,
CompareValLowerLimit: compareValLowerLimit, CompareValLowerLimit: compareValLowerLimit,
AnchorRealTimeData: anchorRealTimeData, AnchorRealTimeData: anchorRealTimeData,
}, },
CalculateFunc: calculateFunc, CalculateFunc: calculateFunc,
CalculateParams: params, CalculateParams: []float64{},
} }
pool.GetComponentChan(ctx, componentID) <- anchorConfig anchorChan, err := pool.GetAnchorParamChan(ctx, componentUUID)
if err != nil {
logger.Error(ctx, "get anchor param chan failed", "component_uuid", componentUUID, "error", err)
continue
}
anchorChan <- anchorConfig
default: default:
} }
} }

View File

@ -63,7 +63,6 @@ func WriteComponentInShareMemory(key uintptr, componentInfo *orm.Component) erro
obj := (*orm.Component)(unsafe.Pointer(shmAddr + unsafe.Sizeof(structSize))) obj := (*orm.Component)(unsafe.Pointer(shmAddr + unsafe.Sizeof(structSize)))
fmt.Println(obj) fmt.Println(obj)
obj.ComponentType = componentInfo.ComponentType
// id integer NOT NULL DEFAULT nextval('component_id_seq'::regclass), // id integer NOT NULL DEFAULT nextval('component_id_seq'::regclass),
// global_uuid uuid NOT NULL DEFAULT gen_random_uuid(), // global_uuid uuid NOT NULL DEFAULT gen_random_uuid(),

View File

@ -0,0 +1,178 @@
package handler_test
// TODO 使用 mock测试 handler
// 一、安装 GoMock
// 首先需要安装 GoMock 和 mockgen 工具:
// bash
// 复制
// # 安装 GoMock 包
// go get github.com/golang/mock/gomock
// # 安装 mockgen 工具
// go install github.com/golang/mock/mockgen@latest
// 二、基本使用步骤
// 1. 定义接口
// 假设我们有一个简单的接口:
// go
// 复制
// // greeter.go
// package main
// type Greeter interface {
// Greet(name string) string
// }
// 2. 生成 mock 代码
// 使用 mockgen 为接口生成 mock 实现:
// bash
// 复制
// mockgen -source=greeter.go -destination=mock_greeter.go -package=main
// 这会生成一个 mock_greeter.go 文件,包含 MockGreeter 结构体。
// 3. 编写测试代码
// go
// 复制
// // greeter_test.go
// package main
// import (
// "testing"
// "github.com/golang/mock/gomock"
// )
// func TestGreet(t *testing.T) {
// // 创建控制器
// ctrl := gomock.NewController(t)
// defer ctrl.Finish() // 断言所有期望都被满足
// // 创建 mock 对象
// mockGreeter := NewMockGreeter(ctrl)
// // 设置期望
// mockGreeter.EXPECT().
// Greet("Alice").
// Return("Hello, Alice!").
// Times(1)
// // 使用 mock 对象
// result := mockGreeter.Greet("Alice")
// // 验证结果
// if result != "Hello, Alice!" {
// t.Errorf("Expected 'Hello, Alice!', got '%s'", result)
// }
// }
// 三、高级功能
// 1. 参数匹配
// GoMock 提供了多种参数匹配方式:
// go
// 复制
// // 精确匹配
// mockGreeter.EXPECT().Greet("Alice")
// // 任意值匹配
// mockGreeter.EXPECT().Greet(gomock.Any())
// // 自定义匹配
// mockGreeter.EXPECT().Greet(gomock.AssignableToTypeOf("")).DoAndReturn(
// func(name string) string {
// return "Hello, " + name + "!"
// },
// )
// 2. 调用次数控制
// go
// 复制
// // 精确调用次数
// mockGreeter.EXPECT().Greet("Alice").Times(3)
// // 至少调用一次
// mockGreeter.EXPECT().Greet("Alice").MinTimes(1)
// // 最多调用一次
// mockGreeter.EXPECT().Greet("Alice").MaxTimes(1)
// // 任意次数(0或多次)
// mockGreeter.EXPECT().Greet("Alice").AnyTimes()
// 3. 调用顺序控制
// go
// 复制
// gomock.InOrder(
// mockGreeter.EXPECT().Greet("Alice"),
// mockGreeter.EXPECT().Greet("Bob"),
// )
// 4. 模拟副作用
// go
// 复制
// // 使用 Do
// mockGreeter.EXPECT().Greet("Alice").Do(func(name string) {
// t.Logf("Greet was called with %s", name)
// })
// // 使用 DoAndReturn
// mockGreeter.EXPECT().Greet("Alice").DoAndReturn(
// func(name string) string {
// return "Hi, " + name + "!"
// },
// )
// 四、实际应用示例
// 假设我们有一个服务依赖 Greeter 接口:
// go
// 复制
// // greeter_service.go
// package main
// type GreeterService struct {
// greeter Greeter
// }
// func (s *GreeterService) WelcomePeople(names []string) []string {
// var greetings []string
// for _, name := range names {
// greetings = append(greetings, s.greeter.Greet(name))
// }
// return greetings
// }
// 对应的测试:
// go
// 复制
// // greeter_service_test.go
// package main
// import (
// "testing"
// "github.com/golang/mock/gomock"
// )
// func TestWelcomePeople(t *testing.T) {
// ctrl := gomock.NewController(t)
// defer ctrl.Finish()
// mockGreeter := NewMockGreeter(ctrl)
// service := &GreeterService{greeter: mockGreeter}
// // 设置期望
// mockGreeter.EXPECT().Greet("Alice").Return("Hello, Alice!")
// mockGreeter.EXPECT().Greet("Bob").Return("Hello, Bob!")
// // 测试
// result := service.WelcomePeople([]string{"Alice", "Bob"})
// // 验证
// expected := []string{"Hello, Alice!", "Hello, Bob!"}
// if len(result) != len(expected) {
// t.Fatalf("Expected %d greetings, got %d", len(expected), len(result))
// }
// for i := range expected {
// if result[i] != expected[i] {
// t.Errorf("At index %d: expected %q, got %q", i, expected[i], result[i])
// }
// }
// }