Compare commits

..

18 Commits

Author SHA1 Message Date
ca18eba167 update gitea ci
All checks were successful
Build and Publish / chart-updated (push) Successful in 40s
Build and Publish / helm-release (push) Successful in 18s
Build and Publish / release (push) Successful in 3m4s
2025-03-21 13:14:45 -04:00
c020c4eec8 update gitea ci
All checks were successful
Build and Publish / release (push) Has been skipped
Build and Publish / chart-updated (push) Successful in 10s
Build and Publish / helm-release (push) Successful in 18s
2025-03-21 13:12:39 -04:00
df7c2dff40 update gitea ci
All checks were successful
Build and Publish / release (push) Has been skipped
Build and Publish / chart-updated (push) Successful in 10s
Build and Publish / helm-release (push) Has been skipped
2025-03-21 13:09:47 -04:00
0b27285b86 update gitea ci
Some checks failed
Build and Publish / release (push) Has been skipped
Build and Publish / chart-updated (push) Failing after 18s
Build and Publish / helm-release (push) Has been skipped
2025-03-21 13:08:08 -04:00
1f097b1fd7 fix recorder 2025-03-21 12:52:39 -04:00
42eea2346b refactor state to recorder, finish implementing 2025-03-21 09:22:32 -04:00
a5948cf334 bump helm chart
All checks were successful
Build and Publish / release (push) Has been skipped
Build and Publish / helm-release (push) Successful in 17s
2025-03-20 17:04:35 -04:00
deb831a2c5 bump helm chart
All checks were successful
Build and Publish / release (push) Has been skipped
Build and Publish / helm-release (push) Has been skipped
2025-03-20 16:50:06 -04:00
d8291150d4 fix tag
All checks were successful
Build and Publish / release (push) Successful in 2m45s
Build and Publish / helm-release (push) Successful in 21s
2025-03-20 16:41:51 -04:00
4a35f11553 bump helm version
All checks were successful
Build and Publish / release (push) Successful in 2m55s
Build and Publish / helm-release (push) Successful in 20s
2025-03-20 16:31:04 -04:00
399c694c3e add map update test 2025-03-20 16:26:11 -04:00
133c6f7315 map weather update
All checks were successful
Build and Publish / release (push) Successful in 4m12s
Build and Publish / helm-release (push) Successful in 22s
2025-03-20 16:04:28 -04:00
220cc818e7 continue working on weather mapping 2025-03-15 09:53:13 -04:00
69fd27916b implement grpc weather 2025-03-14 23:10:01 -04:00
421c246cc6 remove flux from ale 2025-03-10 16:11:12 -04:00
6f297829fc add flux to ale 2025-03-10 16:08:30 -04:00
797b0a2f3a update TODO 2025-03-08 17:40:03 -05:00
be66762834 add helm ci 2025-03-08 17:30:56 -05:00
16 changed files with 715 additions and 208 deletions

View File

