Loadpoint: get soc or temp limit from integrated device (#19397)
This commit is contained in:
parent
86c7364c7d
commit
1e7ca8f16d
7 changed files with 4881 additions and 210 deletions
17
assets/js/components/MaterialIcon/TempLimit.vue
Normal file
17
assets/js/components/MaterialIcon/TempLimit.vue
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<svg :style="svgStyle" viewBox="0 0 32 32">
|
||||
<path
|
||||
d="M16,28c-1.844,0 -3.416,-0.65 -4.716,-1.951c-1.3,-1.3 -1.95,-2.872 -1.951,-4.716c0,-1.066 0.234,-2.061 0.7,-2.984c0.467,-0.922 1.123,-1.705 1.967,-2.349l0,-8c0,-1.111 0.389,-2.056 1.167,-2.833c0.777,-0.778 1.722,-1.167 2.833,-1.167c1.111,0 2.056,0.389 2.833,1.167c0.778,0.777 1.167,1.722 1.167,2.833l0,8c0.844,0.644 1.5,1.428 1.967,2.351c0.466,0.922 0.7,1.917 0.7,2.982c-0,1.845 -0.651,3.417 -1.951,4.718c-1.3,1.3 -2.872,1.95 -4.716,1.949m-1.333,-18l2.666,0l0,-2c0,-0.378 -0.128,-0.694 -0.384,-0.949c-0.256,-0.255 -0.572,-0.383 -0.949,-0.384c-0.377,-0.001 -0.693,0.127 -0.949,0.384c-0.256,0.257 -0.384,0.573 -0.384,0.949l-0,2Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import icon from "../../mixins/icon";
|
||||
|
||||
export default {
|
||||
name: "TempLimit",
|
||||
mixins: [icon],
|
||||
};
|
||||
</script>
|
||||
|
|
@ -33,68 +33,82 @@
|
|||
<div class="tabular">{{ fmtDuration(phaseRemainingInterpolated) }}</div>
|
||||
</div>
|
||||
|
||||
<!-- vehicle -->
|
||||
<button
|
||||
v-if="minSocVisible"
|
||||
ref="minSoc"
|
||||
type="button"
|
||||
class="entry text-danger text-decoration-underline"
|
||||
data-testid="vehicle-status-minsoc"
|
||||
data-bs-toggle="tooltip"
|
||||
@click="openMinSocSettings"
|
||||
>
|
||||
<VehicleMinSocIcon />
|
||||
{{ fmtPercentage(minSoc) }}
|
||||
</button>
|
||||
<div
|
||||
v-else-if="vehicleLimitVisible"
|
||||
ref="vehicleLimit"
|
||||
class="entry"
|
||||
:class="vehicleLimitClass"
|
||||
data-bs-toggle="tooltip"
|
||||
data-testid="vehicle-status-limit"
|
||||
:role="vehicleLimitWarning ? 'button' : null"
|
||||
@click="vehicleLimitClicked"
|
||||
>
|
||||
<component :is="vehicleLimitIconComponent" />
|
||||
{{ fmtPercentage(vehicleLimitSoc) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="vehicleClimaterActive"
|
||||
ref="vehicleClimater"
|
||||
data-bs-toggle="tooltip"
|
||||
class="entry"
|
||||
data-testid="vehicle-status-climater"
|
||||
>
|
||||
<ClimaterIcon />
|
||||
</div>
|
||||
<div
|
||||
v-if="vehicleWelcomeActive"
|
||||
ref="vehicleWelcome"
|
||||
data-bs-toggle="tooltip"
|
||||
class="entry"
|
||||
data-testid="vehicle-status-welcome"
|
||||
>
|
||||
<WelcomeIcon />
|
||||
</div>
|
||||
<div
|
||||
v-if="awaitingAuthorizationVisible"
|
||||
ref="awaitingAuthorization"
|
||||
data-bs-toggle="tooltip"
|
||||
class="entry"
|
||||
data-testid="vehicle-status-awaiting-authorization"
|
||||
>
|
||||
<RfidWaitIcon />
|
||||
</div>
|
||||
<div
|
||||
v-if="disconnectRequiredVisible"
|
||||
ref="disconnectRequired"
|
||||
class="entry text-warning"
|
||||
data-bs-toggle="tooltip"
|
||||
data-testid="vehicle-status-disconnect-required"
|
||||
>
|
||||
<ReconnectIcon />
|
||||
</div>
|
||||
<template v-if="heating">
|
||||
<div
|
||||
v-if="tempLimitVisible"
|
||||
ref="tempLimit"
|
||||
class="entry"
|
||||
data-bs-toggle="tooltip"
|
||||
data-testid="vehicle-status-limit"
|
||||
>
|
||||
<TempLimitIcon />
|
||||
{{ fmtTemperature(vehicleLimitSoc) }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<!-- vehicle -->
|
||||
<button
|
||||
v-if="minSocVisible"
|
||||
ref="minSoc"
|
||||
type="button"
|
||||
class="entry text-danger text-decoration-underline"
|
||||
data-testid="vehicle-status-minsoc"
|
||||
data-bs-toggle="tooltip"
|
||||
@click="openMinSocSettings"
|
||||
>
|
||||
<VehicleMinSocIcon />
|
||||
{{ fmtPercentage(minSoc) }}
|
||||
</button>
|
||||
<div
|
||||
v-else-if="vehicleLimitVisible"
|
||||
ref="vehicleLimit"
|
||||
class="entry"
|
||||
:class="vehicleLimitClass"
|
||||
data-bs-toggle="tooltip"
|
||||
data-testid="vehicle-status-limit"
|
||||
:role="vehicleLimitWarning ? 'button' : null"
|
||||
@click="vehicleLimitClicked"
|
||||
>
|
||||
<component :is="vehicleLimitIconComponent" />
|
||||
{{ fmtPercentage(vehicleLimitSoc) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="vehicleClimaterActive"
|
||||
ref="vehicleClimater"
|
||||
data-bs-toggle="tooltip"
|
||||
class="entry"
|
||||
data-testid="vehicle-status-climater"
|
||||
>
|
||||
<ClimaterIcon />
|
||||
</div>
|
||||
<div
|
||||
v-if="vehicleWelcomeActive"
|
||||
ref="vehicleWelcome"
|
||||
data-bs-toggle="tooltip"
|
||||
class="entry"
|
||||
data-testid="vehicle-status-welcome"
|
||||
>
|
||||
<WelcomeIcon />
|
||||
</div>
|
||||
<div
|
||||
v-if="awaitingAuthorizationVisible"
|
||||
ref="awaitingAuthorization"
|
||||
data-bs-toggle="tooltip"
|
||||
class="entry"
|
||||
data-testid="vehicle-status-awaiting-authorization"
|
||||
>
|
||||
<RfidWaitIcon />
|
||||
</div>
|
||||
<div
|
||||
v-if="disconnectRequiredVisible"
|
||||
ref="disconnectRequired"
|
||||
class="entry text-warning"
|
||||
data-bs-toggle="tooltip"
|
||||
data-testid="vehicle-status-disconnect-required"
|
||||
>
|
||||
<ReconnectIcon />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- smart cost -->
|
||||
<button
|
||||
|
|
@ -179,6 +193,7 @@ import ReconnectIcon from "./MaterialIcon/Reconnect.vue";
|
|||
import RfidWaitIcon from "./MaterialIcon/RfidWait.vue";
|
||||
import SunDownIcon from "./MaterialIcon/SunDown.vue";
|
||||
import SunUpIcon from "./MaterialIcon/SunUp.vue";
|
||||
import TempLimitIcon from "./MaterialIcon/TempLimit.vue";
|
||||
import Tooltip from "bootstrap/js/dist/tooltip";
|
||||
import VehicleLimitIcon from "./MaterialIcon/VehicleLimit.vue";
|
||||
import VehicleLimitReachedIcon from "./MaterialIcon/VehicleLimitReached.vue";
|
||||
|
|
@ -203,6 +218,7 @@ export default {
|
|||
VehicleLimitIcon,
|
||||
VehicleMinSocIcon,
|
||||
WelcomeIcon,
|
||||
TempLimitIcon,
|
||||
BatteryBoostIcon,
|
||||
},
|
||||
mixins: [formatter],
|
||||
|
|
@ -252,6 +268,7 @@ export default {
|
|||
vehicleWelcomeTooltip: null,
|
||||
smartCostTooltip: null,
|
||||
vehicleLimitTooltip: null,
|
||||
tempLimitTooltip: null,
|
||||
awaitingAuthorizationTooltip: null,
|
||||
disconnectRequiredTooltip: null,
|
||||
batteryBoostTooltip: null,
|
||||
|
|
@ -329,6 +346,12 @@ export default {
|
|||
}
|
||||
return this.$t("main.vehicleStatus.vehicleLimit");
|
||||
},
|
||||
tempLimitTooltipContent() {
|
||||
if (!this.tempLimitVisible) {
|
||||
return "";
|
||||
}
|
||||
return this.$t("main.heatingStatus.vehicleLimit");
|
||||
},
|
||||
minSocVisible() {
|
||||
return this.connected && this.minSoc > 0 && this.vehicleSoc < this.minSoc;
|
||||
},
|
||||
|
|
@ -357,6 +380,9 @@ export default {
|
|||
}
|
||||
return "";
|
||||
},
|
||||
tempLimitVisible() {
|
||||
return this.heating && this.vehicleLimitSoc > 0;
|
||||
},
|
||||
vehicleLimitIconComponent() {
|
||||
if (this.vehicleLimitReached) {
|
||||
return VehicleLimitReachedIcon;
|
||||
|
|
@ -523,6 +549,9 @@ export default {
|
|||
vehicleLimitTooltipContent() {
|
||||
this.$nextTick(this.updateVehicleLimitTooltip);
|
||||
},
|
||||
tempLimitTooltipContent() {
|
||||
this.$nextTick(this.updateTempLimitTooltip);
|
||||
},
|
||||
awaitingAuthorizationTooltipContent() {
|
||||
this.$nextTick(this.updateAwaitingAuthorizationTooltip);
|
||||
},
|
||||
|
|
@ -552,6 +581,7 @@ export default {
|
|||
this.updateVehicleWelcomeTooltip();
|
||||
this.updateSmartCostTooltip();
|
||||
this.updateVehicleLimitTooltip();
|
||||
this.updateTempLimitTooltip();
|
||||
this.updateAwaitingAuthorizationTooltip();
|
||||
this.updateDisconnectRequiredTooltip();
|
||||
this.updateDurations();
|
||||
|
|
@ -684,6 +714,13 @@ export default {
|
|||
true
|
||||
);
|
||||
},
|
||||
updateTempLimitTooltip() {
|
||||
this.tempLimitTooltip = this.updateTooltip(
|
||||
this.tempLimitTooltip,
|
||||
this.tempLimitTooltipContent,
|
||||
this.$refs.tempLimit
|
||||
);
|
||||
},
|
||||
updateAwaitingAuthorizationTooltip() {
|
||||
this.awaitingAuthorizationTooltip = this.updateTooltip(
|
||||
this.awaitingAuthorizationTooltip,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ func init() {
|
|||
registry.AddCtx(api.Custom, NewConfigurableFromConfig)
|
||||
}
|
||||
|
||||
//go:generate go tool decorate -f decorateCustom -b *Charger -r api.Charger -t "api.ChargerEx,MaxCurrentMillis,func(float64) error" -t "api.Identifier,Identify,func() (string, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error" -t "api.Resurrector,WakeUp,func() error" -t "api.Battery,Soc,func() (float64, error)" -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseCurrents,Currents,func() (float64, float64, float64, error)" -t "api.PhaseVoltages,Voltages,func() (float64, float64, float64, error)"
|
||||
//go:generate go tool decorate -f decorateCustom -b *Charger -r api.Charger -t "api.ChargerEx,MaxCurrentMillis,func(float64) error" -t "api.Identifier,Identify,func() (string, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error" -t "api.Resurrector,WakeUp,func() error" -t "api.Battery,Soc,func() (float64, error)" -t "api.SocLimiter,GetLimitSoc,func() (int64, error)" -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseCurrents,Currents,func() (float64, float64, float64, error)" -t "api.PhaseVoltages,Voltages,func() (float64, float64, float64, error)"
|
||||
|
||||
// NewConfigurableFromConfig creates a new configurable charger
|
||||
func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}) (api.Charger, error) {
|
||||
|
|
@ -36,6 +36,7 @@ func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}
|
|||
Identify, Phases1p3p *plugin.Config
|
||||
Wakeup *plugin.Config
|
||||
Soc *plugin.Config
|
||||
LimitSoc *plugin.Config
|
||||
Tos bool
|
||||
measurement.Energy `mapstructure:",squash"` // optional
|
||||
meter.Phases `mapstructure:",squash"` // optional
|
||||
|
|
@ -119,6 +120,12 @@ func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}
|
|||
return nil, fmt.Errorf("soc: %w", err)
|
||||
}
|
||||
|
||||
// decorate limitsoc
|
||||
limitsoc, err := cc.LimitSoc.IntGetter(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("limitsoc: %w", err)
|
||||
}
|
||||
|
||||
// decorate measurements
|
||||
powerG, energyG, err := cc.Energy.Configure(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -130,7 +137,7 @@ func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return decorateCustom(c, maxcurrentmillis, identify, phases1p3p, wakeup, soc, powerG, energyG, currentsG, voltagesG), nil
|
||||
return decorateCustom(c, maxcurrentmillis, identify, phases1p3p, wakeup, soc, limitsoc, powerG, energyG, currentsG, voltagesG), nil
|
||||
}
|
||||
|
||||
// NewConfigurable creates a new charger
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1635,7 +1635,14 @@ func (lp *Loadpoint) publishSocAndRange() {
|
|||
// vehicle target soc
|
||||
// TODO take vehicle api limits into account
|
||||
apiLimitSoc := 100
|
||||
if vs, ok := lp.GetVehicle().(api.SocLimiter); ok {
|
||||
|
||||
// integrated device with charger limit
|
||||
vs, ok := lp.charger.(api.SocLimiter)
|
||||
if !ok {
|
||||
// vehicle limit
|
||||
vs, ok = lp.GetVehicle().(api.SocLimiter)
|
||||
}
|
||||
if ok {
|
||||
if limit, err := vs.GetLimitSoc(); err == nil {
|
||||
apiLimitSoc = int(limit)
|
||||
lp.log.DEBUG.Printf("vehicle soc limit: %d%%", limit)
|
||||
|
|
|
|||
|
|
@ -560,6 +560,7 @@ selfConsumption = "Eigenverbrauch"
|
|||
|
||||
[main.heatingStatus]
|
||||
charging = "Heize …"
|
||||
vehicleLimit = "Heizungslimit"
|
||||
waitForVehicle = "Bereit. Warte auf Heizung …"
|
||||
|
||||
[main.loadpoint]
|
||||
|
|
@ -711,6 +712,7 @@ scale3p = "Erhöhe gleich auf dreiphasiges Laden."
|
|||
targetChargeActive = "Ladeplan aktiv. Geplantes Ende in {duration}."
|
||||
targetChargePlanned = "Ladeplan startet in {duration}."
|
||||
targetChargeWaitForVehicle = "Ladeplan bereit. Warte auf Fahrzeug …"
|
||||
tempLimit = "Heizungslimit."
|
||||
unknown = ""
|
||||
vehicleLimit = "Fahrzeuglimit."
|
||||
vehicleLimitReached = "Fahrzeuglimit erreicht."
|
||||
|
|
|
|||
|
|
@ -559,6 +559,7 @@ selfConsumption = "Self-consumption"
|
|||
|
||||
[main.heatingStatus]
|
||||
charging = "Heating…"
|
||||
vehicleLimit = "Heater limit"
|
||||
waitForVehicle = "Ready. Waiting for heater…"
|
||||
|
||||
[main.loadpoint]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue