package mqttingest import ( "encoding/json" "fmt" "strconv" "strings" ) type BarometerPayload struct { PressureHPA float64 } func ParseBarometer(b []byte) (*BarometerPayload, map[string]any, error) { var raw map[string]any if err := json.Unmarshal(b, &raw); err != nil { return nil, nil, err } pressure, ok := pressureHPAFromPayload(raw) if !ok { return nil, raw, fmt.Errorf("barometer payload missing pressure field") } return &BarometerPayload{ PressureHPA: pressure, }, raw, nil } func pressureHPAFromPayload(raw map[string]any) (float64, bool) { if v, ok := findFloat(raw, "pressure_hpa", "pressure_mb", "pressure_mbar", "barometer_hpa", "baro_hpa", "pressure", ); ok { return v, true } if v, ok := findFloat(raw, "pressure_pa"); ok { return v / 100.0, true } if v, ok := findFloat(raw, "pressure_kpa"); ok { return v * 10.0, true } if v, ok := findFloat(raw, "pressure_inhg", "barometer_inhg"); ok { return v * 33.8638866667, true } return 0, false } func findFloat(raw map[string]any, keys ...string) (float64, bool) { for _, key := range keys { v, ok := raw[key] if !ok { continue } if f, ok := asFloat(v); ok { return f, true } } return 0, false } func asFloat(v any) (float64, bool) { switch t := v.(type) { case float64: return t, true case float32: return float64(t), true case int: return float64(t), true case int8: return float64(t), true case int16: return float64(t), true case int32: return float64(t), true case int64: return float64(t), true case uint: return float64(t), true case uint8: return float64(t), true case uint16: return float64(t), true case uint32: return float64(t), true case uint64: return float64(t), true case json.Number: f, err := t.Float64() return f, err == nil case string: s := strings.TrimSpace(t) if s == "" { return 0, false } f, err := strconv.ParseFloat(s, 64) return f, err == nil default: return 0, false } }