Target Charge: fix timezones (#3382) (#3386)

This commit is contained in:
Michael Geers 2022-05-18 06:35:26 +02:00 • committed by GitHub
parent ee8d3db356
commit aad8166b5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 92 additions and 25 deletions

View file

@ -86,7 +86,7 @@ func NewHTTPd(addr string, site site.API, hub *SocketHub, cache *util.Cache) *HT
"mincurrent": {[]string{"POST", "OPTIONS"}, "/mincurrent/{value:[0-9]+}", minCurrentHandler(lp)},
"maxcurrent": {[]string{"POST", "OPTIONS"}, "/maxcurrent/{value:[0-9]+}", maxCurrentHandler(lp)},
"phases": {[]string{"POST", "OPTIONS"}, "/phases/{value:[0-9]+}", phasesHandler(lp)},
"targetcharge": {[]string{"POST", "OPTIONS"}, "/targetcharge/{soc:[0-9]+}/{time:[0-9TZ:-]+}", targetChargeHandler(lp)},
"targetcharge": {[]string{"POST", "OPTIONS"}, "/targetcharge/{soc:[0-9]+}/{time:[0-9TZ:.-]+}", targetChargeHandler(lp)},
"targetcharge2": {[]string{"DELETE", "OPTIONS"}, "/targetcharge", targetChargeRemoveHandler(lp)},
"vehicle": {[]string{"DELETE", "OPTIONS"}, "/vehicle", vehicleRemoveHandler(lp)},
"remotedemand": {[]string{"POST", "OPTIONS"}, "/remotedemand/{demand:[a-z]+}/{source::[0-9a-zA-Z_-]+}", remoteDemandHandler(lp)},

View file

@ -5,7 +5,6 @@ import (
"fmt"
"io/fs"
"net/http"
"os"
"strconv"
"text/template"
"time"
@ -222,18 +221,8 @@ func remoteDemandHandler(lp loadpoint.API) http.HandlerFunc {
}
}
func timezone() *time.Location {
tz := os.Getenv("TZ")
if tz == "" {
tz = "Local"
}
loc, _ := time.LoadLocation(tz)
return loc
}
// targetChargeHandler updates target soc
func targetChargeHandler(loadpoint loadpoint.API) http.HandlerFunc {
func targetChargeHandler(loadpoint targetCharger) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
@ -246,7 +235,7 @@ func targetChargeHandler(loadpoint loadpoint.API) http.HandlerFunc {
}
timeS, ok := vars["time"]
timeV, err := time.ParseInLocation("2006-01-02T15:04:05", timeS, timezone())
timeV, err := time.Parse(time.RFC3339, timeS)
if !ok || err != nil {
jsonError(w, http.StatusBadRequest, err)
@ -291,3 +280,9 @@ func socketHandler(hub *SocketHub) http.HandlerFunc {
ServeWebsocket(hub, w, r)
}
}
// TargetCharger defines target charge related loadpoint operations
type targetCharger interface {
// SetTargetCharge sets the charge targetSoC
SetTargetCharge(time.Time, int)
}

View file

@ -0,0 +1,73 @@
package server
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gorilla/mux"
)
type mockLoadpoint struct {
SoC int
TargetTime time.Time
}
func (lp *mockLoadpoint) SetTargetCharge(time time.Time, soc int) {
lp.SoC = soc
lp.TargetTime = time
}
func TestTargetChargeHandler(t *testing.T) {
tc := []struct {
inSoC string
inTime string
statusCode int
outSoC int
outTime time.Time
}{
{"70", "2022-05-17T06:20:59.509Z", http.StatusOK,
70, time.Date(2022, 05, 17, 06, 20, 59, 509000000, time.UTC)},
{"foo", "2022-05-17T06:20:59.509Z", http.StatusBadRequest, 0, time.Time{}},
{"70", "2022-05-17 06:20:59", http.StatusBadRequest, 0, time.Time{}},
}
for _, tc := range tc {
mockLp := &mockLoadpoint{}
handler := http.HandlerFunc(targetChargeHandler(mockLp))
req, err := http.NewRequest("GET", fmt.Sprintf("/targetcharge/%s/%s", tc.inSoC, tc.inTime), nil)
if err != nil {
t.Fatal(err)
}
vars := map[string]string{
"soc": tc.inSoC,
"time": tc.inTime,
}
req = mux.SetURLVars(req, vars)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if status := rr.Code; status != tc.statusCode {
t.Errorf("handler returned wrong status code: got %v want %v",
status, tc.statusCode)
}
if mockLp.SoC != tc.outSoC {
t.Errorf("wrong target soc: got %v want %v", mockLp.SoC, tc.outSoC)
}
isoFormat := "2006-01-02T15:04:05.999Z07:00"
if !mockLp.TargetTime.Equal(tc.outTime) {
t.Errorf("wrong target time year: got %v want %v", mockLp.TargetTime.UTC().Format(isoFormat), tc.outTime.Format(isoFormat))
}
}
}