support sensor name mapping
All checks were successful
Build and Publish / release (push) Successful in 4m6s
All checks were successful
Build and Publish / release (push) Successful in 4m6s
This commit is contained in:
parent
f98a4cf348
commit
29433cddd7
14
go.mod
14
go.mod
@ -22,12 +22,12 @@ require (
|
|||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
github.com/prometheus/client_golang v1.21.1 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.62.0 // indirect
|
github.com/prometheus/common v0.62.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
@ -43,11 +43,11 @@ require (
|
|||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
golang.org/x/net v0.35.0 // indirect
|
golang.org/x/net v0.36.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.22.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
google.golang.org/grpc v1.70.0 // indirect
|
google.golang.org/grpc v1.71.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.5 // indirect
|
google.golang.org/protobuf v1.36.5 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
15
go.sum
15
go.sum
@ -33,6 +33,7 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
|||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
|
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
|
||||||
@ -41,8 +42,12 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTK
|
|||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@ -63,6 +68,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
|
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||||
|
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||||
@ -110,6 +117,8 @@ golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
|||||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
|
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
||||||
|
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -127,12 +136,18 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287 h1:
|
|||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b h1:i+d0RZa8Hs2L/MuaOQYI+krthcxdEbEM2N+Tf3kJ4zk=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b h1:i+d0RZa8Hs2L/MuaOQYI+krthcxdEbEM2N+Tf3kJ4zk=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 h1:J1H9f+LEdWAfHcez/4cvaVBox7cOYT+IU6rgqj5x++8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 h1:J1H9f+LEdWAfHcez/4cvaVBox7cOYT+IU6rgqj5x++8=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||||
|
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||||
|
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/codes"
|
"go.opentelemetry.io/otel/codes"
|
||||||
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
|
||||||
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/ambient/config"
|
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/ambient/config"
|
||||||
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/provider"
|
"gitea.libretechconsulting.com/rmcguire/ambient-weather-local-exporter/pkg/provider"
|
||||||
@ -67,6 +68,11 @@ func (aw *AmbientWeather) GetWundergroundHandlerFunc(appCtx context.Context) fun
|
|||||||
// 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
|
||||||
|
//
|
||||||
|
// This will call Update on metrics, and will also proxy
|
||||||
|
// requests to AWN/Wunderground if enabled
|
||||||
|
// This is the main work performed when a weather station or
|
||||||
|
// weather hub sends an update
|
||||||
func (aw *AmbientWeather) handleProviderRequest(
|
func (aw *AmbientWeather) handleProviderRequest(
|
||||||
p provider.AmbientProvider,
|
p provider.AmbientProvider,
|
||||||
w http.ResponseWriter,
|
w http.ResponseWriter,
|
||||||
@ -96,20 +102,17 @@ func (aw *AmbientWeather) handleProviderRequest(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate any fields that may be missing
|
// Perform enrichment
|
||||||
// such as dew point and wind chill
|
aw.enrichUpdate(ctx, p, update)
|
||||||
update.Enrich()
|
|
||||||
|
|
||||||
// Prepare metrics if this is the first update
|
// Update metrics
|
||||||
|
ctx, updateSpan := tracer.Start(ctx, p.Name()+".update.metrics")
|
||||||
if aw.metrics == nil {
|
if aw.metrics == nil {
|
||||||
aw.InitMetrics()
|
aw.InitMetrics()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enrich station if configured
|
|
||||||
aw.enrichStation(update)
|
|
||||||
|
|
||||||
// Update metrics
|
|
||||||
aw.metrics.Update(update)
|
aw.metrics.Update(update)
|
||||||
|
updateSpan.SetStatus(codes.Ok, "")
|
||||||
|
updateSpan.End()
|
||||||
|
|
||||||
l.Debug().
|
l.Debug().
|
||||||
Str("provider", p.Name()).
|
Str("provider", p.Name()).
|
||||||
@ -120,17 +123,61 @@ func (aw *AmbientWeather) handleProviderRequest(
|
|||||||
// Proxy update to one or both services if configured to do so
|
// Proxy update to one or both services if configured to do so
|
||||||
// Uses a weather update to allow awn to publish to wunderground and
|
// Uses a weather update to allow awn to publish to wunderground and
|
||||||
// visa versa.
|
// visa versa.
|
||||||
if station := update.StationConfig; station != nil {
|
if update.StationConfig != nil {
|
||||||
// Perform proxy updates in parallel if enabled
|
aw.proxyUpdate(ctx, p, update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (aw *AmbientWeather) enrichUpdate(
|
||||||
|
ctx context.Context,
|
||||||
|
p provider.AmbientProvider,
|
||||||
|
update *weather.WeatherUpdate,
|
||||||
|
) {
|
||||||
|
tracer := otel.GetTracer(aw.appCtx, p.Name()+".http.handler")
|
||||||
|
|
||||||
|
// Calculate any fields that may be missing
|
||||||
|
// such as dew point and wind chill
|
||||||
|
ctx, enrichSpan := tracer.Start(ctx, p.Name()+".update.enrich")
|
||||||
|
update.Enrich()
|
||||||
|
|
||||||
|
// Enrich station if configured
|
||||||
|
aw.enrichStation(update)
|
||||||
|
|
||||||
|
// Map sensor names
|
||||||
|
update.MapSensors()
|
||||||
|
|
||||||
|
enrichSpan.SetStatus(codes.Ok, "")
|
||||||
|
enrichSpan.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (aw *AmbientWeather) proxyUpdate(
|
||||||
|
ctx context.Context,
|
||||||
|
p provider.AmbientProvider,
|
||||||
|
update *weather.WeatherUpdate,
|
||||||
|
) {
|
||||||
var proxyWg sync.WaitGroup
|
var proxyWg sync.WaitGroup
|
||||||
|
|
||||||
|
tracer := otel.GetTracer(aw.appCtx, p.Name()+".http.handler")
|
||||||
|
station := update.StationConfig
|
||||||
|
|
||||||
|
ctx, proxySpan := tracer.Start(ctx, p.Name()+".update.proxy", trace.WithAttributes(
|
||||||
|
attribute.Bool("proxyToWunderground", station.ProxyToWunderground),
|
||||||
|
attribute.Bool("proxyToAWN", station.ProxyToAWN),
|
||||||
|
))
|
||||||
|
defer proxySpan.End()
|
||||||
|
|
||||||
|
// Perform proxy updates in parallel if enabled
|
||||||
|
|
||||||
if station.ProxyToAWN {
|
if station.ProxyToAWN {
|
||||||
proxyWg.Add(1)
|
proxyWg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer proxyWg.Done()
|
defer proxyWg.Done()
|
||||||
|
defer proxySpan.AddEvent("proxied to ambient weather network")
|
||||||
err := aw.awnProvider.ProxyReq(ctx, update)
|
err := aw.awnProvider.ProxyReq(ctx, update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(aw.appCtx).Err(err).Msg("failed to proxy to ambient weather")
|
zerolog.Ctx(aw.appCtx).Err(err).Msg("failed to proxy to ambient weather")
|
||||||
|
proxySpan.RecordError(err)
|
||||||
|
proxySpan.SetStatus(codes.Error, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
zerolog.Ctx(aw.appCtx).Debug().
|
zerolog.Ctx(aw.appCtx).Debug().
|
||||||
@ -143,9 +190,12 @@ func (aw *AmbientWeather) handleProviderRequest(
|
|||||||
proxyWg.Add(1)
|
proxyWg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer proxyWg.Done()
|
defer proxyWg.Done()
|
||||||
|
defer proxySpan.AddEvent("proxied to wunderground")
|
||||||
err := aw.wuProvider.ProxyReq(ctx, update)
|
err := aw.wuProvider.ProxyReq(ctx, update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(aw.appCtx).Err(err).Msg("failed to proxy to ambient weather")
|
zerolog.Ctx(aw.appCtx).Err(err).Msg("failed to proxy to ambient weather")
|
||||||
|
proxySpan.RecordError(err)
|
||||||
|
proxySpan.SetStatus(codes.Error, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
zerolog.Ctx(aw.appCtx).Debug().
|
zerolog.Ctx(aw.appCtx).Debug().
|
||||||
@ -155,7 +205,6 @@ func (aw *AmbientWeather) handleProviderRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
proxyWg.Wait()
|
proxyWg.Wait()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *AmbientWeather) InitMetrics() {
|
func (aw *AmbientWeather) InitMetrics() {
|
||||||
|
@ -33,4 +33,14 @@ type WeatherStation struct {
|
|||||||
// Check weather.WeatherUpdateField for options
|
// Check weather.WeatherUpdateField for options
|
||||||
KeepMetrics []string `yaml:"keepMetrics"`
|
KeepMetrics []string `yaml:"keepMetrics"`
|
||||||
DropMetrics []string `yaml:"dropMetrics"`
|
DropMetrics []string `yaml:"dropMetrics"`
|
||||||
|
|
||||||
|
// Relabels battery and sensor names
|
||||||
|
// Temp+Humidity Sensors:
|
||||||
|
// - TempHumiditySensor[1-8]
|
||||||
|
// Batteries:
|
||||||
|
// - IndoorSensor
|
||||||
|
// - OutdoorSensor
|
||||||
|
// - RainSensor
|
||||||
|
// - CO2Sensor
|
||||||
|
SensorMappings map[string]string `yaml:"sensorMappings"`
|
||||||
}
|
}
|
||||||
|
12
pkg/ambient/config/ws_map.go
Normal file
12
pkg/ambient/config/ws_map.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
// If the weather-station has a mapping, returns the new
|
||||||
|
// name for the sensor
|
||||||
|
func (ws *WeatherStation) MapSensor(sensor string) string {
|
||||||
|
for name, replacement := range ws.SensorMappings {
|
||||||
|
if name == sensor && replacement != "" {
|
||||||
|
return replacement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sensor
|
||||||
|
}
|
67
pkg/ambient/config/ws_map_test.go
Normal file
67
pkg/ambient/config/ws_map_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestWeatherStation_MapSensor(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
Name string
|
||||||
|
Equipment string
|
||||||
|
WundergroundID string
|
||||||
|
WundergroundPassword string
|
||||||
|
AWNPassKey string
|
||||||
|
ProxyToAWN bool
|
||||||
|
ProxyToWunderground bool
|
||||||
|
KeepMetrics []string
|
||||||
|
DropMetrics []string
|
||||||
|
SensorMappings map[string]string
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
sensor string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Check sensor mapping",
|
||||||
|
fields: fields{
|
||||||
|
SensorMappings: map[string]string{
|
||||||
|
"TempHumiditySensor1": "TestSensor",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{sensor: "TempHumiditySensor1"},
|
||||||
|
want: "TestSensor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Check sensor no mapping",
|
||||||
|
fields: fields{
|
||||||
|
SensorMappings: map[string]string{
|
||||||
|
"TempHumiditySensor1": "TestSensor",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{sensor: "TempHumiditySensor2"},
|
||||||
|
want: "TempHumiditySensor2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
ws := &WeatherStation{
|
||||||
|
Name: tt.fields.Name,
|
||||||
|
Equipment: tt.fields.Equipment,
|
||||||
|
WundergroundID: tt.fields.WundergroundID,
|
||||||
|
WundergroundPassword: tt.fields.WundergroundPassword,
|
||||||
|
AWNPassKey: tt.fields.AWNPassKey,
|
||||||
|
ProxyToAWN: tt.fields.ProxyToAWN,
|
||||||
|
ProxyToWunderground: tt.fields.ProxyToWunderground,
|
||||||
|
KeepMetrics: tt.fields.KeepMetrics,
|
||||||
|
DropMetrics: tt.fields.DropMetrics,
|
||||||
|
SensorMappings: tt.fields.SensorMappings,
|
||||||
|
}
|
||||||
|
if got := ws.MapSensor(tt.args.sensor); got != tt.want {
|
||||||
|
t.Errorf("WeatherStation.MapSensor() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -128,16 +128,15 @@ func MapAwnUpdate(awnUpdate *AmbientWeatherUpdate) *weather.WeatherUpdate {
|
|||||||
HumidityIndoor: awnUpdate.HumidityIn,
|
HumidityIndoor: awnUpdate.HumidityIn,
|
||||||
BaromRelativeIn: awnUpdate.BaromRelIn,
|
BaromRelativeIn: awnUpdate.BaromRelIn,
|
||||||
BaromAbsoluteIn: awnUpdate.BaromAbsIn,
|
BaromAbsoluteIn: awnUpdate.BaromAbsIn,
|
||||||
// TODO: Permit mapping to config name
|
|
||||||
TempHumiditySensors: []*weather.TempHumiditySensor{
|
TempHumiditySensors: []*weather.TempHumiditySensor{
|
||||||
{Name: "Sensor1", TempF: awnUpdate.Temp1F, Humidity: awnUpdate.Humidity1},
|
{Name: THSensor + "1", TempF: awnUpdate.Temp1F, Humidity: awnUpdate.Humidity1},
|
||||||
{Name: "Sensor2", TempF: awnUpdate.Temp2F, Humidity: awnUpdate.Humidity2},
|
{Name: THSensor + "2", TempF: awnUpdate.Temp2F, Humidity: awnUpdate.Humidity2},
|
||||||
{Name: "Sensor3", TempF: awnUpdate.Temp3F, Humidity: awnUpdate.Humidity3},
|
{Name: THSensor + "3", TempF: awnUpdate.Temp3F, Humidity: awnUpdate.Humidity3},
|
||||||
{Name: "Sensor4", TempF: awnUpdate.Temp4F, Humidity: awnUpdate.Humidity4},
|
{Name: THSensor + "4", TempF: awnUpdate.Temp4F, Humidity: awnUpdate.Humidity4},
|
||||||
{Name: "Sensor5", TempF: awnUpdate.Temp5F, Humidity: awnUpdate.Humidity5},
|
{Name: THSensor + "5", TempF: awnUpdate.Temp5F, Humidity: awnUpdate.Humidity5},
|
||||||
{Name: "Sensor6", TempF: awnUpdate.Temp6F, Humidity: awnUpdate.Humidity6},
|
{Name: THSensor + "6", TempF: awnUpdate.Temp6F, Humidity: awnUpdate.Humidity6},
|
||||||
{Name: "Sensor7", TempF: awnUpdate.Temp7F, Humidity: awnUpdate.Humidity7},
|
{Name: THSensor + "7", TempF: awnUpdate.Temp7F, Humidity: awnUpdate.Humidity7},
|
||||||
{Name: "Sensor8", TempF: awnUpdate.Temp8F, Humidity: awnUpdate.Humidity8},
|
{Name: THSensor + "8", TempF: awnUpdate.Temp8F, Humidity: awnUpdate.Humidity8},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
// 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
|
||||||
|
// TODO: Add span
|
||||||
func (u *WeatherUpdate) Enrich(weatherStations ...*config.WeatherStation) {
|
func (u *WeatherUpdate) Enrich(weatherStations ...*config.WeatherStation) {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
return
|
return
|
||||||
@ -49,6 +50,24 @@ func (u *WeatherUpdate) Enrich(weatherStations ...*config.WeatherStation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Swaps sensor and component names based on
|
||||||
|
// user provided configuration
|
||||||
|
func (u *WeatherUpdate) MapSensors() {
|
||||||
|
if u.StationConfig == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map sensor battery components
|
||||||
|
for i, batt := range u.Batteries {
|
||||||
|
u.Batteries[i].Component = u.StationConfig.MapSensor(batt.Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map other sensors
|
||||||
|
for _, th := range u.TempHumiditySensors {
|
||||||
|
th.Name = u.StationConfig.MapSensor(th.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CalculateDewPoint(tempF, humidity float64) float64 {
|
func CalculateDewPoint(tempF, humidity float64) float64 {
|
||||||
// Convert temperature from Fahrenheit to Celsius
|
// Convert temperature from Fahrenheit to Celsius
|
||||||
tempC := (tempF - 32) * 5 / 9
|
tempC := (tempF - 32) * 5 / 9
|
||||||
|
Loading…
x
Reference in New Issue
Block a user