package collector import ( "bee/audit/internal/schema" "strconv" "strings" ) func enrichPSUsWithTelemetry(psus []schema.HardwarePowerSupply, doc sensorsDoc) []schema.HardwarePowerSupply { if len(psus) == 0 || len(doc) == 0 { return psus } tempBySlot := psuTempsFromSensors(doc) healthBySlot := psuHealthFromSensors(doc) for i := range psus { slot := derefPSUSlot(psus[i].Slot) if slot == "" { continue } if psus[i].TemperatureC == nil { if value, ok := tempBySlot[slot]; ok { psus[i].TemperatureC = &value } } if psus[i].LifeRemainingPct == nil { if value, ok := healthBySlot[slot]; ok { psus[i].LifeRemainingPct = &value used := 100 - value psus[i].LifeUsedPct = &used } } } return psus } func psuHealthFromSensors(doc sensorsDoc) map[string]float64 { out := map[string]float64{} for chip, features := range doc { for featureName, raw := range features { feature, ok := raw.(map[string]any) if !ok { continue } if !isLikelyPSUHealth(chip, featureName) { continue } value, ok := firstFeaturePercent(feature) if !ok { continue } if slot, ok := detectPSUSlot(chip, featureName); ok { if _, exists := out[slot]; !exists { out[slot] = value } } } } return out } func firstFeaturePercent(feature map[string]any) (float64, bool) { keys := sortedFeatureKeys(feature) for _, key := range keys { lower := strings.ToLower(key) if strings.HasSuffix(lower, "_alarm") { continue } if strings.Contains(lower, "health") || strings.Contains(lower, "life") || strings.Contains(lower, "remain") { if value, ok := floatFromAny(feature[key]); ok { return value, true } } } return 0, false } func isLikelyPSUHealth(chip, feature string) bool { value := strings.ToLower(chip + " " + feature) return (strings.Contains(value, "psu") || strings.Contains(value, "power supply")) && (strings.Contains(value, "health") || strings.Contains(value, "life") || strings.Contains(value, "remain")) } func psuTempsFromSensors(doc sensorsDoc) map[string]float64 { out := map[string]float64{} for chip, features := range doc { for featureName, raw := range features { feature, ok := raw.(map[string]any) if !ok || classifySensorFeature(feature) != "temp" { continue } if !isLikelyPSUTemp(chip, featureName) { continue } temp, ok := firstFeatureFloat(feature, "_input") if !ok { continue } if slot, ok := detectPSUSlot(chip, featureName); ok { if _, exists := out[slot]; !exists { out[slot] = temp } } } } return out } func isLikelyPSUTemp(chip, feature string) bool { value := strings.ToLower(chip + " " + feature) return strings.Contains(value, "psu") || strings.Contains(value, "power supply") } func detectPSUSlot(parts ...string) (string, bool) { for _, part := range parts { if value, ok := parsePSUSlot(part); ok && value > 0 { return strconv.Itoa(value - 1), true } } return "", false }