// 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.Debug(). Str("provider", p.Name()). Any("update", update). Msg("successfully handled update") w.Write([]byte("ok")) }