Files
go-weatherstation/internal/mqttingest/barometer.go
2026-02-02 16:10:29 +11:00

106 lines
2.0 KiB
Go

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", "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", "altim"); 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
}
}