7 Commits

Author SHA1 Message Date
rmcguire dcdf5e4230 bump chart
Build and Publish / go-binaries (push) Successful in 1m41s
Build and Publish / check-chart (push) Successful in 10s
Build and Publish / helm-release (push) Has been skipped
Build and Publish / container-images (push) Successful in 5m19s
2026-07-05 14:56:30 -04:00
rmcguire 1b42d26ffc add changelog 2026-07-05 14:56:10 -04:00
rmcguire a8e0a6ef1e support tls insecure due to cloudblade old TLS cert 2026-07-05 14:53:10 -04:00
rmcguire 059b89b5cd add TODO
Build and Publish / helm-release (push) Has been skipped
Build and Publish / container-images (push) Has been skipped
Build and Publish / go-binaries (push) Has been skipped
Build and Publish / check-chart (push) Successful in 10s
2026-07-04 17:47:54 -04:00
rmcguire 87e53bd620 bump chart versions
Build and Publish / container-images (push) Successful in 2m10s
Build and Publish / helm-release (push) Has been skipped
Build and Publish / check-chart (push) Successful in 16s
Build and Publish / go-binaries (push) Successful in 5m29s
2026-07-04 17:42:50 -04:00
rmcguire c481d3f032 add ca-certs to image
Build and Publish / check-chart (push) Successful in 14s
Build and Publish / helm-release (push) Has been skipped
Build and Publish / go-binaries (push) Successful in 2m35s
Build and Publish / container-images (push) Successful in 3m1s
2026-07-04 17:42:03 -04:00
rmcguire 1918138dbf fix chart app version
Build and Publish / container-images (push) Successful in 2m12s
Build and Publish / helm-release (push) Has been skipped
Build and Publish / check-chart (push) Successful in 17s
Build and Publish / go-binaries (push) Successful in 4m31s
2026-07-04 17:27:34 -04:00
7 changed files with 79 additions and 26 deletions
+7
View File
@@ -30,6 +30,13 @@ that's all it takes — no extra wiring.
- `costPerKWH` is **US dollars per kWh** (0.18 = 18¢), feeding - `costPerKWH` is **US dollars per kWh** (0.18 = 18¢), feeding
`econet_energy_cost_dollars`. `econet_energy_cost_dollars`.
- `econetTLSInsecure` (env `ECONET_TLS_INSECURE`) skips TLS certificate
verification when connecting to the EcoNet cloud API. It exists because the
upstream host (cloudblade) serves a
DigiCert Global Root G1 chain, which is no longer trusted by default in
current root stores. **Evaluate removing this later** — prefer fixing the
trust chain (e.g. bundling the needed intermediate/root CA) over disabling
verification outright.
## Metrics conventions ## Metrics conventions
+50 -15
View File
@@ -1,18 +1,53 @@
# v0.7.0 # Changelog
* feat: Add HTTP log exclusion regex paths to configuration schema.
* chore: Update Go version to 1.25.
* chore: Update module dependencies.
# v0.6.0 All notable changes to econet-exporter are documented here. The format is
* feat: Introduce Model Context Protocol (MCP) server with a demo random fact tool. based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
* feat: Add MCP server configuration file (`contrib/mcpinspector.json`). project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
* deps: Update Go module dependencies, including `bufbuild/protovalidate`, `go-app`, `grpc-gateway`, `googleapis/api`, `grpc`, `protobuf`, `golang.org/x/exp`, and `googleapis/rpc`.
* deps: Add new Go module dependencies: `modelcontextprotocol/go-sdk` and `k8s.io/utils`.
# v0.5.0 ## [v0.2.0] - 2026-07-05
* Added OpenTelemetry tracing for application startup. ### Added
* Updated Go module dependencies, including `protovalidate`, `go-app`, `grpc`, and OpenTelemetry related packages.
* Enhanced `Makefile` `rename` target to update the application name constant in `main.go`. * `econetTLSInsecure` config option (env `ECONET_TLS_INSECURE`) to skip TLS
* Configured `air` live-reloading to exclude the `proto` directory. certificate verification when
* Refactored application initialization logic for improved modularity and OpenTelemetry integration. connecting to the Rheem/EcoNet cloud API. The upstream host (cloudblade)
serves an old/untrusted certificate chain; this is a stopgap and should be
removed once the upstream certificate is fixed. See AGENTS.md.
* `TODO.md` tracking outstanding work (CA cert bundle, mutating proto RPCs,
additional tracing spans).
## [v0.1.2] - 2026-07-04
### Added
* CA certificate bundle baked into the container image so the exporter can
establish TLS connections to the EcoNet API.
### Changed
* Bumped Helm chart versions.
## [v0.1.1] - 2026-07-04
### Fixed
* Corrected the Helm chart `appVersion`.
## [v0.1.0] - 2026-07-04
Initial release of the EcoNet exporter for Rheem / Rheemcloud water heaters,
built on the `go-app` framework.
### Added
* `EconetService` owning a single shared `*rheemcloud.Client` across the gRPC,
MCP, and metrics sub-servers (fail-fast on missing credentials).
* gRPC API (`ListDevices`, `GetDevice`) with proto definitions and
grpc-gateway REST bindings.
* MCP server at `/api/mcp` exposing a `list_water_heaters` tool.
* OpenTelemetry observable gauges for device state (temperature, mode, energy
and water usage, cost) with a background usage poller, exported to
Prometheus. Units are encoded in metric names (`_fahrenheit`, `_kwh`,
`_gallons`, `_dollars`).
* `costPerKWH` config (US dollars per kWh) feeding `econet_energy_cost_dollars`.
* Helm chart for Kubernetes deployment.
+2
View File
@@ -19,6 +19,8 @@ FROM alpine:latest
ARG APP_NAME=econet-exporter ARG APP_NAME=econet-exporter
RUN apk add --no-cache ca-certificates
WORKDIR /app WORKDIR /app
USER 100:101 USER 100:101
+6 -9
View File
@@ -1,10 +1,7 @@
# Demo app TODO # econet-exporter TODO
- [ ] Fix Docerfile for ca cert bundle (TLS error to API host)
- [ ] Add mutating proto RPCs (change mode, etc..)
- [ ] Add spans to things
- [x] Create generic interface for implenting a service
- [x] Create config sample not called demo, so it is more easily reused
- [x] Update README for tagging/versioning/pipeline info
- [x] Update README for detail on installing protoc tools and make
- [x] Rename project
- [x] Finish grpc sample implementation
- [x] Add Dockerfile
- [x] Add gitea CI
+2 -2
View File
@@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # 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. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.3 version: 0.1.5
# This is the version number of the application being deployed. This version number should be # 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 # 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. # follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes. # It is recommended to use it with quotes.
appVersion: "v0.7.0" appVersion: "v0.2.0"
dependencies: dependencies:
- name: hull - name: hull
+3
View File
@@ -22,6 +22,9 @@ type ServiceConfig struct {
EconetEmail string `yaml:"econetEmail" json:"econetEmail,omitempty" env:"ECONET_EMAIL"` EconetEmail string `yaml:"econetEmail" json:"econetEmail,omitempty" env:"ECONET_EMAIL"`
EconetPassword string `yaml:"econetPassword" json:"econetPassword,omitempty" env:"ECONET_PASSWORD"` EconetPassword string `yaml:"econetPassword" json:"econetPassword,omitempty" env:"ECONET_PASSWORD"`
// Necessary due to ancient TLS certificate run by cloudblade that isn't trusted in modern ca-certificate bundles
EconetTLSInsecure bool `yaml:"econetTLSInsecure" json:"econetTLSInsecure,omitempty" env:"ECONET_TLS_INSECURE" default:"false"`
// CostPerKWH is the electricity price in US dollars per kWh (e.g. 0.18 // CostPerKWH is the electricity price in US dollars per kWh (e.g. 0.18
// means 18 cents/kWh, NOT 18). It derives the econet_energy_cost_dollars // means 18 cents/kWh, NOT 18). It derives the econet_energy_cost_dollars
// metric from kWh energy usage. // metric from kWh energy usage.
+9
View File
@@ -5,8 +5,10 @@ package econet
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"log/slog" "log/slog"
"net/http"
rheemcloud "github.com/kevinburke/rheemcloud-go" rheemcloud "github.com/kevinburke/rheemcloud-go"
@@ -55,6 +57,13 @@ func connect(ctx context.Context, cfg *config.ServiceConfig) (*rheemcloud.Client
} }
client, err := rheemcloud.Connect(ctx, cfg.EconetEmail, cfg.EconetPassword, &rheemcloud.Config{ client, err := rheemcloud.Connect(ctx, cfg.EconetEmail, cfg.EconetPassword, &rheemcloud.Config{
Logger: slog.Default(), Logger: slog.Default(),
HTTPClient: &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: cfg.EconetTLSInsecure,
},
},
},
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("econet: connect failed: %w", err) return nil, fmt.Errorf("econet: connect failed: %w", err)