Repository: evcc-io/evcc
Pull request #2743 (2022-03-01 07:45:58)

Add vehicle api
Add experimental vehicle api. This is required in preparation of the the "Parkplatz" feature.


Patch:
diff --git a/core/loadpoint.go b/core/loadpoint.go
index 219db3cf..ac91119e 100644
--- a/core/loadpoint.go
+++ b/core/loadpoint.go
@@ -1079,7 +1079,7 @@ func (lp *LoadPoint) pvScalePhases(availablePower, minCurrent, maxCurrent float6
 	scalable := maxPhases > 1 && phases < maxPhases
 
 	// scale up phases
-	if min3pCurrent := powerToCurrent(availablePower, 3); min3pCurrent >= minCurrent && scalable {
+	if min3pCurrent := powerToCurrent(availablePower, maxPhases); min3pCurrent >= minCurrent && scalable {
 		lp.log.DEBUG.Printf("available power %.0fW > %.0fW min %dp threshold", availablePower, 3*Voltage*minCurrent, maxPhases)
 
 		if lp.phaseTimer.IsZero() {
diff --git a/core/loadpoint/api.go b/core/loadpoint/api.go
index 6a9dcefc..1ab4271a 100644
--- a/core/loadpoint/api.go
+++ b/core/loadpoint/api.go
@@ -48,6 +48,8 @@ type API interface {
 
 	// SetTargetCharge sets the charge targetSoC
 	SetTargetCharge(time.Time, int)
+	// SetVehicle sets the active vehicle
+	SetVehicle(vehicle api.Vehicle)
 	// RemoteControl sets remote status demand
 	RemoteControl(string, RemoteDemand)
 
diff --git a/core/loadpoint_api.go b/core/loadpoint_api.go
index dc6cb1bc..76d11395 100644
--- a/core/loadpoint_api.go
+++ b/core/loadpoint_api.go
@@ -139,6 +139,14 @@ func (lp *LoadPoint) SetTargetCharge(finishAt time.Time, soc int) {
 	}
 }
 
+// SetVehicle sets the active vehicle
+func (lp *LoadPoint) SetVehicle(vehicle api.Vehicle) {
+	lp.Lock()
+	defer lp.Unlock()
+
+	lp.setActiveVehicle(vehicle)
+}
+
 // RemoteControl sets remote status demand
 func (lp *LoadPoint) RemoteControl(source string, demand loadpoint.RemoteDemand) {
 	lp.Lock()
diff --git a/server/http.go b/server/http.go
index 9cbb2dcf..85e34bba 100644
--- a/server/http.go
+++ b/server/http.go
@@ -87,6 +87,7 @@ func NewHTTPd(url string, site site.API, hub *SocketHub, cache *util.Cache) *HTT
 			"phases":        {[]string{"POST", "OPTIONS"}, "/phases/{value:[0-9]+}", phasesHandler(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)},
 		}
 
diff --git a/server/http_handler.go b/server/http_handler.go
index 80c00acb..46796b1c 100644
--- a/server/http_handler.go
+++ b/server/http_handler.go
@@ -274,6 +274,15 @@ func targetChargeRemoveHandler(loadpoint loadpoint.API) http.HandlerFunc {
 	}
 }
 
+// vehicleRemoveHandler removes vehicle
+func vehicleRemoveHandler(loadpoint loadpoint.API) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		loadpoint.SetVehicle(nil)
+		res := struct{}{}
+		jsonResult(w, res)
+	}
+}
+
 // socketHandler attaches websocket handler to uri
 func socketHandler(hub *SocketHub) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {


Test patch:
diff --git a/core/loadpoint_phases_test.go b/core/loadpoint_phases_test.go
index d98eb1ee..ac764126 100644
--- a/core/loadpoint_phases_test.go
+++ b/core/loadpoint_phases_test.go
@@ -162,9 +162,12 @@ func TestPvScalePhases(t *testing.T) {
 			ctrl.Finish()
 
 			// scale up
-			min3p := 3 * minA * Voltage
+			min3p := float64(tc.maxExpected) * minA * Voltage
 			lp.phaseTimer = time.Time{}
-			lp.Phases = tc.physical // reset to initial state
+
+			// reset to initial state
+			lp.Phases = tc.physical
+			lp.measuredPhases = tc.measuredPhases
 
 			plainCharger.EXPECT().Enable(false).Return(nil).MaxTimes(1)
 			phaseCharger.EXPECT().Phases1p3p(3).Return(nil).MaxTimes(1)