Fix removing target charge time (#2066)

This commit is contained in:
andig 2021-12-18 17:15:55 +01:00 • committed by GitHub
parent 5ca18306c4
commit 57f5a72055
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 69 additions and 43 deletions

View file

@ -17,6 +17,7 @@
v-bind="vehicle"
@target-soc-updated="setTargetSoC"
@target-time-updated="setTargetTime"
@target-time-removed="removeTargetTime"
/>
</div>
<LoadpointDetails v-bind="details" />
@ -57,8 +58,7 @@ export default {
vehiclePresent: Boolean,
vehicleRange: Number,
minSoC: Number,
timerSet: Boolean,
timerActive: Boolean,
targetTimeActive: Boolean,
targetTime: String,
// details
@ -124,6 +124,9 @@ export default {
.post(this.api("targetcharge") + "/" + this.targetSoC + "/" + formattedDate)
.catch(window.app.error);
},
removeTargetTime: function () {
axios.delete(this.api("targetcharge")).catch(window.app.error);
},
},
};
</script>

View file

@ -4,8 +4,8 @@
class="target-time-button btn btn-link btn-sm pe-0"
:class="{
invisible: !targetSoC,
'text-dark': timerActive,
'text-secondary': !timerActive,
'text-dark': targetTimeActive,
'text-secondary': !targetTimeActive,
}"
data-bs-toggle="modal"
:data-bs-target="`#${modalId}`"
@ -26,7 +26,7 @@
aria-label="Close"
></button>
</div>
<form @submit.prevent="saveTargetTime">
<form @submit.prevent="setTargetTime">
<div class="modal-body">
<div class="form-group">
<!-- eslint-disable vue/no-v-html -->
@ -113,8 +113,7 @@ export default {
mixins: [formatter],
props: {
id: Number,
timerActive: Boolean,
timerSet: Boolean,
targetTimeActive: Boolean,
targetTime: String,
targetSoC: Number,
},
@ -123,7 +122,7 @@ export default {
},
computed: {
targetChargeEnabled: function () {
return this.targetTime && this.timerSet;
return this.targetTime;
},
selectedTargetTimeValid: function () {
const now = new Date();
@ -197,12 +196,12 @@ export default {
minTime: function () {
return new Date().toISOString().split("T")[1].slice(0, -8);
},
removeTargetTime: function () {
this.$emit("target-time-updated", new Date(null));
},
saveTargetTime: function () {
setTargetTime: function () {
this.$emit("target-time-updated", this.selectedTargetTime);
},
removeTargetTime: function () {
this.$emit("target-time-removed");
},
},
};
</script>

View file

@ -76,8 +76,7 @@ TargetChargePlanned.args = {
vehicleSoC: 31,
minSoC: 20,
charging: false,
timerSet: true,
timerActive: false,
targetTimeActive: false,
targetSoC: 45,
targetTime: hoursFromNow(14),
id: 0,
@ -92,8 +91,7 @@ TargetChargeActive.args = {
vehicleSoC: 66,
minSoC: 30,
charging: true,
timerSet: true,
timerActive: true,
targetTimeActive: true,
targetSoC: 80,
targetTime: hoursFromNow(2),
id: 0,

View file

@ -7,7 +7,8 @@
<VehicleSubline
v-bind="vehicleSubline"
class="my-1"
@target-time-updated="targetTimeUpdated"
@target-time-updated="setTargetTime"
@target-time-removed="removeTargetTime"
/>
</div>
</template>
@ -31,8 +32,7 @@ export default {
charging: Boolean,
minSoC: Number,
vehicleTitle: String,
timerActive: Boolean,
timerSet: Boolean,
targetTimeActive: Boolean,
targetTime: String,
targetSoC: Number,
},
@ -48,9 +48,12 @@ export default {
targetSocUpdated: function (targetSoC) {
this.$emit("target-soc-updated", targetSoC);
},
targetTimeUpdated: function (targetTime) {
setTargetTime: function (targetTime) {
this.$emit("target-time-updated", targetTime);
},
removeTargetTime: function () {
this.$emit("target-time-removed");
},
},
};
</script>

View file

@ -6,7 +6,11 @@
{{ $t("main.vehicleSubline.mincharge", { soc: minSoC }) }}
</span>
</small>
<TargetCharge v-bind="targetCharge" @target-time-updated="targetTimeUpdated" />
<TargetCharge
v-bind="targetCharge"
@target-time-updated="setTargetTime"
@target-time-removed="removeTargetTime"
/>
</div>
</template>
@ -22,8 +26,7 @@ export default {
id: Number,
vehicleSoC: Number,
minSoC: Number,
timerActive: Boolean,
timerSet: Boolean,
targetTimeActive: Boolean,
targetTime: String,
targetSoC: Number,
},
@ -36,9 +39,12 @@ export default {
},
},
methods: {
targetTimeUpdated: function (targetTime) {
setTargetTime: function (targetTime) {
this.$emit("target-time-updated", targetTime);
},
removeTargetTime: function () {
this.$emit("target-time-removed");
},
},
};
</script>

View file

@ -118,11 +118,14 @@ func (lp *LoadPoint) SetTargetCharge(finishAt time.Time, soc int) {
// apply immediately
if lp.socTimer.Time != finishAt || lp.SoC.Target != soc {
lp.publish("targetTime", finishAt)
lp.socTimer.Time = finishAt
lp.publish("targetTime", finishAt)
lp.setTargetSoC(soc)
lp.requestUpdate()
// don't remove soc
if !finishAt.IsZero() {
lp.setTargetSoC(soc)
lp.requestUpdate()
}
}
}

View file

@ -55,9 +55,7 @@ func (lp *Timer) DemandActive() bool {
}
defer func() {
lp.Publish("timerSet", lp.Time.After(time.Now()))
lp.Publish("timerActive", lp.active)
lp.Publish("timerProjectedEnd", lp.finishAt)
lp.Publish("targetTimeActive", lp.active)
}()
// power

4
dist/index.html vendored
View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png?[[.Version]]"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png?[[.Version]]"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png?[[.Version]]"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg?[[.Version]]" color="#18191a"><link rel="shortcut icon" href="ico/favicon.ico?[[.Version]]"><meta name="apple-mobile-web-app-title" content="evcc"><meta name="application-name" content="evcc"><meta name="msapplication-TileColor" content="#18191a"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#18191a"><title>evcc</title><link href="css/chunk-vendors.a7b690cd.css" rel="preload" as="style"><link href="css/index.801eac99.css" rel="preload" as="style"><link href="js/chunk-vendors.e8d8381a.js" rel="preload" as="script"><link href="js/index.089c55bd.js" rel="preload" as="script"><link href="css/chunk-vendors.a7b690cd.css" rel="stylesheet"><link href="css/index.801eac99.css" rel="stylesheet"></head><body><script>window.evcc = {
<!DOCTYPE html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png?[[.Version]]"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png?[[.Version]]"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png?[[.Version]]"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg?[[.Version]]" color="#18191a"><link rel="shortcut icon" href="ico/favicon.ico?[[.Version]]"><meta name="apple-mobile-web-app-title" content="evcc"><meta name="application-name" content="evcc"><meta name="msapplication-TileColor" content="#18191a"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#18191a"><title>evcc</title><link href="css/chunk-vendors.a7b690cd.css" rel="preload" as="style"><link href="css/index.801eac99.css" rel="preload" as="style"><link href="js/chunk-vendors.e8d8381a.js" rel="preload" as="script"><link href="js/index.b8b64f9b.js" rel="preload" as="script"><link href="css/chunk-vendors.a7b690cd.css" rel="stylesheet"><link href="css/index.801eac99.css" rel="stylesheet"></head><body><script>window.evcc = {
version: "[[.Version]]",
configured: "[[.Configured]]",
};</script><div id="app"></div><script src="js/chunk-vendors.e8d8381a.js"></script><script src="js/index.089c55bd.js"></script></body></html>
};</script><div id="app"></div><script src="js/chunk-vendors.e8d8381a.js"></script><script src="js/index.b8b64f9b.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/js/index.b8b64f9b.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -81,14 +81,15 @@ func NewHTTPd(url string, site site.API, hub *SocketHub, cache *util.Cache) *HTT
lpAPI := api.PathPrefix(fmt.Sprintf("/loadpoints/%d", id)).Subrouter()
routes := map[string]route{
"mode": {[]string{"POST", "OPTIONS"}, "/mode/{value:[a-z]+}", chargeModeHandler(lp)},
"targetsoc": {[]string{"POST", "OPTIONS"}, "/targetsoc/{value:[0-9]+}", targetSoCHandler(lp)},
"minsoc": {[]string{"POST", "OPTIONS"}, "/minsoc/{value:[0-9]+}", minSoCHandler(lp)},
"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)},
"remotedemand": {[]string{"POST", "OPTIONS"}, "/remotedemand/{demand:[a-z]+}/{source::[0-9a-zA-Z_-]+}", remoteDemandHandler(lp)},
"mode": {[]string{"POST", "OPTIONS"}, "/mode/{value:[a-z]+}", chargeModeHandler(lp)},
"targetsoc": {[]string{"POST", "OPTIONS"}, "/targetsoc/{value:[0-9]+}", targetSoCHandler(lp)},
"minsoc": {[]string{"POST", "OPTIONS"}, "/minsoc/{value:[0-9]+}", minSoCHandler(lp)},
"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)},
"targetcharge2": {[]string{"DELETE", "OPTIONS"}, "/targetcharge", targetChargeRemoveHandler(lp)},
"remotedemand": {[]string{"POST", "OPTIONS"}, "/remotedemand/{demand:[a-z]+}/{source::[0-9a-zA-Z_-]+}", remoteDemandHandler(lp)},
}
for _, r := range routes {

View file

@ -265,6 +265,15 @@ func targetChargeHandler(loadpoint loadpoint.API) http.HandlerFunc {
}
}
// targetChargeRemoveHandler removes target soc
func targetChargeRemoveHandler(loadpoint loadpoint.API) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
loadpoint.SetTargetCharge(time.Time{}, 0)
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) {

View file

@ -90,6 +90,12 @@ func NewSocketHub() *SocketHub {
func encode(v interface{}) (string, error) {
var s string
switch val := v.(type) {
case time.Time:
var b []byte
if !val.IsZero() {
b, _ = val.MarshalText()
}
s = fmt.Sprintf(`"%s"`, string(b))
case time.Duration:
// must be before stringer to convert to seconds instead of string
s = fmt.Sprintf("%d", int64(val.Seconds()))