Loadpoint: rename chargeCurrent to offeredCurrent (BC) (#20457)
Co-authored-by: Michael Geers <michael@geers.tv>
This commit is contained in:
parent
2cabe49239
commit
598cccaff1
10 changed files with 66 additions and 64 deletions
|
|
@ -22,7 +22,7 @@ const baseState = {
|
|||
charging: true,
|
||||
vehicleSoc: 66,
|
||||
limitSoc: 90,
|
||||
chargeCurrent: 7,
|
||||
offeredCurrent: 7,
|
||||
minCurrent: 6,
|
||||
maxCurrent: 16,
|
||||
activePhases: 2,
|
||||
|
|
@ -53,7 +53,7 @@ export const Idle = createStory({
|
|||
vehicleName: "",
|
||||
mode: "off",
|
||||
charging: false,
|
||||
chargeCurrent: 0,
|
||||
offeredCurrent: 0,
|
||||
});
|
||||
|
||||
export const DisabledLongTitle = createStory({
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ export default {
|
|||
chargerSinglePhase: Boolean,
|
||||
minCurrent: Number,
|
||||
maxCurrent: Number,
|
||||
chargeCurrent: Number,
|
||||
offeredCurrent: Number,
|
||||
connectedDuration: Number,
|
||||
chargeCurrents: Array,
|
||||
chargeRemainingEnergy: Number,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ function loadpoint(opts = {}) {
|
|||
charging: true,
|
||||
vehicleSoc: 66,
|
||||
limitSoc: 90,
|
||||
chargeCurrent: 7,
|
||||
offeredCurrent: 7,
|
||||
minCurrent: 6,
|
||||
maxCurrent: 16,
|
||||
activePhases: 2,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default {
|
|||
phasesActive: { control: { type: "number" } },
|
||||
minCurrent: { control: { type: "number" } },
|
||||
maxCurrent: { control: { type: "number" } },
|
||||
chargeCurrent: { control: { type: "number" } },
|
||||
offeredCurrent: { control: { type: "number" } },
|
||||
chargeCurrents: { control: { type: "object" } },
|
||||
},
|
||||
};
|
||||
|
|
@ -28,7 +28,7 @@ OnePhase.args = {
|
|||
phasesActive: 1,
|
||||
minCurrent: 6,
|
||||
maxCurrent: 16,
|
||||
chargeCurrent: 8,
|
||||
offeredCurrent: 8,
|
||||
chargeCurrents: null,
|
||||
};
|
||||
|
||||
|
|
@ -48,14 +48,14 @@ export const RealCurrents = Template.bind({});
|
|||
RealCurrents.args = {
|
||||
...OnePhase.args,
|
||||
phasesActive: 3,
|
||||
chargeCurrent: 13,
|
||||
offeredCurrent: 13,
|
||||
chargeCurrents: [11, 9, 12],
|
||||
};
|
||||
|
||||
export const OnePhaseMoreAvailable = Template.bind({});
|
||||
OnePhaseMoreAvailable.args = {
|
||||
...OnePhase.args,
|
||||
chargeCurrent: 12,
|
||||
offeredCurrent: 12,
|
||||
chargeCurrents: [6, 0.2, 0],
|
||||
};
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ export const TwoPhasesActive = Template.bind({});
|
|||
TwoPhasesActive.args = {
|
||||
...OnePhase.args,
|
||||
phasesActive: 2,
|
||||
chargeCurrent: 16,
|
||||
offeredCurrent: 16,
|
||||
chargeCurrents: [16, 16, 0.3],
|
||||
};
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ export const AsymetricPhases = Template.bind({});
|
|||
AsymetricPhases.args = {
|
||||
...OnePhase.args,
|
||||
phasesActive: 2,
|
||||
chargeCurrent: 16,
|
||||
offeredCurrent: 16,
|
||||
chargeCurrents: [8, 0.9, 14],
|
||||
};
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ export const OnlySecondPhase = Template.bind({});
|
|||
OnlySecondPhase.args = {
|
||||
...OnePhase.args,
|
||||
phasesActive: 1,
|
||||
chargeCurrent: 13,
|
||||
offeredCurrent: 13,
|
||||
chargeCurrents: [0, 13, 0],
|
||||
};
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ export const MainlyThirdPhase = Template.bind({});
|
|||
MainlyThirdPhase.args = {
|
||||
...OnePhase.args,
|
||||
phasesActive: 1,
|
||||
chargeCurrent: 10,
|
||||
offeredCurrent: 10,
|
||||
chargeCurrents: [0.007, 0.009, 5.945],
|
||||
minCurrent: 6,
|
||||
maxCurrent: 20,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const MIN_ACTIVE_CURRENT = 1;
|
|||
export default {
|
||||
name: "Phases",
|
||||
props: {
|
||||
chargeCurrent: { type: Number },
|
||||
offeredCurrent: { type: Number },
|
||||
chargeCurrents: { type: Array },
|
||||
phasesActive: { type: Number },
|
||||
minCurrent: { type: Number },
|
||||
|
|
@ -32,7 +32,7 @@ export default {
|
|||
methods: {
|
||||
targetWidth() {
|
||||
const current = Math.min(
|
||||
Math.max(this.minCurrent, this.chargeCurrent),
|
||||
Math.max(this.minCurrent, this.offeredCurrent),
|
||||
this.maxCurrent
|
||||
);
|
||||
return (100 / this.maxCurrent) * current;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ const (
|
|||
Connected = "connected" // connected
|
||||
Charging = "charging" // charging
|
||||
|
||||
// loadpoint setpoint
|
||||
OfferedCurrent = "offeredCurrent" // offered current
|
||||
|
||||
// smart charging
|
||||
SmartCostActive = "smartCostActive" // smart cost active
|
||||
SmartCostLimit = "smartCostLimit" // smart cost limit
|
||||
|
|
@ -51,7 +54,6 @@ const (
|
|||
EffectiveLimitSoc = "effectiveLimitSoc" // effective limit soc
|
||||
|
||||
// measurements
|
||||
ChargeCurrent = "chargeCurrent" // charge current
|
||||
ChargePower = "chargePower" // charge power
|
||||
ChargeCurrents = "chargeCurrents" // charge currents
|
||||
ChargeVoltages = "chargeVoltages" // charge voltages
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ type Loadpoint struct {
|
|||
enabled bool // Charger enabled state
|
||||
phases int // Charger enabled phases, guarded by mutex
|
||||
measuredPhases int // Charger physically measured phases
|
||||
chargeCurrent float64 // Charger current limit
|
||||
offeredCurrent float64 // Charger current limit
|
||||
socUpdated time.Time // Soc updated timestamp (poll: connected)
|
||||
vehicleDetect time.Time // Vehicle connected timestamp
|
||||
chargerSwitched time.Time // Charger enabled/disabled timestamp
|
||||
|
|
@ -548,12 +548,12 @@ func (lp *Loadpoint) evVehicleSocProgressHandler(soc float64) {
|
|||
}
|
||||
}
|
||||
|
||||
// evChargeCurrentHandler publishes the charge current
|
||||
// evChargeCurrentHandler publishes the offered current
|
||||
func (lp *Loadpoint) evChargeCurrentHandler(current float64) {
|
||||
if !lp.enabled {
|
||||
current = 0
|
||||
}
|
||||
lp.publish(keys.ChargeCurrent, current)
|
||||
lp.publish(keys.OfferedCurrent, current)
|
||||
}
|
||||
|
||||
// evChargeCurrentWrappedMeterHandler updates the dummy charge meter's charge power.
|
||||
|
|
@ -740,12 +740,12 @@ func (lp *Loadpoint) syncCharger() error {
|
|||
if isCg {
|
||||
if current, err = cg.GetMaxCurrent(); err == nil {
|
||||
// smallest adjustment most PWM-Controllers can do is: 100%÷256×0,6A = 0.234A
|
||||
if delta := math.Abs(lp.chargeCurrent - current); delta > 0.23 {
|
||||
if delta := math.Abs(lp.offeredCurrent - current); delta > 0.23 {
|
||||
if shouldBeConsistent && delta >= 1 {
|
||||
lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA, expected %.3gA) - make sure your interval is at least 30s", current, lp.chargeCurrent)
|
||||
lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA, expected %.3gA) - make sure your interval is at least 30s", current, lp.offeredCurrent)
|
||||
}
|
||||
lp.chargeCurrent = current
|
||||
lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
|
||||
lp.offeredCurrent = current
|
||||
lp.bus.Publish(evChargeCurrent, lp.offeredCurrent)
|
||||
}
|
||||
} else if !errors.Is(err, api.ErrNotAvailable) {
|
||||
return fmt.Errorf("charger get max current: %w", err)
|
||||
|
|
@ -755,12 +755,12 @@ func (lp *Loadpoint) syncCharger() error {
|
|||
// use measured phase currents as fallback if charger does not provide max current or does not currently relay from vehicle (TWC3)
|
||||
if !isCg || errors.Is(err, api.ErrNotAvailable) {
|
||||
// validate if current too high by more than 1A (https://github.com/evcc-io/evcc/issues/14731)
|
||||
if current := lp.GetMaxPhaseCurrent(); current > lp.chargeCurrent+1.0 {
|
||||
if current := lp.GetMaxPhaseCurrent(); current > lp.offeredCurrent+1.0 {
|
||||
if shouldBeConsistent {
|
||||
lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA measured, expected %.3gA) - make sure your interval is at least 30s", current, lp.chargeCurrent)
|
||||
lp.log.WARN.Printf("charger logic error: current mismatch (got %.3gA measured, expected %.3gA) - make sure your interval is at least 30s", current, lp.offeredCurrent)
|
||||
}
|
||||
lp.chargeCurrent = current
|
||||
lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
|
||||
lp.offeredCurrent = current
|
||||
lp.bus.Publish(evChargeCurrent, lp.offeredCurrent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -822,27 +822,27 @@ func (lp *Loadpoint) coarseCurrent() bool {
|
|||
}
|
||||
|
||||
// roundedCurrent rounds current down to full amps if charger or vehicle require it
|
||||
func (lp *Loadpoint) roundedCurrent(chargeCurrent float64) float64 {
|
||||
func (lp *Loadpoint) roundedCurrent(current float64) float64 {
|
||||
// full amps only?
|
||||
if lp.coarseCurrent() {
|
||||
chargeCurrent = math.Trunc(chargeCurrent)
|
||||
current = math.Trunc(current)
|
||||
}
|
||||
return chargeCurrent
|
||||
return current
|
||||
}
|
||||
|
||||
// setLimit applies charger current limits and enables/disables accordingly
|
||||
func (lp *Loadpoint) setLimit(chargeCurrent float64) error {
|
||||
chargeCurrent = lp.roundedCurrent(chargeCurrent)
|
||||
func (lp *Loadpoint) setLimit(current float64) error {
|
||||
current = lp.roundedCurrent(current)
|
||||
|
||||
// apply circuit limits
|
||||
if lp.circuit != nil {
|
||||
currentLimit := lp.circuit.ValidateCurrent(lp.chargeCurrent, chargeCurrent, lp.charging())
|
||||
currentLimit := lp.circuit.ValidateCurrent(lp.offeredCurrent, current, lp.charging())
|
||||
|
||||
activePhases := lp.ActivePhases()
|
||||
powerLimit := lp.circuit.ValidatePower(lp.chargePower, currentToPower(chargeCurrent, activePhases), lp.charging())
|
||||
powerLimit := lp.circuit.ValidatePower(lp.chargePower, currentToPower(current, activePhases), lp.charging())
|
||||
currentLimitViaPower := powerToCurrent(powerLimit, activePhases)
|
||||
|
||||
chargeCurrent = lp.roundedCurrent(min(currentLimit, currentLimitViaPower))
|
||||
current = lp.roundedCurrent(min(currentLimit, currentLimitViaPower))
|
||||
}
|
||||
|
||||
// https://github.com/evcc-io/evcc/issues/16309
|
||||
|
|
@ -852,12 +852,12 @@ func (lp *Loadpoint) setLimit(chargeCurrent float64) error {
|
|||
}
|
||||
|
||||
// set current
|
||||
if chargeCurrent != lp.chargeCurrent && chargeCurrent >= effMinCurrent {
|
||||
if current != lp.offeredCurrent && current >= effMinCurrent {
|
||||
var err error
|
||||
if charger, ok := lp.charger.(api.ChargerEx); ok {
|
||||
err = charger.MaxCurrentMillis(chargeCurrent)
|
||||
err = charger.MaxCurrentMillis(current)
|
||||
} else {
|
||||
err = lp.charger.MaxCurrent(int64(chargeCurrent))
|
||||
err = lp.charger.MaxCurrent(int64(current))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -865,22 +865,22 @@ func (lp *Loadpoint) setLimit(chargeCurrent float64) error {
|
|||
if vv, ok := v.(api.Resurrector); ok && errors.Is(err, api.ErrAsleep) {
|
||||
// https://github.com/evcc-io/evcc/issues/8254
|
||||
// wakeup vehicle
|
||||
lp.log.DEBUG.Printf("max charge current: waking up vehicle")
|
||||
lp.log.DEBUG.Printf("set charge current limit: waking up vehicle")
|
||||
if err := vv.WakeUp(); err != nil {
|
||||
return fmt.Errorf("wake-up vehicle: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("max charge current %.3gA: %w", chargeCurrent, err)
|
||||
return fmt.Errorf("set charge current limit %.3gA: %w", current, err)
|
||||
}
|
||||
|
||||
lp.log.DEBUG.Printf("max charge current: %.3gA", chargeCurrent)
|
||||
lp.chargeCurrent = chargeCurrent
|
||||
lp.bus.Publish(evChargeCurrent, chargeCurrent)
|
||||
lp.log.DEBUG.Printf("set charge current limit: %.3gA", current)
|
||||
lp.offeredCurrent = current
|
||||
lp.bus.Publish(evChargeCurrent, current)
|
||||
}
|
||||
|
||||
// set enabled/disabled
|
||||
if enabled := chargeCurrent >= effMinCurrent; enabled != lp.enabled {
|
||||
if enabled := current >= effMinCurrent; enabled != lp.enabled {
|
||||
if err := lp.charger.Enable(enabled); err != nil {
|
||||
v := lp.GetVehicle()
|
||||
if vv, ok := v.(api.Resurrector); enabled && ok && errors.Is(err, api.ErrAsleep) {
|
||||
|
|
@ -900,10 +900,10 @@ func (lp *Loadpoint) setLimit(chargeCurrent float64) error {
|
|||
|
||||
// ensure we always re-set current when enabling charger
|
||||
if !enabled {
|
||||
lp.chargeCurrent = 0
|
||||
lp.offeredCurrent = 0
|
||||
}
|
||||
|
||||
lp.bus.Publish(evChargeCurrent, chargeCurrent)
|
||||
lp.bus.Publish(evChargeCurrent, current)
|
||||
|
||||
// start/stop vehicle wake-up timer
|
||||
if enabled {
|
||||
|
|
@ -1090,7 +1090,7 @@ func (lp *Loadpoint) updateChargerStatus() (bool, error) {
|
|||
}
|
||||
|
||||
// update whenever there is a state change
|
||||
lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
|
||||
lp.bus.Publish(evChargeCurrent, lp.offeredCurrent)
|
||||
}
|
||||
|
||||
return welcomeCharge, nil
|
||||
|
|
@ -1105,10 +1105,10 @@ func (lp *Loadpoint) effectiveCurrent() float64 {
|
|||
// adjust actual current for vehicles like Zoe where it remains below target
|
||||
if lp.chargeCurrents != nil {
|
||||
cur := max(lp.chargeCurrents[0], lp.chargeCurrents[1], lp.chargeCurrents[2])
|
||||
return min(cur+2.0, lp.chargeCurrent)
|
||||
return min(cur+2.0, lp.offeredCurrent)
|
||||
}
|
||||
|
||||
return lp.chargeCurrent
|
||||
return lp.offeredCurrent
|
||||
}
|
||||
|
||||
// elapsePVTimer puts the pv enable/disable timer into elapsed state
|
||||
|
|
@ -1767,7 +1767,7 @@ func (lp *Loadpoint) Update(sitePower, batteryBoostPower float64, rates api.Rate
|
|||
lp.energyMetrics.SetEnvironment(greenShare, effPrice, effCo2)
|
||||
|
||||
// update ChargeRater here to make sure initial meter update is caught
|
||||
lp.bus.Publish(evChargeCurrent, lp.chargeCurrent)
|
||||
lp.bus.Publish(evChargeCurrent, lp.offeredCurrent)
|
||||
lp.bus.Publish(evChargePower, lp.chargePower)
|
||||
|
||||
// update progress and soc before status is updated
|
||||
|
|
|
|||
|
|
@ -610,7 +610,7 @@ func (lp *Loadpoint) GetMaxPhaseCurrent() float64 {
|
|||
lp.RLock()
|
||||
defer lp.RUnlock()
|
||||
if lp.chargeCurrents == nil {
|
||||
return lp.chargeCurrent
|
||||
return lp.offeredCurrent
|
||||
}
|
||||
return max(lp.chargeCurrents[0], lp.chargeCurrents[1], lp.chargeCurrents[2])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,11 +84,11 @@ func TestSyncChargerCurrentsByGetter(t *testing.T) {
|
|||
status: api.StatusC,
|
||||
enabled: true,
|
||||
phases: 3,
|
||||
chargeCurrent: tc.lpCurrent,
|
||||
offeredCurrent: tc.lpCurrent,
|
||||
}
|
||||
|
||||
require.NoError(t, lp.syncCharger())
|
||||
assert.Equal(t, tc.outCurrent, lp.chargeCurrent)
|
||||
assert.Equal(t, tc.outCurrent, lp.offeredCurrent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,12 +120,12 @@ func TestSyncChargerCurrentsByMeasurement(t *testing.T) {
|
|||
status: api.StatusC,
|
||||
enabled: true,
|
||||
phases: 3,
|
||||
chargeCurrent: tc.lpCurrent,
|
||||
offeredCurrent: tc.lpCurrent,
|
||||
chargeCurrents: []float64{tc.actualCurrent, 0, 0},
|
||||
}
|
||||
|
||||
require.NoError(t, lp.syncCharger())
|
||||
assert.Equal(t, tc.outCurrent, lp.chargeCurrent)
|
||||
assert.Equal(t, tc.outCurrent, lp.offeredCurrent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ func TestDisableAndEnableAtTargetSoc(t *testing.T) {
|
|||
attachListeners(t, lp)
|
||||
|
||||
lp.enabled = true
|
||||
lp.chargeCurrent = minA
|
||||
lp.offeredCurrent = minA
|
||||
lp.status = api.StatusC
|
||||
|
||||
t.Log("charging below soc target")
|
||||
|
|
@ -490,7 +490,7 @@ func TestSetModeAndSocAtDisconnect(t *testing.T) {
|
|||
attachListeners(t, lp)
|
||||
|
||||
lp.enabled = true
|
||||
lp.chargeCurrent = minA
|
||||
lp.offeredCurrent = minA
|
||||
lp.mode = api.ModeNow
|
||||
|
||||
t.Log("charging at min")
|
||||
|
|
@ -556,7 +556,7 @@ func TestChargedEnergyAtDisconnect(t *testing.T) {
|
|||
attachListeners(t, lp)
|
||||
|
||||
lp.enabled = true
|
||||
lp.chargeCurrent = maxA
|
||||
lp.offeredCurrent = maxA
|
||||
lp.mode = api.ModeNow
|
||||
|
||||
// attach cache for verifying values
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue