Server 2.4.0, app 2.11.1: ABRP forwarding removed from the server
The car sends live data to ABRP itself, and the car and the server go over the same mobile connection: when the car cannot reach ABRP, it cannot reach the server either, so the server's fallback bought nothing. The forwarder, its ABRP_* settings and abrpSentUtc are gone; the server only stores. The app stops sending abrpSentUtc (the server ignores unknown fields, so 2.11.0 keeps working) and its texts no longer promise a server fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QLJfZQZeAKAwSqViTmLzki
This commit is contained in:
+20
-40
@@ -1,5 +1,6 @@
|
||||
// Command server is the Nils' MG4 car server: the API the car writes its telemetry,
|
||||
// consumption and charging sessions to, stored in InfluxDB 2 and forwarded live to ABRP.
|
||||
// consumption and charging sessions to, stored in InfluxDB 2. The car sends live data to ABRP
|
||||
// itself.
|
||||
// Dashboards are Grafana's job; Grafana reads the same bucket directly.
|
||||
package main
|
||||
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
@@ -22,33 +22,28 @@ const (
|
||||
)
|
||||
|
||||
type config struct {
|
||||
listenAddr string
|
||||
influxURL string
|
||||
influxToken string
|
||||
influxOrg string
|
||||
influxBucket string
|
||||
ingestToken string
|
||||
abrpAPIKey string
|
||||
abrpUserToken string
|
||||
abrpMinInterval time.Duration
|
||||
approvalPass string
|
||||
publicURL string
|
||||
listenAddr string
|
||||
influxURL string
|
||||
influxToken string
|
||||
influxOrg string
|
||||
influxBucket string
|
||||
ingestToken string
|
||||
approvalPass string
|
||||
publicURL string
|
||||
}
|
||||
|
||||
// loadConfig reads the environment and fails closed: a missing InfluxDB setting or a
|
||||
// short ingest token stops the server from starting rather than serving something broken.
|
||||
func loadConfig(getenv func(string) string) (config, error) {
|
||||
c := config{
|
||||
listenAddr: getenv("LISTEN_ADDR"),
|
||||
influxURL: getenv("INFLUX_URL"),
|
||||
influxToken: getenv("INFLUX_TOKEN"),
|
||||
influxOrg: getenv("INFLUX_ORG"),
|
||||
influxBucket: getenv("INFLUX_BUCKET"),
|
||||
ingestToken: getenv("INGEST_TOKEN"),
|
||||
abrpAPIKey: getenv("ABRP_API_KEY"),
|
||||
abrpUserToken: getenv("ABRP_USER_TOKEN"),
|
||||
approvalPass: getenv("APPROVAL_PASSWORD"),
|
||||
publicURL: getenv("PUBLIC_URL"),
|
||||
listenAddr: getenv("LISTEN_ADDR"),
|
||||
influxURL: getenv("INFLUX_URL"),
|
||||
influxToken: getenv("INFLUX_TOKEN"),
|
||||
influxOrg: getenv("INFLUX_ORG"),
|
||||
influxBucket: getenv("INFLUX_BUCKET"),
|
||||
ingestToken: getenv("INGEST_TOKEN"),
|
||||
approvalPass: getenv("APPROVAL_PASSWORD"),
|
||||
publicURL: getenv("PUBLIC_URL"),
|
||||
}
|
||||
if c.listenAddr == "" {
|
||||
c.listenAddr = ":8080"
|
||||
@@ -69,14 +64,6 @@ func loadConfig(getenv func(string) string) (config, error) {
|
||||
if c.approvalPass != "" && len(c.approvalPass) < minApprovalPasswordLength {
|
||||
return config{}, fmt.Errorf("APPROVAL_PASSWORD must be at least %d characters", minApprovalPasswordLength)
|
||||
}
|
||||
c.abrpMinInterval = 5 * time.Second
|
||||
if raw := getenv("ABRP_MIN_INTERVAL_SECONDS"); raw != "" {
|
||||
seconds, err := strconv.ParseFloat(raw, 64)
|
||||
if err != nil || seconds < 0 {
|
||||
return config{}, errors.New("ABRP_MIN_INTERVAL_SECONDS must be a non-negative number")
|
||||
}
|
||||
c.abrpMinInterval = time.Duration(seconds * float64(time.Second))
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -90,12 +77,6 @@ func main() {
|
||||
|
||||
store := NewInfluxStore(cfg.influxURL, cfg.influxToken, cfg.influxOrg, cfg.influxBucket)
|
||||
defer store.Close()
|
||||
forwarder := &Forwarder{
|
||||
APIKey: cfg.abrpAPIKey,
|
||||
UserToken: cfg.abrpUserToken,
|
||||
MinInterval: cfg.abrpMinInterval,
|
||||
Client: &http.Client{Timeout: 10 * time.Second},
|
||||
}
|
||||
// Paired cars' tokens must be known before the first request; starting without them
|
||||
// would answer every paired car with 401, so a failed load stops the start instead.
|
||||
loadCtx, cancelLoad := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
@@ -106,8 +87,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
pairing := NewPairing(cfg.approvalPass, devices)
|
||||
api := &API{Store: store, IngestToken: cfg.ingestToken, Forwarder: forwarder,
|
||||
Pairing: pairing, PublicURL: cfg.publicURL}
|
||||
api := &API{Store: store, IngestToken: cfg.ingestToken, Pairing: pairing, PublicURL: cfg.publicURL}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: cfg.listenAddr,
|
||||
@@ -122,7 +102,7 @@ func main() {
|
||||
defer stop()
|
||||
go func() {
|
||||
slog.Info("listening", "addr", cfg.listenAddr, "bucket", cfg.influxBucket,
|
||||
"abrp", forwarder.configured(), "pairing", pairing.Enabled(), "pairedDevices", len(devices))
|
||||
"pairing", pairing.Enabled(), "pairedDevices", len(devices))
|
||||
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
slog.Error("server failed", "error", err)
|
||||
os.Exit(1)
|
||||
|
||||
Reference in New Issue
Block a user