write code for polling real time data from dataRT service
This commit is contained in:
parent
39e380ee1e
commit
5a9fa5cc4d
|
|
@ -9,47 +9,51 @@ import (
|
||||||
type AnchorParamListConfig struct {
|
type AnchorParamListConfig struct {
|
||||||
AnchorName string
|
AnchorName string
|
||||||
FuncType string // 函数类型
|
FuncType string // 函数类型
|
||||||
UpperLimit float32 // 比较值上限
|
UpperLimit float64 // 比较值上限
|
||||||
LowerLimit float32 // 比较值下限
|
LowerLimit float64 // 比较值下限
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnchorParamBaseConfig define anchor params base config struct
|
// AnchorParamBaseConfig define anchor params base config struct
|
||||||
type AnchorParamBaseConfig struct {
|
type AnchorParamBaseConfig struct {
|
||||||
UUID string
|
StationID string // component表 station_id
|
||||||
|
ComponentID string // component表 ID
|
||||||
|
UUID string // component表 global_uuid
|
||||||
AnchorName string // 锚定参量名称
|
AnchorName string // 锚定参量名称
|
||||||
CompareValUpperLimit float32 // 比较值上限
|
CompareValUpperLimit float64 // 比较值上限
|
||||||
CompareValLowerLimit float32 // 比较值下限
|
CompareValLowerLimit float64 // 比较值下限
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnchorParamConfig define anchor params config struct
|
// AnchorParamConfig define anchor params config struct
|
||||||
type AnchorParamConfig struct {
|
type AnchorParamConfig struct {
|
||||||
AnchorParamBaseConfig
|
AnchorParamBaseConfig
|
||||||
CalculateFunc func(archorValue float32, args ...float32) float32 // 计算函数
|
CalculateFunc func(archorValue float64, args ...float64) float64 // 计算函数
|
||||||
CalculateParams []float32 // 计算参数
|
CalculateParams []float64 // 计算参数
|
||||||
|
APIURL string // API URL
|
||||||
|
APIMethod string // API Method
|
||||||
}
|
}
|
||||||
|
|
||||||
var baseVoltageFunc = func(archorValue float32, args ...float32) float32 {
|
var baseVoltageFunc = func(archorValue float64, args ...float64) float64 {
|
||||||
voltage := archorValue
|
voltage := archorValue
|
||||||
resistance := args[1]
|
resistance := args[1]
|
||||||
return voltage / resistance
|
return voltage / resistance
|
||||||
}
|
}
|
||||||
|
|
||||||
var baseCurrentFunc = func(archorValue float32, args ...float32) float32 {
|
var baseCurrentFunc = func(archorValue float64, args ...float64) float64 {
|
||||||
current := archorValue
|
current := archorValue
|
||||||
resistance := args[1]
|
resistance := args[1]
|
||||||
return current * resistance
|
return current * resistance
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectAnchorCalculateFuncAndParams define select anchor func and anchor calculate value by component type 、 anchor name and component data
|
// SelectAnchorCalculateFuncAndParams define select anchor func and anchor calculate value by component type 、 anchor name and component data
|
||||||
func SelectAnchorCalculateFuncAndParams(componentType int, anchorName string, componentData map[string]interface{}) (func(archorValue float32, args ...float32) float32, []float32) {
|
func SelectAnchorCalculateFuncAndParams(componentType int, anchorName string, componentData map[string]interface{}) (func(archorValue float64, args ...float64) float64, []float64) {
|
||||||
if componentType == constant.DemoType {
|
if componentType == constant.DemoType {
|
||||||
if anchorName == "voltage" {
|
if anchorName == "voltage" {
|
||||||
resistance := componentData["resistance"].(float32)
|
resistance := componentData["resistance"].(float64)
|
||||||
return baseVoltageFunc, []float32{resistance}
|
return baseVoltageFunc, []float64{resistance}
|
||||||
} else if anchorName == "current" {
|
} else if anchorName == "current" {
|
||||||
resistance := componentData["resistance"].(float32)
|
resistance := componentData["resistance"].(float64)
|
||||||
return baseCurrentFunc, []float32{resistance}
|
return baseCurrentFunc, []float64{resistance}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, []float32{}
|
return nil, []float64{}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,16 @@ type LoggerConfig struct {
|
||||||
|
|
||||||
// AntsConfig define config stuct of ants pool config
|
// AntsConfig define config stuct of ants pool config
|
||||||
type AntsConfig struct {
|
type AntsConfig struct {
|
||||||
ParseConcurrentQuantity int `mapstructure:"parse_concurrent_quantity"` // parse comtrade file concurrent quantity
|
ParseConcurrentQuantity int `mapstructure:"parse_concurrent_quantity"` // parse comtrade file concurrent quantity
|
||||||
|
PollingConcurrentQuantity int `mapstructure:"polling_concurrent_quantity"` // polling real time data concurrent quantity
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataRTConfig define config stuct of data runtime server api config
|
||||||
|
type DataRTConfig struct {
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
Port int64 `mapstructure:"port"`
|
||||||
|
PollingAPI string `mapstructure:"polling_api"`
|
||||||
|
Method string `mapstructure:"polling_api_method"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModelRTConfig define config stuct of model runtime server
|
// ModelRTConfig define config stuct of model runtime server
|
||||||
|
|
@ -55,6 +64,7 @@ type ModelRTConfig struct {
|
||||||
KafkaConfig `mapstructure:"kafka"`
|
KafkaConfig `mapstructure:"kafka"`
|
||||||
LoggerConfig `mapstructure:"logger"`
|
LoggerConfig `mapstructure:"logger"`
|
||||||
AntsConfig `mapstructure:"ants"`
|
AntsConfig `mapstructure:"ants"`
|
||||||
|
DataRTConfig `mapstructure:"dataRT"`
|
||||||
PostgresDBURI string `mapstructure:"-"`
|
PostgresDBURI string `mapstructure:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,12 +81,12 @@ func ReadAndInitConfig(configDir, configName, configType string) (modelRTConfig
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rtConfig := ModelRTConfig{}
|
modelRTconf := ModelRTConfig{}
|
||||||
if err := config.Unmarshal(&rtConfig); err != nil {
|
if err := config.Unmarshal(&modelRTConfig); err != nil {
|
||||||
panic(fmt.Sprintf("unmarshal modelRT config failed:%s\n", err.Error()))
|
panic(fmt.Sprintf("unmarshal modelRT config failed:%s\n", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
modelRTConfig.PostgresDBURI = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", rtConfig.Host, rtConfig.Port, rtConfig.User, rtConfig.Password, rtConfig.DataBase)
|
modelRTConfig.PostgresDBURI = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", modelRTconf.PostgresConfig.Host, modelRTconf.PostgresConfig.Port, modelRTconf.PostgresConfig.User, modelRTconf.PostgresConfig.Password, modelRTconf.PostgresConfig.DataBase)
|
||||||
|
|
||||||
return modelRTConfig
|
return modelRTConfig
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,17 @@ logger:
|
||||||
# ants config
|
# ants config
|
||||||
ants:
|
ants:
|
||||||
parse_concurrent_quantity: 10
|
parse_concurrent_quantity: 10
|
||||||
|
polling_concurrent_quantity: 10
|
||||||
|
|
||||||
# modelRT base config
|
# modelRT base config
|
||||||
base:
|
base:
|
||||||
grid_id: 1
|
grid_id: 1
|
||||||
zone_id: 1
|
zone_id: 1
|
||||||
station_id: 1
|
station_id: 1
|
||||||
|
|
||||||
|
# dataRT api config
|
||||||
|
dataRT:
|
||||||
|
host: "http://127.0.0.1"
|
||||||
|
port: 8888
|
||||||
|
polling_api: "datart/getPointData"
|
||||||
|
polling_api_method: "GET"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"modelRT/config"
|
"modelRT/config"
|
||||||
|
|
@ -139,10 +140,12 @@ func ComponentAnchorReplaceHandler(c *gin.Context) {
|
||||||
|
|
||||||
anchorParam := config.AnchorParamConfig{
|
anchorParam := config.AnchorParamConfig{
|
||||||
AnchorParamBaseConfig: config.AnchorParamBaseConfig{
|
AnchorParamBaseConfig: config.AnchorParamBaseConfig{
|
||||||
|
StationID: strconv.FormatInt(componentInfo.StationID, 10),
|
||||||
|
ComponentID: strconv.FormatInt(componentInfo.ID, 10),
|
||||||
UUID: uuid,
|
UUID: uuid,
|
||||||
AnchorName: anchorName,
|
AnchorName: anchorName,
|
||||||
CompareValUpperLimit: float32(anchorConfigsJSON.Get("params_list").GetIndex(anchorIndex).Get("upper_limit").MustFloat64()),
|
CompareValUpperLimit: anchorConfigsJSON.Get("params_list").GetIndex(anchorIndex).Get("upper_limit").MustFloat64(),
|
||||||
CompareValLowerLimit: float32(anchorConfigsJSON.Get("params_list").GetIndex(anchorIndex).Get("lower_limit").MustFloat64()),
|
CompareValLowerLimit: anchorConfigsJSON.Get("params_list").GetIndex(anchorIndex).Get("lower_limit").MustFloat64(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
anchorParam.CalculateFunc, anchorParam.CalculateParams = config.SelectAnchorCalculateFuncAndParams(componentInfo.ComponentType, anchorName, unmarshalMap)
|
anchorParam.CalculateFunc, anchorParam.CalculateParams = config.SelectAnchorCalculateFuncAndParams(componentInfo.ComponentType, anchorName, unmarshalMap)
|
||||||
|
|
|
||||||
3
main.go
3
main.go
|
|
@ -72,8 +72,7 @@ func main() {
|
||||||
defer parsePool.Release()
|
defer parsePool.Release()
|
||||||
|
|
||||||
// init data polling ants pool
|
// init data polling ants pool
|
||||||
// TODO 优化轮询池初始化参数定义方式,改为从 config 中获取
|
pollingPool, err := ants.NewPoolWithFunc(modelRTConfig.PollingConcurrentQuantity, pool.AnchorFunc)
|
||||||
pollingPool, err := ants.NewPoolWithFunc(1000, pool.AnchorFunc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zapLogger.Error("init concurrent data polling task pool failed", zap.Error(err))
|
zapLogger.Error("init concurrent data polling task pool failed", zap.Error(err))
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"modelRT/logger"
|
"github.com/bitly/go-simplejson"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIEndpoint defines an api endpoint struct to poll data from dataRT service
|
// APIEndpoint defines an api endpoint struct to poll data from dataRT service
|
||||||
|
|
@ -61,18 +58,27 @@ func fetchAPI(endpoint APIEndpoint) (string, error) {
|
||||||
return string(body), nil
|
return string(body), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// pollAPIEndpoints defines unmarshal polling data from http request
|
// PollAPIEndpoints defines unmarshal polling data from http request
|
||||||
func pollAPIEndpoints(endpoint APIEndpoint) {
|
func PollAPIEndpoints(endpoint APIEndpoint) ([]float64, error) {
|
||||||
logger := logger.GetLoggerInstance()
|
var valueSlice []float64
|
||||||
|
|
||||||
respStr, err := fetchAPI(endpoint)
|
respStr, err := fetchAPI(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("unmarshal component anchor point replace info failed", zap.Error(err))
|
return valueSlice, fmt.Errorf("fetch api failed:%w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
fmt.Println(respStr)
|
realDataJSON, err := simplejson.NewJson([]byte(respStr))
|
||||||
time.Sleep(time.Duration(endpoint.Interval) * time.Second)
|
if err != nil {
|
||||||
// 注意:这里使用了 endpoint.Interval 而不是传入的 interval,
|
return valueSlice, fmt.Errorf("format real time data failed:%w", err)
|
||||||
// 但为了示例简单,我们统一使用传入的 interval。
|
}
|
||||||
// 如果要根据每个端点的不同间隔来轮询,应该使用 endpoint.Interval。
|
simplejson.New().UnmarshalJSON([]byte(respStr))
|
||||||
|
code := realDataJSON.Get("code").MustInt()
|
||||||
|
if code != 0 {
|
||||||
|
return valueSlice, fmt.Errorf("polling data api status error:%s", realDataJSON.Get("msg").MustString())
|
||||||
|
}
|
||||||
|
|
||||||
|
dataLen := len(realDataJSON.Get("data").MustArray())
|
||||||
|
for i := 0; i < dataLen; i++ {
|
||||||
|
valueSlice = append(valueSlice, realDataJSON.Get("data").GetIndex(i).Get("value").MustFloat64())
|
||||||
|
}
|
||||||
|
return valueSlice, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,41 +3,84 @@ package pool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"modelRT/config"
|
"modelRT/config"
|
||||||
"modelRT/diagram"
|
"modelRT/diagram"
|
||||||
|
"modelRT/logger"
|
||||||
|
"modelRT/network"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AnchorFunc = func(anchorConfig interface{}) {
|
var AnchorFunc = func(anchorConfig interface{}) {
|
||||||
logger := zap.L()
|
logger := logger.GetLoggerInstance()
|
||||||
|
var firstTimePolling bool
|
||||||
|
|
||||||
paramConfig, ok := anchorConfig.(config.AnchorParamConfig)
|
paramConfig, ok := anchorConfig.(config.AnchorParamConfig)
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Error("conversion model anchor param config type failed")
|
logger.Error("conversion model anchor param config type failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
calculateFunc := paramConfig.CalculateFunc
|
|
||||||
for {
|
for {
|
||||||
// TODO 通过 api 循环获取 vlaue 实时值
|
var beginUnixTime, endUnixTime int64
|
||||||
var value float32
|
if firstTimePolling {
|
||||||
anchorName, err := diagram.GetAnchorValue(paramConfig.UUID)
|
milliUnixTime := time.Now().UnixMilli()
|
||||||
|
endUnixTime = milliUnixTime
|
||||||
|
beginUnixTime = milliUnixTime - 1000*60
|
||||||
|
firstTimePolling = false
|
||||||
|
} else {
|
||||||
|
// 判断时间差值是否小于10s,如果小于则重新获取时间
|
||||||
|
endUnixTime = time.Now().UnixMilli()
|
||||||
|
if endUnixTime-beginUnixTime < 1000*10 {
|
||||||
|
time.Sleep(time.Duration(1 * time.Second))
|
||||||
|
endUnixTime = time.Now().UnixMilli()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pollingAPI := network.APIEndpoint{
|
||||||
|
URL: paramConfig.APIURL,
|
||||||
|
Method: paramConfig.APIMethod,
|
||||||
|
QueryParams: map[string]string{
|
||||||
|
"station": paramConfig.StationID,
|
||||||
|
"component": paramConfig.ComponentID,
|
||||||
|
"point": paramConfig.AnchorName,
|
||||||
|
"begin": strconv.FormatInt(beginUnixTime, 10),
|
||||||
|
"end": strconv.FormatInt(endUnixTime, 10),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !firstTimePolling {
|
||||||
|
beginUnixTime = time.Now().UnixMilli()
|
||||||
|
}
|
||||||
|
|
||||||
|
valueSlice, err := network.PollAPIEndpoints(pollingAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("can not get anchor value from map by uuid", zap.String("uuid", paramConfig.UUID), zap.Error(err))
|
logger.Error("polling real time data from dataRT service failed", zap.Error(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if anchorName != paramConfig.AnchorName {
|
for _, value := range valueSlice {
|
||||||
logger.Error("anchor name not equal param config anchor value", zap.String("map_anchor_name", anchorName), zap.String("param_anchor_name", paramConfig.AnchorName))
|
anchorName, err := diagram.GetAnchorValue(paramConfig.UUID)
|
||||||
continue
|
if err != nil {
|
||||||
}
|
logger.Error("can not get anchor value from map by uuid", zap.String("uuid", paramConfig.UUID), zap.Error(err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
upperLimitVal := paramConfig.CompareValUpperLimit
|
if anchorName != paramConfig.AnchorName {
|
||||||
lowerlimitVal := paramConfig.CompareValLowerLimit
|
logger.Error("anchor name not equal param config anchor value", zap.String("map_anchor_name", anchorName), zap.String("param_anchor_name", paramConfig.AnchorName))
|
||||||
compareValue := calculateFunc(value, paramConfig.CalculateParams...)
|
continue
|
||||||
if compareValue > upperLimitVal || compareValue < lowerlimitVal {
|
}
|
||||||
fmt.Println("log warning")
|
|
||||||
|
upperLimitVal := paramConfig.CompareValUpperLimit
|
||||||
|
lowerlimitVal := paramConfig.CompareValLowerLimit
|
||||||
|
compareValue := paramConfig.CalculateFunc(value, paramConfig.CalculateParams...)
|
||||||
|
if compareValue > upperLimitVal || compareValue < lowerlimitVal {
|
||||||
|
// TODO 选择报警方式
|
||||||
|
fmt.Println("log warning")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,13 @@ package pool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"modelRT/config"
|
"modelRT/config"
|
||||||
"modelRT/database"
|
"modelRT/database"
|
||||||
"modelRT/diagram"
|
"modelRT/diagram"
|
||||||
|
"modelRT/logger"
|
||||||
"modelRT/model"
|
"modelRT/model"
|
||||||
realtimedata "modelRT/real-time-data"
|
realtimedata "modelRT/real-time-data"
|
||||||
|
|
||||||
|
|
@ -15,8 +17,9 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ParseFunc defines func that parses the model data from postgres
|
||||||
var ParseFunc = func(parseConfig interface{}) {
|
var ParseFunc = func(parseConfig interface{}) {
|
||||||
logger := zap.L()
|
logger := logger.GetLoggerInstance()
|
||||||
|
|
||||||
modelParseConfig, ok := parseConfig.(config.ModelParseConfig)
|
modelParseConfig, ok := parseConfig.(config.ModelParseConfig)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -56,10 +59,12 @@ var ParseFunc = func(parseConfig interface{}) {
|
||||||
|
|
||||||
anchorParam := config.AnchorParamConfig{
|
anchorParam := config.AnchorParamConfig{
|
||||||
AnchorParamBaseConfig: config.AnchorParamBaseConfig{
|
AnchorParamBaseConfig: config.AnchorParamBaseConfig{
|
||||||
|
StationID: strconv.FormatInt(modelParseConfig.ComponentInfo.StationID, 10),
|
||||||
|
ComponentID: strconv.FormatInt(modelParseConfig.ComponentInfo.ID, 10),
|
||||||
UUID: uuid,
|
UUID: uuid,
|
||||||
AnchorName: anchorName,
|
AnchorName: anchorName,
|
||||||
CompareValUpperLimit: float32(anchorConfigsJSON.Get("params_list").GetIndex(index).Get("upper_limit").MustFloat64()),
|
CompareValUpperLimit: anchorConfigsJSON.Get("params_list").GetIndex(index).Get("upper_limit").MustFloat64(),
|
||||||
CompareValLowerLimit: float32(anchorConfigsJSON.Get("params_list").GetIndex(index).Get("lower_limit").MustFloat64()),
|
CompareValLowerLimit: anchorConfigsJSON.Get("params_list").GetIndex(index).Get("lower_limit").MustFloat64(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
anchorParam.CalculateFunc, anchorParam.CalculateParams = config.SelectAnchorCalculateFuncAndParams(modelParseConfig.ComponentInfo.ComponentType, anchorName, unmarshalMap)
|
anchorParam.CalculateFunc, anchorParam.CalculateParams = config.SelectAnchorCalculateFuncAndParams(modelParseConfig.ComponentInfo.ComponentType, anchorName, unmarshalMap)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue