Compare commits

...

17 Commits

Author SHA1 Message Date
87f0cbac01 Fix typos, update TODO
All checks were successful
Build and Publish / release (push) Successful in 3m44s
2025-01-07 11:28:34 -05:00
4c93303f27 Consolidate battery metrics 2025-01-07 10:27:02 -05:00
e8654e76bc Update TODO 2025-01-07 08:53:06 -05:00
54f725c822 Update go-app 2025-01-05 20:33:28 -05:00
c002331fd4 Fix NaN with zero values
All checks were successful
Build and Publish / release (push) Successful in 3m7s
2025-01-05 19:05:24 -05:00
2ed4eca56c Add support for co2 battery
All checks were successful
Build and Publish / release (push) Successful in 2m57s
2025-01-05 18:39:58 -05:00
2e3cfb44f4 Don't enrich nil updates
All checks were successful
Build and Publish / release (push) Successful in 2m48s
2025-01-05 17:37:14 -05:00
be8a4f3bca Don't enrich nil updates 2025-01-05 17:36:39 -05:00
96dfcf7e53 Update sample
All checks were successful
Build and Publish / release (push) Successful in 3m58s
2025-01-05 16:24:52 -05:00
5fc16b39af Upgrade go-app 2025-01-05 16:23:15 -05:00
1ae58f64ca Move docker compose sample 2025-01-05 15:16:16 -05:00
bb4e4aa2af Update TODO 2025-01-05 13:19:30 -05:00
f102ef50bf Upgrade to fix env overrides
All checks were successful
Build and Publish / release (push) Successful in 4m7s
2025-01-05 13:13:19 -05:00
d3d251ef30 Update TODO 2025-01-05 11:47:06 -05:00
eecaf2a82e Add latest tag
All checks were successful
Build and Publish / release (push) Successful in 2m44s
2025-01-05 11:44:48 -05:00
f0f6c58f0b Fix versioning
All checks were successful
Build and Publish / release (push) Successful in 3m24s
2025-01-05 11:36:30 -05:00
681c7f703b Add Linux ARM64
Some checks failed
Build and Publish / release (push) Failing after 3m27s
2025-01-05 11:32:21 -05:00
15 changed files with 163 additions and 108 deletions

View File

@ -79,7 +79,9 @@ jobs:
with: with:
context: . context: .
push: true push: true
tags: ${{ env.DOCKER_IMG }}:${{ github.ref_name }} tags: |
${{ env.DOCKER_IMG }}:${{ github.ref_name }}
${{ env.DOCKER_IMG }}:latest
build-args: | build-args: |
VER_PKG={{ env.VER_PKG }} VER_PKG=${{ env.VER_PKG }}
VERSION=${{ github.ref_name }} VERSION=${{ github.ref_name }}

4
.gitignore vendored
View File

