Signal vehicle detection and send message on guest vehicle (#4139)

This commit is contained in:
andig 2022-08-19 14:13:36 +02:00 • committed by GitHub
parent 14693d2267
commit 8f665ec4b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 120 additions and 57 deletions

View file

@ -149,9 +149,6 @@ export default {
</script>
<style scoped>
.car-icon {
width: 1.75rem;
}
.details > div {
flex-grow: 1;
flex-basis: 0;

View file

@ -1,33 +1,42 @@
<template>
<div class="d-flex justify-content-between mb-3 align-items-center">
<VehicleOptions
v-if="showOptions"
class="options"
:vehicles="otherVehicles"
:is-unknown="isUnknown"
@change-vehicle="changeVehicle"
@remove-vehicle="removeVehicle"
>
<h4 class="d-flex align-items-center m-0 flex-grow-1 overflow-hidden">
<shopicon-regular-car3
v-if="carIcon"
class="me-2 flex-shrink-0 car-icon"
></shopicon-regular-car3>
<shopicon-regular-cablecharge
v-else
class="me-2 flex-shrink-0 car-icon"
></shopicon-regular-cablecharge>
<h4 class="d-flex align-items-center m-0 flex-grow-1 overflow-hidden">
<shopicon-regular-refresh
v-if="icon === 'refresh'"
ref="refresh"
data-bs-toggle="tooltip"
:title="$t('main.vehicle.detectionActive')"
class="me-2 flex-shrink-0 spin"
></shopicon-regular-refresh>
<shopicon-regular-car3
v-else-if="icon === 'car'"
class="me-2 flex-shrink-0"
></shopicon-regular-car3>
<shopicon-regular-cablecharge
v-else
class="me-2 flex-shrink-0"
></shopicon-regular-cablecharge>
<VehicleOptions
v-if="showOptions"
class="options"
:vehicles="otherVehicles"
:is-unknown="isUnknown"
@change-vehicle="changeVehicle"
@remove-vehicle="removeVehicle"
>
<span class="flex-grow-1 text-truncate vehicle-name">
{{ name }}
</span>
</h4>
</VehicleOptions>
</VehicleOptions>
</h4>
</div>
</template>
<script>
import "@h2d2/shopicons/es/regular/car3";
import "@h2d2/shopicons/es/regular/refresh";
import "@h2d2/shopicons/es/regular/cablecharge";
import { Tooltip } from "bootstrap";
import VehicleOptions from "./VehicleOptions.vue";
@ -37,14 +46,21 @@ export default {
props: {
vehiclePresent: Boolean,
vehicleTitle: String,
vehicleDetectionActive: Boolean,
parked: Boolean,
connected: Boolean,
vehicles: { type: Array, default: () => [] },
},
emits: ["change-vehicle", "remove-vehicle"],
computed: {
carIcon() {
return this.connected || this.parked;
icon() {
if (this.vehicleDetectionActive) {
return "refresh";
}
if (this.connected || this.parked) {
return "car";
}
return null;
},
name() {
if (this.vehiclePresent || this.parked) {
@ -70,6 +86,14 @@ export default {
return !this.isUnknown || this.vehicles.length;
},
},
watch: {
icon: function () {
this.tooltip();
},
},
mounted: function () {
this.tooltip();
},
methods: {
changeVehicle(index) {
this.$emit("change-vehicle", index);
@ -77,6 +101,13 @@ export default {
removeVehicle() {
this.$emit("remove-vehicle");
},
tooltip() {
this.$nextTick(() => {
if (this.$refs.refresh) {
new Tooltip(this.$refs.refresh);
}
});
},
},
};
</script>
@ -89,4 +120,19 @@ export default {
text-decoration: underline;
text-decoration-color: var(--evcc-gray);
}
.spin {
animation: rotation 1s infinite cubic-bezier(0.37, 0, 0.63, 1);
}
.spin >>> svg {
/* workaround to fix the not perfectly centered shopicon. Remove once its fixed in @h2d2/shopicons */
transform: translateY(-0.7px);
}
@keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>

View file

@ -120,6 +120,7 @@ export default {
none: "Kein Fahrzeug",
unknown: "Gastfahrzeug",
changeVehicle: "Fahrzeug ändern",
detectionActive: "Fahrzeugerkennung läuft ...",
},
vehicleSoC: {
disconnected: "getrennt",

View file

@ -119,6 +119,7 @@ export default {
none: "No vehicle",
unknown: "Guest vehicle",
changeVehicle: "Change Vehicle",
detectionActive: "Detecting vehicle ...",
},
vehicleSoC: {
disconnected: "disconnected",

View file

@ -4,4 +4,6 @@ const (
phasesConfigured = "phasesConfigured" // configured phases (1/3, 0 for 1p3p chargers)
phasesEnabled = "phasesEnabled" // enabled phases (1/3)
phasesActive = "phasesActive" // active phases as used by vehicle (1/2/3)
vehicleDetectionActive = "vehicleDetectionActive" // vehicle detection is active (bool)
)

View file

@ -29,13 +29,14 @@ import (
)
const (
evChargeStart = "start" // update chargeTimer
evChargeStop = "stop" // update chargeTimer
evChargeCurrent = "current" // update fakeChargeMeter
evChargePower = "power" // update chargeRater
evVehicleConnect = "connect" // vehicle connected
evVehicleDisconnect = "disconnect" // vehicle disconnected
evVehicleSoC = "soc" // vehicle soc progress
evChargeStart = "start" // update chargeTimer
evChargeStop = "stop" // update chargeTimer
evChargeCurrent = "current" // update fakeChargeMeter
evChargePower = "power" // update chargeRater
evVehicleConnect = "connect" // vehicle connected
evVehicleDisconnect = "disconnect" // vehicle disconnected
evVehicleSoC = "soc" // vehicle soc progress
evVehicleUnidentified = "guest" // vehicle unidentified
pvTimer = "pv"
pvEnable = "enable"
@ -418,8 +419,9 @@ func (lp *LoadPoint) evVehicleDisconnectHandler() {
lp.pushEvent(evVehicleDisconnect)
// remove charger vehicle id
// remove charger vehicle id and stop potential detection
lp.setVehicleIdentifier("")
lp.stopVehicleDetection()
// remove active vehicle if not default
if lp.vehicle != lp.defaultVehicle {
@ -526,6 +528,7 @@ func (lp *LoadPoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even
lp.Unlock()
// set default or start detection
lp.publish(vehicleDetectionActive, false)
lp.vehicleDefaultOrDetect()
// read initial charger state to prevent immediately disabling charger
@ -738,6 +741,8 @@ func (lp *LoadPoint) identifyVehicle() {
lp.setVehicleIdentifier(id)
if id != "" {
lp.stopVehicleDetection()
lp.log.DEBUG.Println("charger vehicle id:", id)
if vehicle := lp.selectVehicleByID(id); vehicle != nil {
@ -855,11 +860,16 @@ func (lp *LoadPoint) unpublishVehicle() {
// vehicleUnidentified checks if there are associated vehicles and starts discovery period
func (lp *LoadPoint) vehicleUnidentified() bool {
res := len(lp.coordinatedVehicles()) > 0 && lp.vehicle == nil &&
lp.clock.Since(lp.vehicleDetect) < vehicleDetectDuration
res := len(lp.coordinatedVehicles()) > 0 && lp.vehicle == nil
// request vehicle api refresh while waiting to identify
if res {
if lp.clock.Since(lp.vehicleDetect) > vehicleDetectDuration {
lp.stopVehicleDetection()
lp.pushEvent(evVehicleUnidentified)
return false
}
select {
case <-lp.vehicleDetectTicker.C:
lp.log.DEBUG.Println("vehicle api refresh")
@ -889,6 +899,7 @@ func (lp *LoadPoint) vehicleDefaultOrDetect() {
// reset connection timer and starts api refresh timer
lp.vehicleDetect = lp.clock.Now()
lp.vehicleDetectTicker = lp.clock.Ticker(vehicleDetectInterval)
lp.publish(vehicleDetectionActive, true)
}
}
@ -898,6 +909,7 @@ func (lp *LoadPoint) stopVehicleDetection() {
if lp.vehicleDetectTicker != nil {
lp.vehicleDetectTicker.Stop()
}
lp.publish(vehicleDetectionActive, false)
}
// identifyVehicleByStatus validates if the active vehicle is still connected to the loadpoint
@ -909,6 +921,7 @@ func (lp *LoadPoint) identifyVehicleByStatus() {
_, ok := lp.charger.(api.Identifier)
if vehicle := lp.coordinator.IdentifyVehicleByStatus(!ok); vehicle != nil {
lp.stopVehicleDetection()
lp.setActiveVehicle(vehicle)
return
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View file

@ -20,8 +20,8 @@
<meta name="theme-color" content="#020318" />
<title>evcc</title>
<script type="module" crossorigin src="./assets/index.f014e26a.js"></script>
<link rel="stylesheet" href="./assets/index.c0100ffd.css">
<script type="module" crossorigin src="./assets/index.9738d453.js"></script>
<link rel="stylesheet" href="./assets/index.fb2bc24b.css">
</head>
<body>
<script>

View file

@ -177,6 +177,9 @@ messaging:
soc: # vehicle soc update event
title: SoC updated
msg: Battery charged to ${vehicleSoC:%.0f}%
guest: # vehicle could not be identified
title: Unknown vehicle
msg: Unknown vehicle, guest connected?
services:
# - type: pushover
# app: # app id