267 lines
5.7 KiB
Go
267 lines
5.7 KiB
Go
// Package util provide some utility fun
|
|
package util
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"modelRT/orm"
|
|
)
|
|
|
|
type CalculationResult struct {
|
|
BaseValue float64
|
|
Changes []float64
|
|
Size int
|
|
BaseType string // "normal", "warning", "edge"
|
|
Message string
|
|
}
|
|
|
|
func ProcessMeasurements(measurements []orm.Measurement) map[string]CalculationResult {
|
|
results := make(map[string]CalculationResult, len(measurements))
|
|
for _, measurement := range measurements {
|
|
// 检查 DataSource 是否存在且 type 为 1
|
|
if measurement.DataSource == nil {
|
|
continue
|
|
}
|
|
|
|
// 检查 type 是否为 1
|
|
dataType, typeExists := measurement.DataSource["type"]
|
|
if !typeExists {
|
|
continue
|
|
}
|
|
|
|
// 类型断言,处理不同的数字类型
|
|
var typeValue int
|
|
switch v := dataType.(type) {
|
|
case int:
|
|
typeValue = v
|
|
case float64:
|
|
typeValue = int(v)
|
|
case int64:
|
|
typeValue = int(v)
|
|
default:
|
|
continue
|
|
}
|
|
|
|
if typeValue != 1 {
|
|
continue
|
|
}
|
|
|
|
// 获取 io_address
|
|
ioAddressRaw, ioExists := measurement.DataSource["io_address"]
|
|
if !ioExists {
|
|
continue
|
|
}
|
|
|
|
ioAddress, ok := ioAddressRaw.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
station, _ := ioAddress["station"].(string)
|
|
device, _ := ioAddress["device"].(string)
|
|
channel, _ := ioAddress["channel"].(string)
|
|
|
|
result := fmt.Sprintf("%s:%s:phasor:%s", station, device, channel)
|
|
if measurement.EventPlan == nil {
|
|
continue
|
|
}
|
|
|
|
causeValue, causeExist := measurement.EventPlan["cause"]
|
|
if !causeExist {
|
|
continue
|
|
}
|
|
causeMap, ok := causeValue.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
calResult, err := calculateBaseValueEnhanced(causeMap)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
calResult.Size = measurement.Size
|
|
results[result] = calResult
|
|
}
|
|
return results
|
|
}
|
|
|
|
func calculateBaseValueEnhanced(data map[string]any) (CalculationResult, error) {
|
|
result := CalculationResult{}
|
|
if edge, exists := data["edge"]; exists {
|
|
value, err := calculateEdgeValue(edge)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
if edge == "raising" {
|
|
result.Changes = []float64{1.0}
|
|
} else {
|
|
result.Changes = []float64{0.0}
|
|
}
|
|
|
|
result.BaseValue = value
|
|
result.BaseType = "TI"
|
|
result.Message = "边沿触发基准值"
|
|
return result, nil
|
|
}
|
|
|
|
hasUpDown := HasKeys(data, "up", "down")
|
|
hasUpUpDownDown := HasKeys(data, "upup", "downdown")
|
|
result.BaseType = "TE"
|
|
switch {
|
|
case hasUpDown && hasUpUpDownDown:
|
|
value, err := calculateAverage(data, "up", "down")
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
result.BaseValue = value
|
|
result.Changes, err = calculateChanges(data, value, false, 4)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
result.Message = "上下限基准值(忽略预警上上下下限)"
|
|
return result, nil
|
|
|
|
case hasUpDown:
|
|
value, err := calculateAverage(data, "up", "down")
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
result.BaseValue = value
|
|
result.Changes, err = calculateChanges(data, value, false, 2)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
result.Message = "上下限基准值"
|
|
return result, nil
|
|
|
|
case hasUpUpDownDown:
|
|
value, err := calculateAverage(data, "upup", "downdown")
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
result.BaseValue = value
|
|
result.Changes, err = calculateChanges(data, value, true, 2)
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
result.Message = "上上下下限基准值"
|
|
return result, nil
|
|
|
|
default:
|
|
return result, fmt.Errorf("不支持的数据结构: %v", data)
|
|
}
|
|
}
|
|
|
|
func calculateAverage(data map[string]any, key1, key2 string) (float64, error) {
|
|
val1, err := getFloatValue(data, key1)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
val2, err := getFloatValue(data, key2)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return (val1 + val2) / 2.0, nil
|
|
}
|
|
|
|
func calculateChanges(data map[string]any, baseValue float64, maxLimt bool, limitNum int) ([]float64, error) {
|
|
results := make([]float64, 0, limitNum)
|
|
switch limitNum {
|
|
case 2:
|
|
var key1, key2 string
|
|
if maxLimt {
|
|
key1 = "upup"
|
|
key2 = "downdown"
|
|
} else {
|
|
key1 = "up"
|
|
key2 = "down"
|
|
}
|
|
val1, err := getFloatValue(data, key1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, val1-baseValue)
|
|
|
|
val2, err := getFloatValue(data, key2)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, val2-baseValue)
|
|
case 4:
|
|
key1 := "up"
|
|
key2 := "down"
|
|
key3 := "upup"
|
|
key4 := "downdown"
|
|
|
|
val1, err := getFloatValue(data, key1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, val1-baseValue)
|
|
|
|
val2, err := getFloatValue(data, key2)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, val2-baseValue)
|
|
|
|
val3, err := getFloatValue(data, key3)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, val3-baseValue)
|
|
|
|
val4, err := getFloatValue(data, key4)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, val4-baseValue)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
func getFloatValue(data map[string]any, key string) (float64, error) {
|
|
value, exists := data[key]
|
|
if !exists {
|
|
return 0, fmt.Errorf("缺少必需的键:%s", key)
|
|
}
|
|
|
|
switch v := value.(type) {
|
|
case float64:
|
|
return v, nil
|
|
case int:
|
|
return float64(v), nil
|
|
case float32:
|
|
return float64(v), nil
|
|
default:
|
|
return 0, fmt.Errorf("键 %s 的值类型错误,期望数字类型,得到 %T", key, value)
|
|
}
|
|
}
|
|
|
|
func HasKeys(data map[string]any, keys ...string) bool {
|
|
for _, key := range keys {
|
|
if _, exists := data[key]; !exists {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func calculateEdgeValue(edge any) (float64, error) {
|
|
edgeStr, ok := edge.(string)
|
|
if !ok {
|
|
return 0, fmt.Errorf("edge 字段类型错误,期望 string,得到 %T", edge)
|
|
}
|
|
|
|
switch edgeStr {
|
|
case "raising":
|
|
return 1.0, nil
|
|
case "falling":
|
|
return 0.0, nil
|
|
default:
|
|
return 0, fmt.Errorf("不支持的 edge 值: %s", edgeStr)
|
|
}
|
|
}
|