@ -20,7 +20,11 @@
# Go workspace file # Go workspace file
go.work go.work
go.work.sum
.env .env
bin/* bin/*
config.yaml
docker-compose.yml

View File

@ -3,7 +3,7 @@ CMD_NAME := ambient-local-exporter
.PHONY: all test build docker install clean .PHONY: all test build docker install clean
VERSION ?= development # Default to "development" if VERSION is not set VERSION ?= development # Default to "development" if VERSION is not set
PLATFORMS := linux/amd64 darwin/amd64 darwin/arm64 PLATFORMS := linux/amd64 linux/arm64 darwin/amd64 darwin/arm64
OUTPUT_DIR := bin OUTPUT_DIR := bin
VER_PKG := gitea.libretechconsulting.com/rmcguire/go-app/pkg/config.Version VER_PKG := gitea.libretechconsulting.com/rmcguire/go-app/pkg/config.Version
DOCKER_IMG := gitea.libretechconsulting.com/rmcguire/ambient-local-exporter DOCKER_IMG := gitea.libretechconsulting.com/rmcguire/ambient-local-exporter

18
TODO.md
View File

@ -1,10 +1,16 @@
# TODO # TODO
- [ ] Fix shutdown
- [ ] Configuration for app - [ ] Configuration for app
- [ ] Makefile
- [ ] Dockerfile
- [ ] Helm Chart - [ ] Helm Chart
- [ ] Gitea CI
- [ ] Update README - [ ] Update README
- [ ] Version flag - [ ] Add Grafana dashboard
- [ ] Add device name field with ID/Key mappings
- [ ] Add device type field with ID/Key mappings
## Done
- [x] Consolidate battery status into one metric with device label
- [x] Fix shutdown
- [x] Add new fields from WS-2192
- [x] Gitea CI
- [x] Version flag
- [x] Makefile
- [x] Dockerfile

View File

@ -10,6 +10,10 @@ services:
APP_LOG_FORMAT: json ## console, json APP_LOG_FORMAT: json ## console, json
APP_LOG_TIME_FORMAT: rfc3339 ## long, short, unix, rfc3339, off APP_LOG_TIME_FORMAT: rfc3339 ## long, short, unix, rfc3339, off
APP_HTTP_LISTEN: 0.0.0.0:8080 APP_HTTP_LISTEN: 0.0.0.0:8080
APP_HTTP_READ_TIMEOUT: 10s
APP_HTTP_WRITE_TIMEOUT: 10s
APP_HTTP_IDLE_TIMEOUT: 30s
APP_HTTP_LOG_REQUESTS: true
APP_OTEL_STDOUT_ENABLED: false APP_OTEL_STDOUT_ENABLED: false
APP_OTEL_METRIC_INTERVAL_SECS: 30 APP_OTEL_METRIC_INTERVAL_SECS: 30
OTEL_EXPORTER_OTLP_ENDPOINT: http://otel.libretechconsulting.com:4317 # Set to your otel collector OTEL_EXPORTER_OTLP_ENDPOINT: http://otel.libretechconsulting.com:4317 # Set to your otel collector

4
go.mod
View File

@ -3,7 +3,7 @@ module gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter
go 1.23.4 go 1.23.4
require ( require (
gitea.libretechconsulting.com/rmcguire/go-app v0.1.1 gitea.libretechconsulting.com/rmcguire/go-app v0.3.0
github.com/gorilla/schema v1.4.1 github.com/gorilla/schema v1.4.1
github.com/rs/zerolog v1.33.0 github.com/rs/zerolog v1.33.0
go.opentelemetry.io/otel v1.33.0 go.opentelemetry.io/otel v1.33.0
@ -13,7 +13,7 @@ require (
require ( require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/caarlos0/env/v9 v9.0.0 // indirect github.com/caarlos0/env/v11 v11.3.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect

14
go.sum
View File

@ -1,11 +1,13 @@
gitea.libretechconsulting.com/rmcguire/go-app v0.1.0 h1:H4TMgQ463oRNOyoi0FAvfGtOoDn651zNZStxM+sdNuU= gitea.libretechconsulting.com/rmcguire/go-app v0.1.3 h1:EwmEJLpN+rQjJ5stGEkZsqEDa5F/YnDAEeqJB9XlFn4=
gitea.libretechconsulting.com/rmcguire/go-app v0.1.0/go.mod h1:p0ajkpFvzzD6VZ4xSjuowtwGRb1DjMfo/iG6LyFqFCs= gitea.libretechconsulting.com/rmcguire/go-app v0.1.3/go.mod h1:wHOWh4O4AMDATQ3WEUYjq5a5bnICPBpu5G6BsNxqN38=
gitea.libretechconsulting.com/rmcguire/go-app v0.1.1 h1:Hrxqi1tqz8mf0baBsWgFe/S4jyMtIuPqH2FlanJUMNc= gitea.libretechconsulting.com/rmcguire/go-app v0.2.0 h1:pOm/PysC0IWPuEbmEjNSHHa8Qc5OhuoksYExcuJMFE4=
gitea.libretechconsulting.com/rmcguire/go-app v0.1.1/go.mod h1:p0ajkpFvzzD6VZ4xSjuowtwGRb1DjMfo/iG6LyFqFCs= gitea.libretechconsulting.com/rmcguire/go-app v0.2.0/go.mod h1:wHOWh4O4AMDATQ3WEUYjq5a5bnICPBpu5G6BsNxqN38=
gitea.libretechconsulting.com/rmcguire/go-app v0.3.0 h1:TSR6oEDBX+83975gmgGgU/cTFgfG999+9N/1h4RAXq0=
gitea.libretechconsulting.com/rmcguire/go-app v0.3.0/go.mod h1:wHOWh4O4AMDATQ3WEUYjq5a5bnICPBpu5G6BsNxqN38=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/caarlos0/env/v9 v9.0.0 h1:SI6JNsOA+y5gj9njpgybykATIylrRMklbs5ch6wO6pc= github.com/caarlos0/env/v11 v11.3.1 h1:cArPWC15hWmEt+gWk7YBi7lEXTXCvpaSdCiZE2X5mCA=
github.com/caarlos0/env/v9 v9.0.0/go.mod h1:ye5mlCVMYh6tZ+vCgrs/B95sj88cg5Tlnc0XIzgZ020= github.com/caarlos0/env/v11 v11.3.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=

View File

@ -16,10 +16,10 @@ func main() {
ctx, cncl := signal.NotifyContext(context.Background(), os.Kill, unix.SIGTERM) ctx, cncl := signal.NotifyContext(context.Background(), os.Kill, unix.SIGTERM)
defer cncl() defer cncl()
// Read config and environment, set up logging, load up
// an appCtx, and prepare ambient weather local exporter
ctx = app.MustSetupConfigAndLogging(ctx) ctx = app.MustSetupConfigAndLogging(ctx)
aw := ambient.New(ctx).Init()
aw := ambient.New(ctx)
aw.MustInit()
awApp := app.App{ awApp := app.App{
AppContext: ctx, AppContext: ctx,

View File

@ -37,10 +37,12 @@ func New(appCtx context.Context) *AmbientWeather {
} }
} }
func (aw *AmbientWeather) MustInit() { // Initialize with defaults, set logger from context
func (aw *AmbientWeather) Init() *AmbientWeather {
aw.awnProvider = &awn.AWNProvider{} aw.awnProvider = &awn.AWNProvider{}
aw.wuProvider = &wunderground.WUProvider{} aw.wuProvider = &wunderground.WUProvider{}
aw.l = zerolog.Ctx(aw.appCtx) aw.l = zerolog.Ctx(aw.appCtx)
return aw
} }
func (aw *AmbientWeather) GetAWNHandlerFunc(appCtx context.Context) func(http.ResponseWriter, *http.Request) { func (aw *AmbientWeather) GetAWNHandlerFunc(appCtx context.Context) func(http.ResponseWriter, *http.Request) {
@ -55,7 +57,7 @@ func (aw *AmbientWeather) GetWundergroundHandlerFunc(appCtx context.Context) fun
} }
} }
// Takes an HTTP requests and convers it to a // Takes an HTTP requests and converts it to a
// stable type. Enrich is called on the type to complete // stable type. Enrich is called on the type to complete
// any missing fields as the two providers supported by Ambient // any missing fields as the two providers supported by Ambient
// devices (awn/wunderground) produce different fields // devices (awn/wunderground) produce different fields
@ -85,6 +87,7 @@ func (aw *AmbientWeather) handleProviderRequest(
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error())) w.Write([]byte(err.Error()))
return
} }
// Calculate any fields that may be missing // Calculate any fields that may be missing

View File

@ -39,31 +39,46 @@ func MapAwnUpdate(awnUpdate *AmbientWeatherUpdate) *weather.WeatherUpdate {
} }
return &weather.WeatherUpdate{ return &weather.WeatherUpdate{
StationType: awnUpdate.StationType, StationType: awnUpdate.StationType,
DateUTC: &updateTime, DateUTC: &updateTime,
TempOutdoorF: awnUpdate.TempF, TempOutdoorF: awnUpdate.TempF,
HumidityOudoor: awnUpdate.Humidity, HumidityOudoor: awnUpdate.Humidity,
WindSpeedMPH: awnUpdate.WindGustMPH, WindSpeedMPH: awnUpdate.WindGustMPH,
WindGustMPH: awnUpdate.WindGustMPH, WindGustMPH: awnUpdate.WindGustMPH,
MaxDailyGust: awnUpdate.MaxDailyGust, MaxDailyGust: awnUpdate.MaxDailyGust,
WindDir: awnUpdate.WindDir, WindDir: awnUpdate.WindDir,
WindDirAvg10m: awnUpdate.WindDirAVG10m, WindDirAvg10m: awnUpdate.WindDirAVG10m,
UV: awnUpdate.UV, UV: awnUpdate.UV,
SolarRadiation: awnUpdate.SolarRadiation, SolarRadiation: awnUpdate.SolarRadiation,
HourlyRainIn: awnUpdate.HourlyRainIn, HourlyRainIn: awnUpdate.HourlyRainIn,
EventRainIn: awnUpdate.EventRainIn, EventRainIn: awnUpdate.EventRainIn,
DailyRainIn: awnUpdate.DailyRainIn, DailyRainIn: awnUpdate.DailyRainIn,
WeeklyRainIn: awnUpdate.WeeklyRainIn, WeeklyRainIn: awnUpdate.WeeklyRainIn,
MonthlyRainIn: awnUpdate.MonthlyRainIn, MonthlyRainIn: awnUpdate.MonthlyRainIn,
YearlyRainIn: awnUpdate.YearlyRainIn, YearlyRainIn: awnUpdate.YearlyRainIn,
TotalRainIn: awnUpdate.TotalRainIn, TotalRainIn: awnUpdate.TotalRainIn,
BattOutdoorSensor: awnUpdate.BattOut, Batteries: []weather.BatteryStatus{
BattIndoorSensor: awnUpdate.BattIn, {
BattRainSensor: awnUpdate.BattRain, Component: "OutdoorSensor",
TempIndoorF: awnUpdate.TempInF, Status: awnUpdate.BattOut,
HumidityIndoor: awnUpdate.HumidityIn, },
BaromRelativeIn: awnUpdate.BaromRelIn, {
BaromAbsoluteIn: awnUpdate.BaromAbsIn, Component: "IndoorSensor",
Status: awnUpdate.BattIn,
},
{
Component: "RainSensor",
Status: awnUpdate.BattRain,
},
{
Component: "CO2Sensor",
Status: awnUpdate.BattCO2,
},
},
TempIndoorF: awnUpdate.TempInF,
HumidityIndoor: awnUpdate.HumidityIn,
BaromRelativeIn: awnUpdate.BaromRelIn,
BaromAbsoluteIn: awnUpdate.BaromAbsIn,
} }
} }

View File

@ -27,4 +27,5 @@ type AmbientWeatherUpdate struct {
BaromRelIn float64 `json:"baromrelin,omitempty" schema:"baromrelin"` BaromRelIn float64 `json:"baromrelin,omitempty" schema:"baromrelin"`
BaromAbsIn float64 `json:"baromabsin,omitempty" schema:"baromabsin"` BaromAbsIn float64 `json:"baromabsin,omitempty" schema:"baromabsin"`
BattIn int `json:"battin,omitempty" schema:"battin"` BattIn int `json:"battin,omitempty" schema:"battin"`
BattCO2 int `json:"batt_co2,omitempty" schema:"batt_co2"`
} }

View File

@ -5,11 +5,15 @@ import "math"
// Attempts to complete missing fields that may not // Attempts to complete missing fields that may not
// be set by a specific provider, such as DewPoint and WindChill // be set by a specific provider, such as DewPoint and WindChill
func (u *WeatherUpdate) Enrich() { func (u *WeatherUpdate) Enrich() {
if u == nil {
return
}
if u.WindChillF == 0 { if u.WindChillF == 0 {
u.WindChillF = CalculateWindChill(u.TempOutdoorF, u.WindSpeedMPH) u.WindChillF = CalculateWindChill(u.TempOutdoorF, u.WindSpeedMPH)
} }
if u.DewPointF == 0 { if u.DewPointF == 0 && (u.TempOutdoorF != 0 && u.HumidityOudoor != 0) {
u.DewPointF = CalculateDewPoint(u.TempOutdoorF, float64(u.HumidityOudoor)) u.DewPointF = CalculateDewPoint(u.TempOutdoorF, float64(u.HumidityOudoor))
} }

View File

@ -12,31 +12,29 @@ import (
type WeatherMetrics struct { type WeatherMetrics struct {
// Weather Metrics // Weather Metrics
TempOutdoorF metric.Float64Gauge TempOutdoorF metric.Float64Gauge
TempIndoorF metric.Float64Gauge TempIndoorF metric.Float64Gauge
HumidityOudoor metric.Int64Gauge HumidityOudoor metric.Int64Gauge
HumidityIndoor metric.Int64Gauge HumidityIndoor metric.Int64Gauge
WindSpeedMPH metric.Float64Gauge WindSpeedMPH metric.Float64Gauge
WindGustMPH metric.Float64Gauge WindGustMPH metric.Float64Gauge
MaxDailyGust metric.Float64Gauge MaxDailyGust metric.Float64Gauge
WindDir metric.Int64Gauge WindDir metric.Int64Gauge
WindDirAvg10m metric.Int64Gauge WindDirAvg10m metric.Int64Gauge
UV metric.Int64Gauge UV metric.Int64Gauge
SolarRadiation metric.Float64Gauge SolarRadiation metric.Float64Gauge
HourlyRainIn metric.Float64Gauge HourlyRainIn metric.Float64Gauge
EventRainIn metric.Float64Gauge EventRainIn metric.Float64Gauge
DailyRainIn metric.Float64Gauge DailyRainIn metric.Float64Gauge
WeeklyRainIn metric.Float64Gauge WeeklyRainIn metric.Float64Gauge
MonthlyRainIn metric.Float64Gauge MonthlyRainIn metric.Float64Gauge
YearlyRainIn metric.Float64Gauge YearlyRainIn metric.Float64Gauge
TotalRainIn metric.Float64Gauge TotalRainIn metric.Float64Gauge
BattOutdoorSensor metric.Int64Gauge BatteryStatus metric.Int64Gauge
BattIndoorSensor metric.Int64Gauge BaromRelativeIn metric.Float64Gauge
BattRainSensor metric.Int64Gauge BaromAbsoluteIn metric.Float64Gauge
BaromRelativeIn metric.Float64Gauge DewPointF metric.Float64Gauge
BaromAbsoluteIn metric.Float64Gauge WindChillF metric.Float64Gauge
DewPointF metric.Float64Gauge
WindChillF metric.Float64Gauge
// Internal Telemetry // Internal Telemetry
UpdatesReceived metric.Int64Counter UpdatesReceived metric.Int64Counter
@ -58,7 +56,7 @@ func MustInitMetrics(appCtx context.Context) *WeatherMetrics {
metric.WithDescription("Outdoor Temperature in Faherenheit")) metric.WithDescription("Outdoor Temperature in Faherenheit"))
wm.TempIndoorF, _ = wm.meter.Float64Gauge("weather_temp_indoor_f", wm.TempIndoorF, _ = wm.meter.Float64Gauge("weather_temp_indoor_f",
metric.WithDescription("Indoor Temperature in Faherenheit")) metric.WithDescription("Indoor Temperature in Faherenheit"))
wm.HumidityOudoor, _ = wm.meter.Int64Gauge("weather_humidity_oudoor", wm.HumidityOudoor, _ = wm.meter.Int64Gauge("weather_humidity_outdoor",
metric.WithDescription("Outdoor Humidity %")) metric.WithDescription("Outdoor Humidity %"))
wm.HumidityIndoor, _ = wm.meter.Int64Gauge("weather_humidity_indoor", wm.HumidityIndoor, _ = wm.meter.Int64Gauge("weather_humidity_indoor",
metric.WithDescription("Indoor Humidity %")) metric.WithDescription("Indoor Humidity %"))
@ -90,12 +88,8 @@ func MustInitMetrics(appCtx context.Context) *WeatherMetrics {
metric.WithDescription("Yearly Rain in Inches")) metric.WithDescription("Yearly Rain in Inches"))
wm.TotalRainIn, _ = wm.meter.Float64Gauge("weather_total_rain_in", wm.TotalRainIn, _ = wm.meter.Float64Gauge("weather_total_rain_in",
metric.WithDescription("Total Rain in Inches")) metric.WithDescription("Total Rain in Inches"))
wm.BattOutdoorSensor, _ = wm.meter.Int64Gauge("weather_batt_outdoor_sensor", wm.BatteryStatus, _ = wm.meter.Int64Gauge("battery_status",
metric.WithDescription("Outdoor Equipment Battery")) metric.WithDescription("Per-component battery status"))
wm.BattIndoorSensor, _ = wm.meter.Int64Gauge("weather_batt_indoor_sensor",
metric.WithDescription("Indoor Equipmenet Battery"))
wm.BattRainSensor, _ = wm.meter.Int64Gauge("weather_batt_rain_sensor",
metric.WithDescription("Rain Sensor Battery"))
wm.BaromRelativeIn, _ = wm.meter.Float64Gauge("weather_barometric_pressure_relative_in", wm.BaromRelativeIn, _ = wm.meter.Float64Gauge("weather_barometric_pressure_relative_in",
metric.WithDescription("Relative Pressure in Inches of Mercury")) metric.WithDescription("Relative Pressure in Inches of Mercury"))
wm.BaromAbsoluteIn, _ = wm.meter.Float64Gauge("weather_barometric_pressure_absolute_in", wm.BaromAbsoluteIn, _ = wm.meter.Float64Gauge("weather_barometric_pressure_absolute_in",
@ -136,13 +130,18 @@ func (wm *WeatherMetrics) Update(u *WeatherUpdate) {
wm.MonthlyRainIn.Record(wm.appCtx, u.MonthlyRainIn, metric.WithAttributeSet(attributes)) wm.MonthlyRainIn.Record(wm.appCtx, u.MonthlyRainIn, metric.WithAttributeSet(attributes))
wm.YearlyRainIn.Record(wm.appCtx, u.YearlyRainIn, metric.WithAttributeSet(attributes)) wm.YearlyRainIn.Record(wm.appCtx, u.YearlyRainIn, metric.WithAttributeSet(attributes))
wm.TotalRainIn.Record(wm.appCtx, u.TotalRainIn, metric.WithAttributeSet(attributes)) wm.TotalRainIn.Record(wm.appCtx, u.TotalRainIn, metric.WithAttributeSet(attributes))
wm.BattOutdoorSensor.Record(wm.appCtx, int64(u.BattOutdoorSensor), metric.WithAttributeSet(attributes))
wm.BattIndoorSensor.Record(wm.appCtx, int64(u.BattIndoorSensor), metric.WithAttributeSet(attributes))
wm.BattRainSensor.Record(wm.appCtx, int64(u.BattRainSensor), metric.WithAttributeSet(attributes))
wm.BaromRelativeIn.Record(wm.appCtx, u.BaromRelativeIn, metric.WithAttributeSet(attributes)) wm.BaromRelativeIn.Record(wm.appCtx, u.BaromRelativeIn, metric.WithAttributeSet(attributes))
wm.BaromAbsoluteIn.Record(wm.appCtx, u.BaromAbsoluteIn, metric.WithAttributeSet(attributes)) wm.BaromAbsoluteIn.Record(wm.appCtx, u.BaromAbsoluteIn, metric.WithAttributeSet(attributes))
wm.DewPointF.Record(wm.appCtx, u.DewPointF, metric.WithAttributeSet(attributes)) wm.DewPointF.Record(wm.appCtx, u.DewPointF, metric.WithAttributeSet(attributes))
wm.WindChillF.Record(wm.appCtx, u.WindChillF, metric.WithAttributeSet(attributes)) wm.WindChillF.Record(wm.appCtx, u.WindChillF, metric.WithAttributeSet(attributes))
// Batteries
for _, battery := range u.Batteries {
wm.BatteryStatus.Record(wm.appCtx, int64(battery.Status),
metric.WithAttributeSet(attributes),
metric.WithAttributes(attribute.String("component", battery.Component)),
)
}
wm.UpdatesReceived.Add(wm.appCtx, 1) wm.UpdatesReceived.Add(wm.appCtx, 1)
} }

View File

@ -7,33 +7,40 @@ import (
// Stable intermediate struct containing superset of fields // Stable intermediate struct containing superset of fields
// between AWN and Wunderground style updates from Ambient devices // between AWN and Wunderground style updates from Ambient devices
type WeatherUpdate struct { type WeatherUpdate struct {
DateUTC *time.Time DateUTC *time.Time
StationType string StationType string
TempOutdoorF float64 TempOutdoorF float64
TempIndoorF float64 TempIndoorF float64
HumidityOudoor int HumidityOudoor int
HumidityIndoor int HumidityIndoor int
WindSpeedMPH float64 WindSpeedMPH float64
WindGustMPH float64 WindGustMPH float64
MaxDailyGust float64 MaxDailyGust float64
WindDir int WindDir int
WindDirAvg10m int WindDirAvg10m int
UV int UV int
SolarRadiation float64 SolarRadiation float64
HourlyRainIn float64 HourlyRainIn float64
EventRainIn float64 EventRainIn float64
DailyRainIn float64 DailyRainIn float64
WeeklyRainIn float64 WeeklyRainIn float64
MonthlyRainIn float64 MonthlyRainIn float64
YearlyRainIn float64 YearlyRainIn float64
TotalRainIn float64 TotalRainIn float64
BattOutdoorSensor int Batteries []BatteryStatus
BattIndoorSensor int // BattOutdoorSensor int
BattRainSensor int // BattIndoorSensor int
BaromRelativeIn float64 // BattRainSensor int
BaromAbsoluteIn float64 // BattCO2Sensor int
BaromRelativeIn float64
BaromAbsoluteIn float64
// These fields may be calculated // These fields may be calculated
// if not otherwise set // if not otherwise set
DewPointF float64 DewPointF float64
WindChillF float64 WindChillF float64
} }
type BatteryStatus struct {
Component string
Status int
}

8
unset_env.sh Executable file
View File

@ -0,0 +1,8 @@
#!env sh
unset APP_NAME
unset APP_LOG_LEVEL
unset APP_LOG_FORMAT
unset APP_LOG_TIME_FORMAT
unset APP_HTTP_LISTEN
unset APP_OTEL_STDOUT_ENABLED
unset APP_OTEL_METRIC_INTERVAL_SECS