diff --git a/Dockerfile b/Dockerfile index 780a663fa..79fbc175f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -97,7 +97,5 @@ EXPOSE 8899/udp # SMA Energy Manager EXPOSE 9522/udp -HEALTHCHECK --interval=60s --start-period=60s --timeout=30s --retries=3 CMD [ "evcc", "health" ] - ENTRYPOINT [ "/app/entrypoint.sh" ] CMD [ "evcc" ] diff --git a/cmd/health.go b/cmd/health.go deleted file mode 100644 index 8f1ba69c9..000000000 --- a/cmd/health.go +++ /dev/null @@ -1,58 +0,0 @@ -//go:build !windows - -package cmd - -import ( - "fmt" - "net/http" - "os" - "time" - - "github.com/evcc-io/evcc/server" - "github.com/spf13/cobra" - "github.com/tv42/httpunix" -) - -const serviceName = "evcc" - -// healthCmd represents the meter command -var healthCmd = &cobra.Command{ - Use: "health", - Short: "Check application health", - Run: runHealth, -} - -func init() { - rootCmd.AddCommand(healthCmd) -} - -func runHealth(cmd *cobra.Command, args []string) { - u := &httpunix.Transport{ - DialTimeout: 100 * time.Millisecond, - RequestTimeout: 1 * time.Second, - ResponseHeaderTimeout: 1 * time.Second, - } - - u.RegisterLocation(serviceName, server.SocketPath) - - client := http.Client{ - Transport: u, - } - - var ok bool - resp, err := client.Get(fmt.Sprintf("http+unix://%s/health", serviceName)) - - if err == nil { - resp.Body.Close() - - if resp.StatusCode == http.StatusOK { - log.INFO.Printf("health check ok") - ok = true - } - } - - if !ok { - log.ERROR.Printf("health check failed") - os.Exit(1) - } -} diff --git a/cmd/root.go b/cmd/root.go index 2db4daebf..fe123aab3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -441,9 +441,6 @@ func runRoot(cmd *cobra.Command, args []string) { }() } - // uds health check listener - go server.HealthListener(site) - // wait for shutdown <-stopC diff --git a/core/health.go b/core/health.go deleted file mode 100644 index 9aa030872..000000000 --- a/core/health.go +++ /dev/null @@ -1,42 +0,0 @@ -package core - -import ( - "sync" - "time" -) - -// Health is a health checker that needs regular updates to stay healthy -type Health struct { - mux sync.Mutex - updated time.Time - timeout time.Duration -} - -// NewHealth creates new health checker -func NewHealth(timeout time.Duration) *Health { - return &Health{timeout: timeout} -} - -// Healthy returns health status based on last update timestamp -func (health *Health) Healthy() bool { - if health == nil { - return false - } - - health.mux.Lock() - defer health.mux.Unlock() - - return time.Since(health.updated) < health.timeout -} - -// Update updates the health timer on each loadpoint update -func (health *Health) Update() { - if health == nil { - return - } - - health.mux.Lock() - defer health.mux.Unlock() - - health.updated = time.Now() -} diff --git a/core/site.go b/core/site.go index 6ce1a5744..087d5023c 100644 --- a/core/site.go +++ b/core/site.go @@ -76,8 +76,6 @@ type Site struct { valueChan chan<- util.Param // client push messages lpUpdateChan chan *Loadpoint - *Health - sync.RWMutex log *util.Logger @@ -987,8 +985,6 @@ func (site *Site) update(lp updater) { ) } - site.Health.Update() - site.publishTariffs(greenShareHome, greenShareLoadpoints) if telemetry.Enabled() && totalChargePower > standbyPower { @@ -1120,8 +1116,6 @@ func (site *Site) loopLoadpoints(next chan<- updater) { // Run is the main control loop. It reacts to trigger events by // updating measurements and executing control logic. func (site *Site) Run(stopC chan struct{}, interval time.Duration) { - site.Health = NewHealth(time.Minute + interval) - if max := 30 * time.Second; interval < max { site.log.INFO.Printf("interval <%.0fs can lead to unexpected behavior, see https://docs.evcc.io/docs/reference/configuration/interval", max.Seconds()) } diff --git a/core/site/api.go b/core/site/api.go index c7210224d..d7c94cf84 100644 --- a/core/site/api.go +++ b/core/site/api.go @@ -14,7 +14,6 @@ type Publisher interface { type API interface { Publisher - Healthy() bool Loadpoints() []loadpoint.API Vehicles() Vehicles diff --git a/go.mod b/go.mod index c097adf3b..d5d0a0093 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,6 @@ require ( github.com/teslamotors/vehicle-command v0.4.0 github.com/tess1o/go-ecoflow v1.1.1-0.20251003083510-2ccc15a17e29 github.com/traefik/yaegi v0.16.1 - github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c github.com/volkszaehler/mbmd v0.0.0-20260107074546-6cbf4285cea8 gitlab.com/bboehmke/sunny v0.16.0 go.bug.st/serial v1.6.4 diff --git a/go.sum b/go.sum index a50979388..8cbccecb0 100644 --- a/go.sum +++ b/go.sum @@ -757,8 +757,6 @@ github.com/tess1o/go-ecoflow v1.1.1-0.20251003083510-2ccc15a17e29/go.mod h1:kqrf github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/traefik/yaegi v0.16.1 h1:f1De3DVJqIDKmnasUF6MwmWv1dSEEat0wcpXhD2On3E= github.com/traefik/yaegi v0.16.1/go.mod h1:4eVhbPb3LnD2VigQjhYbEJ69vDRFdT2HQNrXx8eEwUY= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= diff --git a/server/http.go b/server/http.go index 940e3ebf1..170c6d008 100644 --- a/server/http.go +++ b/server/http.go @@ -140,7 +140,6 @@ func (s *HTTPd) RegisterSiteHandlers(site site.API, valueChan chan<- util.Param) } routes := map[string]route{ - "health": {"GET", "/health", healthHandler(site)}, "buffersoc": {"POST", "/buffersoc/{value:[0-9.]+}", floatHandler(site.SetBufferSoc, site.GetBufferSoc)}, "bufferstartsoc": {"POST", "/bufferstartsoc/{value:[0-9.]+}", floatHandler(site.SetBufferStartSoc, site.GetBufferStartSoc)}, "batterydischargecontrol": {"POST", "/batterydischargecontrol/{value:[01truefalse]+}", boolHandler(site.SetBatteryDischargeControl, site.GetBatteryDischargeControl)}, diff --git a/server/http_site_handler.go b/server/http_site_handler.go index eca99afa1..77a20a11f 100644 --- a/server/http_site_handler.go +++ b/server/http_site_handler.go @@ -236,20 +236,6 @@ func stateHandler(cache *util.ParamCache) http.HandlerFunc { } } -// healthHandler returns current charge mode -func healthHandler(site site.API) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - if site == nil || !site.Healthy() { - w.WriteHeader(http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "text/plain") - w.WriteHeader(http.StatusOK) - fmt.Fprintln(w, "OK") - } -} - // tariffHandler returns the configured tariff func tariffHandler(site site.API) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { diff --git a/server/mcp/openapi.json b/server/mcp/openapi.json index fd302146b..ea25e1a99 100644 --- a/server/mcp/openapi.json +++ b/server/mcp/openapi.json @@ -1087,29 +1087,6 @@ ] } }, - "/health": { - "get": { - "description": "Returns 200 if the evcc loop runs as expected.", - "operationId": "healthCheck", - "responses": { - "200": { - "content": { - "text/plain": { - "schema": { - "example": "OK", - "type": "string" - } - } - }, - "description": "Success" - } - }, - "summary": "Health check", - "tags": [ - "general" - ] - } - }, "/loadpoints/{id}/batteryboost/{enable}": { "post": { "description": "Enable or disable battery boost.", diff --git a/server/mcp/openapi.md b/server/mcp/openapi.md index 98cf41e7f..e6f43e3c6 100644 --- a/server/mcp/openapi.md +++ b/server/mcp/openapi.md @@ -230,12 +230,6 @@ call getState { } ``` -## healthCheck - -Returns 200 if the evcc loop runs as expected. - -**Tags:** general - ## removeGlobalSmartCostLimit Convenience method to remove limit for all loadpoints at once. Value is applied to each individual loadpoint. diff --git a/server/openapi.yaml b/server/openapi.yaml index 45aeb155d..a6b7859db 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -188,21 +188,6 @@ paths: responses: "200": $ref: "#/components/responses/NumberResult" - /health: - get: - operationId: healthCheck - summary: Health check - description: Returns 200 if the evcc loop runs as expected. - tags: - - general - responses: - "200": - description: Success - content: - text/plain: - schema: - type: string - example: OK /loadpoints/{id}/batteryboost/{enable}: post: operationId: setLoadpointBatteryBoost diff --git a/server/uds.go b/server/uds.go deleted file mode 100644 index 0dbdc7f42..000000000 --- a/server/uds.go +++ /dev/null @@ -1,45 +0,0 @@ -//go:build !windows - -package server - -import ( - "net" - "net/http" - "os" - - "github.com/evcc-io/evcc/cmd/shutdown" - "github.com/evcc-io/evcc/core/site" -) - -// SocketPath is the unix domain socket path -const SocketPath = "/tmp/evcc" - -// removeIfExists deletes file if it exists or fails -func removeIfExists(file string) { - if _, err := os.Stat(file); err == nil { - if err := os.RemoveAll(file); err != nil { - log.FATAL.Fatal(err) - } - } -} - -// HealthListener attaches listener to unix domain socket and runs listener -func HealthListener(site site.API) { - removeIfExists(SocketPath) - - l, err := net.Listen("unix", SocketPath) - if err != nil { - log.FATAL.Fatal(err) - } - - mux := http.NewServeMux() - httpd := http.Server{Handler: mux} - mux.HandleFunc("/health", healthHandler(site)) - - go func() { _ = httpd.Serve(l) }() - - shutdown.Register(func() { - _ = l.Close() - removeIfExists(SocketPath) // cleanup - }) -} diff --git a/server/uds_windows.go b/server/uds_windows.go deleted file mode 100644 index 17c14015e..000000000 --- a/server/uds_windows.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build windows - -package server - -import "github.com/evcc-io/evcc/core/site" - -// HealthListener attaches listener to unix domain socket -func HealthListener(_ site.API) { - // nop -}