@ -2,6 +2,7 @@ name: Build and Publish
on:
push:
tags: ["v*"]
branches: ["main"]
env:
PACKAGE_NAME: ambient-local-exporter
@ -21,9 +22,10 @@ env:
jobs:
release:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') # Only run on tag push
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Go Environment
uses: actions/setup-go@v4
@ -87,11 +89,29 @@ jobs:
VER_PKG=${{ env.VER_PKG }}
VERSION=${{ github.ref_name }}
# Detect if the helm chart was updated
chart-updated:
runs-on: ubuntu-latest
outputs:
chart-updated: ${{ steps.filter.outputs.chart }}
steps:
- uses: actions/checkout@v4
- name: Check Chart Changed
uses: dorny/paths-filter@v3
id: filter
with:
base: ${{ github.ref }}
filters: |
chart:
- helm/ambient-local-exporter/Chart.yaml
helm-release:
runs-on: ubuntu-latest
needs: chart-updated
if: ${{ needs.chart-updated.outputs.chart-updated == 'true' }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Helm
env:
@ -101,7 +121,7 @@ jobs:
- name: Package Chart
run: |
helm package --app-version ${VERSION#v} ${CHART_DIR}
helm package --app-version ${VERSION} ${CHART_DIR}
- name: Publish Chart
env:

View File

@ -1,11 +1,11 @@
# TODO
- [ ] Finish implementing weather GRPC
- [ ] Helm Chart
- [ ] Update README
- [ ] Add Grafana dashboard
- [ ] Add new spans
## Done
- [x] Helm Chart
- [x] Add proxy to upstream support
- [x] Fix wunderground 401
- [x] Perform proxy calls in goroutines

View File

@ -25,6 +25,7 @@ const (
type GetWeatherRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Opts *GetWeatherOpts `protobuf:"bytes,1,opt,name=opts,proto3" json:"opts,omitempty"`
Limit *int32 `protobuf:"varint,2,opt,name=limit,proto3,oneof" json:"limit,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -66,6 +67,13 @@ func (x *GetWeatherRequest) GetOpts() *GetWeatherOpts {
return nil
}
func (x *GetWeatherRequest) GetLimit() int32 {
if x != nil && x.Limit != nil {
return *x.Limit
}
return 0
}
type GetWeatherResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
LastUpdated *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"`
@ -543,149 +551,151 @@ var file_weather_weather_proto_rawDesc = string([]byte{
0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74,
0x2e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x48, 0x0a, 0x11, 0x47, 0x65, 0x74,
0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6d, 0x0a, 0x11, 0x47, 0x65, 0x74,
0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33,
0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61,
0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x47,
0x65, 0x74, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x73, 0x52, 0x04, 0x6f,
0x70, 0x74, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x57, 0x65, 0x61, 0x74, 0x68,
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x6c, 0x61,
0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6c, 0x61,
0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x0f, 0x77, 0x65, 0x61,
0x74, 0x68, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x65, 0x61,
0x74, 0x68, 0x65, 0x72, 0x2e, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65,
0x72, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x73,
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x26, 0x0a,
0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79,
0x70, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb7, 0x0c, 0x0a, 0x0d, 0x57, 0x65, 0x61, 0x74,
0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12,
0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x29,
0x0a, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x5f, 0x66,
0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x4f, 0x75,
0x74, 0x64, 0x6f, 0x6f, 0x72, 0x46, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x74, 0x65, 0x6d,
0x70, 0x5f, 0x69, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x5f, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01,
0x48, 0x01, 0x52, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x49, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x46, 0x88,
0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x6f,
0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x48, 0x02, 0x52, 0x0f,
0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x4f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x88,
0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x69,
0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x48, 0x03, 0x52, 0x0e, 0x68,
0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x88, 0x01, 0x01,
0x12, 0x29, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x5f, 0x6d,
0x70, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x48, 0x04, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64,
0x53, 0x70, 0x65, 0x65, 0x64, 0x4d, 0x70, 0x68, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x77,
0x69, 0x6e, 0x64, 0x5f, 0x67, 0x75, 0x73, 0x74, 0x5f, 0x6d, 0x70, 0x68, 0x18, 0x09, 0x20, 0x01,
0x28, 0x01, 0x48, 0x05, 0x52, 0x0b, 0x77, 0x69, 0x6e, 0x64, 0x47, 0x75, 0x73, 0x74, 0x4d, 0x70,
0x68, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x69, 0x6c,
0x79, 0x5f, 0x67, 0x75, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x48, 0x06, 0x52, 0x0c,
0x6d, 0x61, 0x78, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x47, 0x75, 0x73, 0x74, 0x88, 0x01, 0x01, 0x12,
0x1e, 0x0a, 0x08, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28,
0x05, 0x48, 0x07, 0x52, 0x07, 0x77, 0x69, 0x6e, 0x64, 0x44, 0x69, 0x72, 0x88, 0x01, 0x01, 0x12,
0x2c, 0x0a, 0x10, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x61, 0x76, 0x67, 0x5f,
0x31, 0x30, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x48, 0x08, 0x52, 0x0d, 0x77, 0x69, 0x6e,
0x64, 0x44, 0x69, 0x72, 0x41, 0x76, 0x67, 0x31, 0x30, 0x6d, 0x88, 0x01, 0x01, 0x12, 0x13, 0x0a,
0x02, 0x75, 0x76, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x48, 0x09, 0x52, 0x02, 0x75, 0x76, 0x88,
0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x6f, 0x6c, 0x61, 0x72, 0x5f, 0x72, 0x61, 0x64, 0x69,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0a, 0x52, 0x0e, 0x73,
0x6f, 0x6c, 0x61, 0x72, 0x52, 0x61, 0x64, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01,
0x12, 0x29, 0x0a, 0x0e, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f,
0x69, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0b, 0x52, 0x0c, 0x68, 0x6f, 0x75, 0x72,
0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x65,
0x76, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x10, 0x20, 0x01,
0x28, 0x01, 0x48, 0x0c, 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x61, 0x69, 0x6e, 0x49,
0x6e, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x72, 0x61,
0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0d, 0x52, 0x0b, 0x64,
0x61, 0x69, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a,
0x0e, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18,
0x12, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0e, 0x52, 0x0c, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x52,
0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, 0x6d, 0x6f, 0x6e, 0x74,
0x68, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28,
0x01, 0x48, 0x0f, 0x52, 0x0d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e,
0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x79, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x5f,
0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x01, 0x48, 0x10, 0x52,
0x0c, 0x79, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01,
0x12, 0x27, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69,
0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x01, 0x48, 0x11, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c,
0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x3c, 0x0a, 0x09, 0x62, 0x61, 0x74,
0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61,
0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x42,
0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x62, 0x61,
0x74, 0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x11, 0x62, 0x61, 0x72, 0x6f, 0x6d,
0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x18, 0x17, 0x20, 0x01,
0x28, 0x01, 0x48, 0x12, 0x52, 0x0f, 0x62, 0x61, 0x72, 0x6f, 0x6d, 0x52, 0x65, 0x6c, 0x61, 0x74,
0x69, 0x76, 0x65, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x62, 0x61, 0x72, 0x6f,
0x6d, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x18, 0x18, 0x20,
0x01, 0x28, 0x01, 0x48, 0x13, 0x52, 0x0f, 0x62, 0x61, 0x72, 0x6f, 0x6d, 0x41, 0x62, 0x73, 0x6f,
0x6c, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x23, 0x0a, 0x0b, 0x64, 0x65, 0x77,
0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x66, 0x18, 0x19, 0x20, 0x01, 0x28, 0x01, 0x48, 0x14,
0x52, 0x09, 0x64, 0x65, 0x77, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x46, 0x88, 0x01, 0x01, 0x12, 0x25,
0x0a, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x5f, 0x66, 0x18, 0x1a,
0x20, 0x01, 0x28, 0x01, 0x48, 0x15, 0x52, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c,
0x6c, 0x46, 0x88, 0x01, 0x01, 0x12, 0x57, 0x0a, 0x15, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x68, 0x75,
0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x18, 0x1b,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x77,
0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70, 0x48, 0x75, 0x6d, 0x69, 0x64,
0x69, 0x74, 0x79, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x13, 0x74, 0x65, 0x6d, 0x70, 0x48,
0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x42, 0x11,
0x0a, 0x0f, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x5f,
0x66, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x64, 0x6f, 0x6f,
0x72, 0x5f, 0x66, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79,
0x5f, 0x6f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x68, 0x75, 0x6d,
0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x42, 0x11, 0x0a, 0x0f,
0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x5f, 0x6d, 0x70, 0x68, 0x42,
0x10, 0x0a, 0x0e, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x67, 0x75, 0x73, 0x74, 0x5f, 0x6d, 0x70,
0x68, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f,
0x67, 0x75, 0x73, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x64, 0x69,
0x72, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x61,
0x76, 0x67, 0x5f, 0x31, 0x30, 0x6d, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x75, 0x76, 0x42, 0x12, 0x0a,
0x10, 0x5f, 0x73, 0x6f, 0x6c, 0x61, 0x72, 0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69,
0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x72,
0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79,
0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x77, 0x65, 0x65,
0x6b, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x12, 0x0a, 0x10, 0x5f,
0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42,
0x11, 0x0a, 0x0f, 0x5f, 0x79, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f,
0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x72, 0x61, 0x69,
0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x62, 0x61, 0x72, 0x6f, 0x6d, 0x5f, 0x72,
0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x62,
0x61, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f, 0x69, 0x6e,
0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x77, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x66,
0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x5f,
0x66, 0x22, 0x7d, 0x0a, 0x12, 0x54, 0x65, 0x6d, 0x70, 0x48, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74,
0x79, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x06, 0x74,
0x65, 0x6d, 0x70, 0x5f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x05, 0x74,
0x65, 0x6d, 0x70, 0x46, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x68, 0x75, 0x6d, 0x69, 0x64,
0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08, 0x68, 0x75, 0x6d,
0x69, 0x64, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x74, 0x65, 0x6d,
0x70, 0x5f, 0x66, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79,
0x22, 0x55, 0x0a, 0x0d, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12,
0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x48,
0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07,
0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x54, 0x5a, 0x52, 0x67, 0x69, 0x74, 0x65, 0x61,
0x2e, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x74, 0x65, 0x63, 0x68, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
0x74, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6d, 0x63, 0x67, 0x75, 0x69, 0x72,
0x65, 0x2f, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2d,
0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x70, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01,
0x28, 0x05, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x42, 0x08,
0x0a, 0x06, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x9c, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74,
0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x3d, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x47,
0x0a, 0x0f, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e,
0x74, 0x2e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65,
0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x57,
0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x48, 0x00, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x88,
0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79,
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x73,
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f,
0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb7, 0x0c, 0x0a,
0x0d, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x21,
0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d,
0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0e, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x64,
0x6f, 0x6f, 0x72, 0x5f, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0c, 0x74,
0x65, 0x6d, 0x70, 0x4f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x46, 0x88, 0x01, 0x01, 0x12, 0x27,
0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x5f, 0x66, 0x18,
0x05, 0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x0b, 0x74, 0x65, 0x6d, 0x70, 0x49, 0x6e, 0x64,
0x6f, 0x6f, 0x72, 0x46, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x68, 0x75, 0x6d, 0x69, 0x64,
0x69, 0x74, 0x79, 0x5f, 0x6f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28,
0x05, 0x48, 0x02, 0x52, 0x0f, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x4f, 0x75, 0x74,
0x64, 0x6f, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x68, 0x75, 0x6d, 0x69, 0x64,
0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05,
0x48, 0x03, 0x52, 0x0e, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x64, 0x6f,
0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x73, 0x70,
0x65, 0x65, 0x64, 0x5f, 0x6d, 0x70, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x48, 0x04, 0x52,
0x0c, 0x77, 0x69, 0x6e, 0x64, 0x53, 0x70, 0x65, 0x65, 0x64, 0x4d, 0x70, 0x68, 0x88, 0x01, 0x01,
0x12, 0x27, 0x0a, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x67, 0x75, 0x73, 0x74, 0x5f, 0x6d, 0x70,
0x68, 0x18, 0x09, 0x20, 0x01, 0x28, 0x01, 0x48, 0x05, 0x52, 0x0b, 0x77, 0x69, 0x6e, 0x64, 0x47,
0x75, 0x73, 0x74, 0x4d, 0x70, 0x68, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x6d, 0x61, 0x78,
0x5f, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x67, 0x75, 0x73, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28,
0x01, 0x48, 0x06, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x47, 0x75, 0x73,
0x74, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x64, 0x69, 0x72,
0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x48, 0x07, 0x52, 0x07, 0x77, 0x69, 0x6e, 0x64, 0x44, 0x69,
0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x10, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x64, 0x69, 0x72,
0x5f, 0x61, 0x76, 0x67, 0x5f, 0x31, 0x30, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x48, 0x08,
0x52, 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x44, 0x69, 0x72, 0x41, 0x76, 0x67, 0x31, 0x30, 0x6d, 0x88,
0x01, 0x01, 0x12, 0x13, 0x0a, 0x02, 0x75, 0x76, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x48, 0x09,
0x52, 0x02, 0x75, 0x76, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x6f, 0x6c, 0x61, 0x72,
0x5f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01,
0x48, 0x0a, 0x52, 0x0e, 0x73, 0x6f, 0x6c, 0x61, 0x72, 0x52, 0x61, 0x64, 0x69, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x5f,
0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0b, 0x52,
0x0c, 0x68, 0x6f, 0x75, 0x72, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01,
0x12, 0x27, 0x0a, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69,
0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0c, 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74,
0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x64, 0x61, 0x69,
0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x01,
0x48, 0x0d, 0x52, 0x0b, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88,
0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69,
0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0e, 0x52, 0x0c, 0x77, 0x65,
0x65, 0x6b, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a,
0x0f, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e,
0x18, 0x13, 0x20, 0x01, 0x28, 0x01, 0x48, 0x0f, 0x52, 0x0d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c,
0x79, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x29, 0x0a, 0x0e, 0x79, 0x65,
0x61, 0x72, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x14, 0x20, 0x01,
0x28, 0x01, 0x48, 0x10, 0x52, 0x0c, 0x79, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x52, 0x61, 0x69, 0x6e,
0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x27, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x72,
0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x01, 0x48, 0x11, 0x52, 0x0b,
0x74, 0x6f, 0x74, 0x61, 0x6c, 0x52, 0x61, 0x69, 0x6e, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x3c,
0x0a, 0x09, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x65, 0x61, 0x74,
0x68, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x09, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x11,
0x62, 0x61, 0x72, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69,
0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x01, 0x48, 0x12, 0x52, 0x0f, 0x62, 0x61, 0x72, 0x6f, 0x6d,
0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a,
0x11, 0x62, 0x61, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x5f,
0x69, 0x6e, 0x18, 0x18, 0x20, 0x01, 0x28, 0x01, 0x48, 0x13, 0x52, 0x0f, 0x62, 0x61, 0x72, 0x6f,
0x6d, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x23,
0x0a, 0x0b, 0x64, 0x65, 0x77, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x66, 0x18, 0x19, 0x20,
0x01, 0x28, 0x01, 0x48, 0x14, 0x52, 0x09, 0x64, 0x65, 0x77, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x46,
0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x63, 0x68, 0x69, 0x6c,
0x6c, 0x5f, 0x66, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x01, 0x48, 0x15, 0x52, 0x0a, 0x77, 0x69, 0x6e,
0x64, 0x43, 0x68, 0x69, 0x6c, 0x6c, 0x46, 0x88, 0x01, 0x01, 0x12, 0x57, 0x0a, 0x15, 0x74, 0x65,
0x6d, 0x70, 0x5f, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x6e, 0x73,
0x6f, 0x72, 0x73, 0x18, 0x1b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x6d, 0x62, 0x69,
0x65, 0x6e, 0x74, 0x2e, 0x77, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x6d, 0x70,
0x48, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x52, 0x13,
0x74, 0x65, 0x6d, 0x70, 0x48, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6e, 0x73,
0x6f, 0x72, 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x6f, 0x75, 0x74,
0x64, 0x6f, 0x6f, 0x72, 0x5f, 0x66, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x5f,
0x69, 0x6e, 0x64, 0x6f, 0x6f, 0x72, 0x5f, 0x66, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x68, 0x75, 0x6d,
0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x6f, 0x75, 0x74, 0x64, 0x6f, 0x6f, 0x72, 0x42, 0x12, 0x0a,
0x10, 0x5f, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x6f, 0x6f,
0x72, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64,
0x5f, 0x6d, 0x70, 0x68, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x67, 0x75,
0x73, 0x74, 0x5f, 0x6d, 0x70, 0x68, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x64,
0x61, 0x69, 0x6c, 0x79, 0x5f, 0x67, 0x75, 0x73, 0x74, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x77, 0x69,
0x6e, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f,
0x64, 0x69, 0x72, 0x5f, 0x61, 0x76, 0x67, 0x5f, 0x31, 0x30, 0x6d, 0x42, 0x05, 0x0a, 0x03, 0x5f,
0x75, 0x76, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x6f, 0x6c, 0x61, 0x72, 0x5f, 0x72, 0x61, 0x64,
0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x6c,
0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f,
0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x11, 0x0a,
0x0f, 0x5f, 0x77, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e,
0x42, 0x12, 0x0a, 0x10, 0x5f, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x5f, 0x72, 0x61, 0x69,
0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x79, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x5f,
0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x6f, 0x74, 0x61,
0x6c, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x62, 0x61,
0x72, 0x6f, 0x6d, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x42,
0x14, 0x0a, 0x12, 0x5f, 0x62, 0x61, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75,
0x74, 0x65, 0x5f, 0x69, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x77, 0x5f, 0x70, 0x6f,
0x69, 0x6e, 0x74, 0x5f, 0x66, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x63,
0x68, 0x69, 0x6c, 0x6c, 0x5f, 0x66, 0x22, 0x7d, 0x0a, 0x12, 0x54, 0x65, 0x6d, 0x70, 0x48, 0x75,
0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x1a, 0x0a, 0x06, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01,
0x48, 0x00, 0x52, 0x05, 0x74, 0x65, 0x6d, 0x70, 0x46, 0x88, 0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08,
0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01,
0x52, 0x08, 0x68, 0x75, 0x6d, 0x69, 0x64, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a,
0x07, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x66, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x68, 0x75, 0x6d,
0x69, 0x64, 0x69, 0x74, 0x79, 0x22, 0x55, 0x0a, 0x0d, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e,
0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
0x6e, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x88, 0x01,
0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x54, 0x5a, 0x52,
0x67, 0x69, 0x74, 0x65, 0x61, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x74, 0x65, 0x63, 0x68, 0x63,
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6d,
0x63, 0x67, 0x75, 0x69, 0x72, 0x65, 0x2f, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x2d, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x77, 0x65, 0x61, 0x74, 0x68,
0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
})
var (
@ -728,6 +738,7 @@ func file_weather_weather_proto_init() {
if File_weather_weather_proto != nil {
return
}
file_weather_weather_proto_msgTypes[0].OneofWrappers = []any{}
file_weather_weather_proto_msgTypes[2].OneofWrappers = []any{}
file_weather_weather_proto_msgTypes[3].OneofWrappers = []any{}
file_weather_weather_proto_msgTypes[4].OneofWrappers = []any{}

View File

@ -3,7 +3,8 @@ services:
ambient-local-exporter:
build: .
ports:
- 8080:8080
- 8080:8080 # HTTP
- 8081:8081 # GRPC
volumes:
- ./config.yaml:/app/config.yaml
command:

View File

@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
version: 0.1.2
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.9.0"
appVersion: "v0.10.2"
dependencies:
- name: hull

View File

@ -130,7 +130,7 @@ hull:
main:
image:
repository: _HT*hull.config.settings.repo
tag: _HT!{{ printf "v%s" _HT*hull.config.settings.tag }}
tag: _HT*hull.config.settings.tag
imagePullPolicy: Always
args:
- -config

48
main.go
View File

@ -17,28 +17,38 @@ import (
weathergrpc "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather/grpc"
)
const defaultMetricPrefix = "weather"
const (
defaultMetricPrefix = "weather"
)
func main() {
ctx, cncl := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt, unix.SIGTERM)
defer cncl()
// Config type for app, which implements go-app/config.AppConfig
awConfig := &config.AmbientLocalExporterConfig{
// Read config and environment, prepare an appCtx, and merge
// go-app config into ambient weather exporter app config
ctx, awConfig := app.MustLoadConfigInto(ctx, &config.AmbientLocalExporterConfig{
MetricPrefix: defaultMetricPrefix,
WeatherStations: make([]config.WeatherStation, 0),
}
})
// Read config and environment, set up logging, load up
// an appCtx, and prepare ambient weather local exporter
ctx, awConfig = app.MustLoadConfigInto(ctx, awConfig)
// Prepare the exporter
// Prepare the ambient exporter with our prepared config
// and set up logging, tracing, etc..
aw := ambient.New(ctx, awConfig).Init()
// Define and prepare the app
awApp := app.App{
// Load http and grpc routes, prepare the app
awApp := prepareApp(ctx, aw)
// Run app and wait
awApp.MustRun()
<-awApp.Done()
}
func prepareApp(ctx context.Context, aw *ambient.AmbientWeather) *app.App {
// Load ambient routes into app
awApp := &app.App{
AppContext: ctx,
// HTTP Endpoints for Ambient Weather Stations
HTTP: &httpopts.AppHTTP{
Funcs: []httpopts.HTTPFunc{
@ -51,8 +61,13 @@ func main() {
HandlerFunc: aw.GetAWNHandlerFunc(ctx),
},
},
// HTTP Listener that fixes broken requests generated by
// some versions of awn firmware
CustomListener: ambienthttp.NewAWNMutatingListener(ctx,
awConfig.HTTP.Listen), // Necessary to fix certain bad AWN firmware
aw.Config.HTTP.Listen), // Necessary to fix certain bad AWN firmware
// Health check funcs
HealthChecks: []httpopts.HealthCheckFunc{
// TODO: Implement
func(ctx context.Context) error {
@ -60,19 +75,18 @@ func main() {
},
},
},
// GRPC Service for retrieving current weather
// GRPC Service for retrieving weather
GRPC: &grpcopts.AppGRPC{
Services: []*grpcopts.GRPCService{
{
Name: "Weather Service",
Type: &weatherpb.AmbientLocalWeatherService_ServiceDesc,
Service: weathergrpc.GRPCWeather{},
Service: weathergrpc.NewGRPCWeather(ctx, aw.GetState()),
},
},
},
}
// Run and wait
awApp.MustRun()
<-awApp.Done()
return awApp
}

View File

@ -20,35 +20,63 @@ import (
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/provider/awn"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/provider/wunderground"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather/recorder"
)
const defUpdatesToKeep = 120
type AmbientWeather struct {
// 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
config *config.AmbientLocalExporterConfig
awnProvider provider.AmbientProvider
wuProvider provider.AmbientProvider
appCtx context.Context
metrics *weather.WeatherMetrics
l *zerolog.Logger
Config *config.AmbientLocalExporterConfig
awnProvider provider.AmbientProvider
wuProvider provider.AmbientProvider
weatherState *recorder.WeatherRecorder
appCtx context.Context
metrics *weather.WeatherMetrics
l *zerolog.Logger
*sync.RWMutex
}
func New(appCtx context.Context, awConfig *config.AmbientLocalExporterConfig) *AmbientWeather {
return &AmbientWeather{
config: awConfig,
appCtx: appCtx,
Config: awConfig,
appCtx: appCtx,
RWMutex: &sync.RWMutex{},
}
}
// Initialize with defaults, set logger from context
func (aw *AmbientWeather) Init() *AmbientWeather {
tracer := otel.GetTracer(aw.appCtx, "ambientWeather")
_, span := tracer.Start(aw.appCtx, "ambientWeather.init",
trace.WithAttributes(
attribute.String("name", aw.Config.Name),
attribute.Bool("grpcEnabled", aw.Config.GRPCEnabled()),
attribute.Bool("httpEnabled", aw.Config.HTTPEnabled()),
attribute.Int("weatherStations", len(aw.Config.WeatherStations)),
))
defer span.End()
aw.awnProvider = &awn.AWNProvider{}
aw.wuProvider = &wunderground.WUProvider{}
aw.l = zerolog.Ctx(aw.appCtx)
aw.l.Trace().Any("awConfig", aw.config).Send()
updatesToKeep := defUpdatesToKeep
if aw.Config.UpdatesToKeep != nil && *aw.Config.UpdatesToKeep > 0 {
updatesToKeep = *aw.Config.UpdatesToKeep
}
span.SetAttributes(attribute.Int("updatesToKeep", updatesToKeep))
aw.weatherState = recorder.NewWeatherRecorder(&recorder.Opts{
Ctx: aw.appCtx,
KeepLast: updatesToKeep,
})
aw.l.Trace().Any("awConfig", aw.Config).Send()
span.SetStatus(codes.Ok, "")
return aw
}
@ -78,6 +106,9 @@ func (aw *AmbientWeather) handleProviderRequest(
w http.ResponseWriter,
r *http.Request,
) {
aw.Lock()
defer aw.Unlock()
l := zerolog.Ctx(aw.appCtx)
tracer := otel.GetTracer(aw.appCtx, p.Name()+".http.handler")
@ -110,6 +141,9 @@ func (aw *AmbientWeather) handleProviderRequest(
updateSpan.SetAttributes(attribute.String("stationName", update.StationConfig.Name))
}
// Record state
aw.weatherState.Set(ctx, update)
// Update metrics
aw.metricsUpdate(ctx, p, update)
@ -227,18 +261,25 @@ func (aw *AmbientWeather) proxyUpdate(
}
func (aw *AmbientWeather) InitMetrics() {
if aw.config.MetricPrefix != "" {
weather.MetricPrefix = aw.config.MetricPrefix
if aw.Config.MetricPrefix != "" {
weather.MetricPrefix = aw.Config.MetricPrefix
}
aw.metrics = weather.MustInitMetrics(aw.appCtx)
}
func (aw *AmbientWeather) enrichStation(update *weather.WeatherUpdate) {
if update != nil && update.StationID != nil && *update.StationID != "" {
for _, station := range aw.config.WeatherStations {
for _, station := range aw.Config.WeatherStations {
if *update.StationID == station.AWNPassKey || *update.StationID == station.WundergroundID {
update.StationConfig = &station
}
}
}
}
func (aw *AmbientWeather) GetState() *recorder.WeatherRecorder {
aw.RLock()
defer aw.RUnlock()
return aw.weatherState
}

View File

@ -7,7 +7,8 @@ import (
// This configuration includes all config from go-app/config.AppConfig
type AmbientLocalExporterConfig struct {
MetricPrefix string `yaml:"metricPrefix" default:"weather" env:"AMBIENT_METRIC_PREFIX"`
WeatherStations []WeatherStation `yaml:"weatherStations"` // No env, too complex, not worth the time
UpdatesToKeep *int `yaml:"updatesToKeep" default:"1" env:"AMBIENT_UPDATES_TO_KEEP"`
WeatherStations []WeatherStation `yaml:"weatherStations" env:"weatherStations"` // No env, too complex, not worth the time
*config.AppConfig // Extends app config
}

View File

@ -0,0 +1,85 @@
package grpc
import (
"k8s.io/utils/ptr"
pb "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/api/v1alpha1/weather"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather"
)
func UpdatesToPbUpdates(u []*weather.WeatherUpdate) []*pb.WeatherUpdate {
updates := make([]*pb.WeatherUpdate, len(u))
for i, update := range u {
updates[i] = UpdateToPbUpdate(update)
}
return updates
}
func UpdateToPbUpdate(u *weather.WeatherUpdate) *pb.WeatherUpdate {
return &pb.WeatherUpdate{
StationName: u.StationConfig.Name,
StationType: derefStr(u.StationType),
StationId: derefStr(u.StationID),
TempOutdoorF: u.TempOutdoorF,
TempIndoorF: u.TempIndoorF,
HumidityOutdoor: int32ptr(u.HumidityOudoor),
HumidityIndoor: int32ptr(u.HumidityIndoor),
WindSpeedMph: u.WindSpeedMPH,
WindGustMph: u.WindGustMPH,
MaxDailyGust: u.MaxDailyGust,
WindDir: int32ptr(u.WindDir),
WindDirAvg_10M: int32ptr(u.WindDirAvg10m),
Uv: int32ptr(u.UV),
SolarRadiation: u.SolarRadiation,
HourlyRainIn: u.HourlyRainIn,
EventRainIn: u.EventRainIn,
DailyRainIn: u.DailyRainIn,
WeeklyRainIn: u.WeeklyRainIn,
MonthlyRainIn: u.MonthlyRainIn,
YearlyRainIn: u.YearlyRainIn,
TotalRainIn: u.TotalRainIn,
Batteries: batteriesToPbBatteries(u.Batteries),
BaromRelativeIn: u.BaromRelativeIn,
BaromAbsoluteIn: u.BaromAbsoluteIn,
DewPointF: u.DewPointF,
WindChillF: u.WindChillF,
TempHumiditySensors: thSensorsToPbSensors(u.TempHumiditySensors),
}
}
func batteriesToPbBatteries(batteries []weather.BatteryStatus) []*pb.BatteryStatus {
pbBatteries := make([]*pb.BatteryStatus, len(batteries))
for i, b := range batteries {
pbBatteries[i] = &pb.BatteryStatus{
Component: b.Component,
Status: int32ptr(b.Status),
}
}
return pbBatteries
}
func thSensorsToPbSensors(sensors []*weather.TempHumiditySensor) []*pb.TempHumiditySensor {
pbSensors := make([]*pb.TempHumiditySensor, len(sensors))
for i, s := range sensors {
pbSensors[i] = &pb.TempHumiditySensor{
Name: s.Name,
TempF: s.TempF,
Humidity: int32ptr(s.Humidity),
}
}
return pbSensors
}
func derefStr(s *string) string {
if s == nil {
return ""
}
return *s
}
func int32ptr(i *int) *int32 {
if i == nil {
return nil
}
return ptr.To(int32(*i))
}

View File

@ -0,0 +1,113 @@
package grpc
import (
"reflect"
"testing"
"time"
"k8s.io/utils/ptr"
pb "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/api/v1alpha1/weather"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/ambient/config"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather"
)
var mockUpdate = &weather.WeatherUpdate{
DateUTC: &time.Time{},
StationConfig: &config.WeatherStation{
Name: "50W",
Equipment: "WS-5000",
},
StationID: ptr.To("50W"),
StationType: ptr.To("WS-5000"),
TempOutdoorF: ptr.To(97.6),
TempIndoorF: ptr.To(77.6),
HumidityOudoor: ptr.To(50),
HumidityIndoor: ptr.To(50),
WindSpeedMPH: ptr.To(20.5),
WindGustMPH: ptr.To(30.5),
MaxDailyGust: ptr.To(40.0),
WindDir: ptr.To(180),
WindDirAvg10m: ptr.To(180),
UV: nil,
SolarRadiation: ptr.To(9.999),
HourlyRainIn: ptr.To(9.999),
EventRainIn: ptr.To(9.999),
DailyRainIn: ptr.To(9.999),
WeeklyRainIn: ptr.To(9.999),
MonthlyRainIn: ptr.To(9.999),
YearlyRainIn: ptr.To(9.999),
TotalRainIn: ptr.To(9.999),
Batteries: []weather.BatteryStatus{
{Component: "battery1", Status: ptr.To(1)},
{Component: "battery2", Status: ptr.To(1)},
},
BaromRelativeIn: ptr.To(9.999),
BaromAbsoluteIn: ptr.To(9.999),
DewPointF: ptr.To(9.999),
WindChillF: ptr.To(9.999),
TempHumiditySensors: []*weather.TempHumiditySensor{
{Name: "sensor1", TempF: ptr.To(99.999), Humidity: nil},
},
}
func TestUpdateToPbUpdate(t *testing.T) {
type args struct {
u *weather.WeatherUpdate
}
tests := []struct {
name string
args args
want *pb.WeatherUpdate
}{
{
name: "Map Update to PB",
args: args{u: mockUpdate},
want: &pb.WeatherUpdate{
StationName: mockUpdate.StationConfig.Name,
StationType: *mockUpdate.StationType,
StationId: *mockUpdate.StationID,
TempOutdoorF: mockUpdate.TempOutdoorF,
TempIndoorF: mockUpdate.TempIndoorF,
HumidityOutdoor: ptr.To(int32(*mockUpdate.HumidityOudoor)),
HumidityIndoor: ptr.To(int32(*mockUpdate.HumidityIndoor)),
WindSpeedMph: mockUpdate.WindSpeedMPH,
WindGustMph: mockUpdate.WindGustMPH,
MaxDailyGust: mockUpdate.MaxDailyGust,
WindDir: ptr.To(int32(*mockUpdate.WindDir)),
WindDirAvg_10M: ptr.To(int32(*mockUpdate.WindDirAvg10m)),
Uv: nil,
SolarRadiation: mockUpdate.SolarRadiation,
HourlyRainIn: mockUpdate.HourlyRainIn,
EventRainIn: mockUpdate.EventRainIn,
DailyRainIn: mockUpdate.DailyRainIn,
WeeklyRainIn: mockUpdate.WeeklyRainIn,
MonthlyRainIn: mockUpdate.MonthlyRainIn,
YearlyRainIn: mockUpdate.YearlyRainIn,
TotalRainIn: mockUpdate.TotalRainIn,
Batteries: []*pb.BatteryStatus{
{Component: mockUpdate.Batteries[0].Component, Status: ptr.To(int32(*mockUpdate.Batteries[0].Status))},
{Component: mockUpdate.Batteries[1].Component, Status: ptr.To(int32(*mockUpdate.Batteries[1].Status))},
},
BaromRelativeIn: mockUpdate.BaromRelativeIn,
BaromAbsoluteIn: mockUpdate.BaromAbsoluteIn,
DewPointF: mockUpdate.DewPointF,
WindChillF: mockUpdate.WindChillF,
TempHumiditySensors: []*pb.TempHumiditySensor{
{
Name: mockUpdate.TempHumiditySensors[0].Name,
TempF: mockUpdate.TempHumiditySensors[0].TempF,
Humidity: nil,
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := UpdateToPbUpdate(tt.args.u); !reflect.DeepEqual(got, tt.want) {
t.Errorf("UpdateToPbUpdate() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -3,11 +3,64 @@ package grpc
import (
"context"
"go.opentelemetry.io/otel/attribute"
otelcodes "go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
"gitea.libretechconsulting.com/rmcguire/go-app/pkg/otel"
pb "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/api/v1alpha1/weather"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather/recorder"
)
// TODO: Implement
type GRPCWeather struct {
ctx context.Context
ctx context.Context
recorder *recorder.WeatherRecorder
tracer trace.Tracer
*pb.UnimplementedAmbientLocalWeatherServiceServer
}
func NewGRPCWeather(ctx context.Context, recorder *recorder.WeatherRecorder) *GRPCWeather {
return &GRPCWeather{
ctx: ctx,
recorder: recorder,
tracer: otel.GetTracer(ctx, "grpcWeather"),
}
}
func (w *GRPCWeather) GetWeather(ctx context.Context, req *pb.GetWeatherRequest) (
*pb.GetWeatherResponse, error,
) {
ctx, span := w.tracer.Start(ctx, "getWeather")
defer span.End()
limit := 1
if req.Limit != nil {
if *req.Limit > 1 {
limit = int(*req.Limit)
}
}
span.SetAttributes(attribute.Int("limit", limit))
updates, err := w.recorder.Get(ctx, limit)
if err != nil {
span.RecordError(err)
span.SetStatus(otelcodes.Error, err.Error())
return nil, status.Errorf(codes.Internal, err.Error())
} else if len(updates) < 1 {
return nil, status.Errorf(codes.OutOfRange, "no weather available")
}
span.SetStatus(otelcodes.Ok, "")
return &pb.GetWeatherResponse{
LastUpdated: &timestamppb.Timestamp{
Seconds: updates[0].DateUTC.Unix(),
},
WeatherUpdates: UpdatesToPbUpdates(updates),
}, nil
}

View File

@ -0,0 +1,42 @@
package recorder
import (
"context"
"sync"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/trace"
"gitea.libretechconsulting.com/rmcguire/go-app/pkg/otel"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather"
)
type WeatherRecorder struct {
updates []*weather.WeatherUpdate
keep int
ctx context.Context
tracer trace.Tracer
meter metric.Meter
*sync.RWMutex
}
type Opts struct {
Ctx context.Context
KeepLast int
}
func NewWeatherRecorder(opts *Opts) *WeatherRecorder {
if opts.KeepLast < 1 {
opts.KeepLast = 1
}
return &WeatherRecorder{
updates: make([]*weather.WeatherUpdate, 0, opts.KeepLast),
keep: opts.KeepLast,
ctx: opts.Ctx,
tracer: otel.GetTracer(opts.Ctx, "weatherRecorder"),
meter: otel.GetMeter(opts.Ctx, "weatherRecorder"),
RWMutex: &sync.RWMutex{},
}
}

View File

@ -0,0 +1,90 @@
package recorder
import (
"context"
"errors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather"
)
// Returns last requested number of weather updates
// If negative number given, will return all weather observations
func (w *WeatherRecorder) Get(ctx context.Context, last int) (
[]*weather.WeatherUpdate, error,
) {
if last < 0 {
last = w.keep
} else if last < 1 {
last = 1
}
ctx, span := w.tracer.Start(ctx, "getWeatherRecorder")
span.SetAttributes(
attribute.Int("last", last),
attribute.Int("keep", w.keep),
attribute.Int("currentSize", w.Count(ctx)),
)
defer span.End()
updates, err := w.get(ctx, last)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
} else {
span.SetStatus(codes.Ok, "")
}
return updates, err
}
func (w *WeatherRecorder) get(ctx context.Context, last int) (
[]*weather.WeatherUpdate, error,
) {
span := trace.SpanFromContext(ctx)
w.RLock()
defer w.RUnlock()
span.AddEvent("acquired lock on recorder cache")
updates := w.updates
if w.count() == 0 {
err := errors.New("no recorded updates to get")
span.RecordError(err)
return nil, err
} else if w.count() <= last {
span.RecordError(errors.New("requested more updates than recorded"))
} else {
updates = updates[len(updates)-last:]
}
span.SetAttributes(attribute.Int("retrieved", len(updates)))
span.SetStatus(codes.Ok, "")
return updates, nil
}
// Returns count of retained weather updates
func (w *WeatherRecorder) Count(ctx context.Context) int {
_, span := w.tracer.Start(ctx, "countWeatherRecorder")
defer span.End()
count := w.count()
span.SetAttributes(attribute.Int("count", count))
span.SetStatus(codes.Ok, "")
return count
}
func (w *WeatherRecorder) count() int {
w.RLock()
defer w.RUnlock()
return len(w.updates)
}

View File

@ -0,0 +1,35 @@
package recorder
import (
"context"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather"
)
func (w *WeatherRecorder) Set(ctx context.Context, u *weather.WeatherUpdate) error {
ctx, span := w.tracer.Start(ctx, "recordWeatherUpdate")
span.SetAttributes(
attribute.Int("countWeatherUpdates", w.Count(ctx)),
attribute.Int("keepUpdates", w.keep),
)
defer span.End()
return w.set(span, u)
}
func (w *WeatherRecorder) set(span trace.Span, u *weather.WeatherUpdate) error {
w.Lock()
defer w.Unlock()
if len(w.updates) > w.keep {
w.updates = w.updates[1:]
span.AddEvent("trimmed recorded updates by 1")
}
w.updates = append(w.updates, u)
span.AddEvent("recorded weather update")
return nil
}

View File

@ -7,6 +7,7 @@ option go_package = "gitea.libretechconsulting.com/rmcguire/ambient-local-export
message GetWeatherRequest {
GetWeatherOpts opts = 1;
optional int32 limit = 2;
}
message GetWeatherResponse{
@ -23,41 +24,41 @@ message WeatherUpdate {
string station_name = 1;
string station_type = 2;
string station_id = 3;
optional double temp_outdoor_f = 4;
optional double temp_indoor_f = 5;
optional int32 humidity_outdoor = 6;
optional int32 humidity_indoor = 7;
optional double wind_speed_mph = 8;
optional double wind_gust_mph = 9;
optional double max_daily_gust = 10;
optional int32 wind_dir = 11;
optional int32 wind_dir_avg_10m = 12;
optional int32 uv = 13;
optional double solar_radiation = 14;
optional double hourly_rain_in = 15;
optional double event_rain_in = 16;
optional double daily_rain_in = 17;
optional double weekly_rain_in = 18;
optional double monthly_rain_in = 19;
optional double yearly_rain_in = 20;
optional double total_rain_in = 21;
repeated BatteryStatus batteries = 22;
optional double barom_relative_in = 23;
optional double barom_absolute_in = 24;
optional double dew_point_f = 25;
optional double wind_chill_f = 26;
repeated TempHumiditySensor temp_humidity_sensors = 27;
optional double temp_outdoor_f = 4;
optional double temp_indoor_f = 5;
optional int32 humidity_outdoor = 6;
optional int32 humidity_indoor = 7;
optional double wind_speed_mph = 8;
optional double wind_gust_mph = 9;
optional double max_daily_gust = 10;
optional int32 wind_dir = 11;
optional int32 wind_dir_avg_10m = 12;
optional int32 uv = 13;
optional double solar_radiation = 14;
optional double hourly_rain_in = 15;
optional double event_rain_in = 16;
optional double daily_rain_in = 17;
optional double weekly_rain_in = 18;
optional double monthly_rain_in = 19;
optional double yearly_rain_in = 20;
optional double total_rain_in = 21;
repeated BatteryStatus batteries = 22;
optional double barom_relative_in = 23;
optional double barom_absolute_in = 24;
optional double dew_point_f = 25;
optional double wind_chill_f = 26;
repeated TempHumiditySensor temp_humidity_sensors = 27;
}
// Represents a temperature and humidity sensor
message TempHumiditySensor {
string name = 1;
optional double temp_f = 2;
optional int32 humidity = 3;
string name = 1;
optional double temp_f = 2;
optional int32 humidity = 3;
}
// Represents battery status for different components
message BatteryStatus {
string component = 1;
optional int32 status = 2;
string component = 1;
optional int32 status = 2;
}