Optimizer: split grid peak shaping into demand, feed-in and combined strategies#32108
Conversation
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="assets/js/components/Optimize/OptimizeHeader.vue" line_range="126-127" />
<code_context>
// themselves come from backend state to avoid drift if the enum changes
const STRATEGY_LABELS: Record<string, string> = {
charge_before_export: "fill battery first",
+ attenuate_demand_peaks: "reduce grid import peaks",
+ attenuate_feedin_peaks: "reduce grid feed-in peaks",
attenuate_grid_peaks: "reduce grid peaks",
none: "no preference",
</code_context>
<issue_to_address>
**suggestion:** Tighten the type of STRATEGY_LABELS to the known strategy key union instead of `Record<string, string>`.
Because these keys correspond to a finite backend enum, typing this as `Record<OptimizerChargingStrategy, string>` or a union of the literal keys will catch typos and missing strategies at compile time instead of only at runtime, and will scale better as the list grows.
Suggested implementation:
```
type OptimizerChargingStrategy =
| "charge_before_export"
| "attenuate_demand_peaks"
| "attenuate_feedin_peaks"
| "attenuate_grid_peaks"
| "none";
// themselves come from backend state to avoid drift if the enum changes
const STRATEGY_LABELS: Record<OptimizerChargingStrategy, string> = {
charge_before_export: "fill battery first",
attenuate_demand_peaks: "reduce grid import peaks",
attenuate_feedin_peaks: "reduce grid feed-in peaks",
attenuate_grid_peaks: "reduce grid peaks",
none: "no preference",
};
```
If a shared `OptimizerChargingStrategy` type already exists in your backend-typed models (e.g. in a `types` or `api` module), prefer importing that instead of defining the local union:
1. Remove the local `type OptimizerChargingStrategy = ...` definition.
2. Add `import type { OptimizerChargingStrategy } from "<appropriate-path>";` at the top of the `<script>` block.
3. Keep `const STRATEGY_LABELS: Record<OptimizerChargingStrategy, string> = { ... }` as-is.
This ensures the labels stay in sync with the backend enum and that missing/extra strategies are caught at compile time.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| attenuate_demand_peaks: "reduce grid import peaks", | ||
| attenuate_feedin_peaks: "reduce grid feed-in peaks", |
There was a problem hiding this comment.
suggestion: Tighten the type of STRATEGY_LABELS to the known strategy key union instead of Record<string, string>.
Because these keys correspond to a finite backend enum, typing this as Record<OptimizerChargingStrategy, string> or a union of the literal keys will catch typos and missing strategies at compile time instead of only at runtime, and will scale better as the list grows.
Suggested implementation:
type OptimizerChargingStrategy =
| "charge_before_export"
| "attenuate_demand_peaks"
| "attenuate_feedin_peaks"
| "attenuate_grid_peaks"
| "none";
// themselves come from backend state to avoid drift if the enum changes
const STRATEGY_LABELS: Record<OptimizerChargingStrategy, string> = {
charge_before_export: "fill battery first",
attenuate_demand_peaks: "reduce grid import peaks",
attenuate_feedin_peaks: "reduce grid feed-in peaks",
attenuate_grid_peaks: "reduce grid peaks",
none: "no preference",
};
If a shared OptimizerChargingStrategy type already exists in your backend-typed models (e.g. in a types or api module), prefer importing that instead of defining the local union:
- Remove the local
type OptimizerChargingStrategy = ...definition. - Add
import type { OptimizerChargingStrategy } from "<appropriate-path>";at the top of the<script>block. - Keep
const STRATEGY_LABELS: Record<OptimizerChargingStrategy, string> = { ... }as-is.
This ensures the labels stay in sync with the backend enum and that missing/extra strategies are caught at compile time.
This comment has been minimized.
This comment has been minimized.
|
✅ Nightly build from master finished. |
Picks up evcc-io/optimizer#96, which reworks the
attenuate_grid_peakssecondary goal. Peak shaping is now a penalty on the horizon maximum of the grid power, so charging spreads over several slots at partial power instead of running a single slot at full power, and the metered side it applies to is selectable:attenuate_demand_peaksattenuate_feedin_peaksattenuate_grid_peaksattenuate_grid_peakskeeps its name and now means "both sides", so existing settings keep peak shaping on the side they expected plus the feed-in side.Both new strategies are added to the accepted list and therefore show up in the secondary goal selector on the optimize page.
🤖 Generated with Claude Code