ambient-local-exporter/pkg/ambient/ambient.go

82 lines
2.4 KiB
Go

// This provides a shim between HTTP GET requests sent
// by ambient devices, and the providers that may be
// configured (awn, wunderground)
package ambient
import (
"context"
"fmt"
"net/http"
"gitea.libretechconsulting.com/rmcguire/go-app/pkg/otel"
"github.com/rs/zerolog"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/provider"
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/provider/awn"
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/provider/wunderground"
)
// These providers implement support for the update sent
// when either "AmbientWeather" or "Wunderground" are selected
// in the "Custom" section of the AWNet app, or the web UI
// of an Ambient WeatherHub
var (
awnProvider = &awn.AWNProvider{}
wuProvider = &wunderground.WUProvider{}
)
func GetAWNHandlerFunc(appCtx context.Context) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
handleProviderRequest(appCtx, awnProvider, w, r)
}
}
func GetWundergroundHandlerFunc(appCtx context.Context) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
handleProviderRequest(appCtx, wuProvider, w, r)
}
}
// Takes an HTTP requests and convers it to a
// stable type. Enrich is called on the type to complete
// any missing fields as the two providers supported by Ambient
// devices (awn/wunderground) produce different fields
func handleProviderRequest(
appCtx context.Context,
p provider.AmbientProvider,
w http.ResponseWriter,
r *http.Request,
) {
l := zerolog.Ctx(appCtx)
tracer := otel.GetTracer(appCtx, p.Name()+".http.handler")
ctx, span := tracer.Start(r.Context(), p.Name()+".update")
span.SetAttributes(attribute.String("provider", p.Name()))
defer span.End()
l.Trace().Str("p", p.Name()).
Any("query", r.URL.Query()).Send()
// Convert to WeatherUpdate
update, err := p.ReqToWeather(ctx, r)
if err != nil {
l.Err(err).Send()
span.RecordError(err)
span.SetStatus(codes.Error,
fmt.Sprintf("failed to handle %s update: %s",
p.Name(), err.Error()))
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
}
// Calculate any fields that may be missing
// such as dew point and wind chill
update.Enrich()
l.Trace().Any("update", update).Send()
w.Write([]byte("ok"))
}