Skip to content
Open
Show file tree
Hide file tree
Changes from 191 commits
Commits
Show all changes
216 commits
Select commit Hold shift + click to select a range
53510e8
fix power scale
daniel309 Jun 5, 2025
957325d
add limittemp
daniel309 Jun 5, 2025
eea11a7
add LPC mode register values as comment
daniel309 Jun 5, 2025
d8c4ac2
Merge branch 'master' into master
daniel309 Jun 6, 2025
686fa41
Merge branch 'master' into master
daniel309 Jun 6, 2025
024ec33
Merge branch 'evcc-io:master' into master
daniel309 Jun 7, 2025
42adbdc
Merge branch 'master' of https://github.com/daniel309/evcc
daniel309 Feb 24, 2026
29c516f
Merge branch 'master' of https://github.com/daniel309/evcc
daniel309 Feb 27, 2026
053eab6
Merge remote-tracking branch 'upstream/master'
daniel309 Mar 11, 2026
0fc1f68
feat: add temperature-based household load correction
daniel309 Mar 2, 2026
dcc047d
Implement heater profile separation for temperature correction
daniel309 Mar 11, 2026
91ba003
fix: remove incorrect temperature correction fallback
daniel309 Mar 11, 2026
c35e440
feat: add debug logging for heater profile separation
daniel309 Mar 11, 2026
0050874
feat: require explicit configuration for temperature correction
daniel309 Mar 11, 2026
2e73f28
chore: remove documentation files
daniel309 Mar 11, 2026
1b0fe62
refactor: remove unnecessary nearestRate() function
daniel309 Mar 11, 2026
c3a7988
refactor: add meter type constants for clarity
daniel309 Mar 11, 2026
c5629bb
feat: use _household constant with GORM default value
daniel309 Mar 15, 2026
ebe56c9
fix: address code review comments
daniel309 Mar 15, 2026
807d967
refactor: pre-index rates for clearer temperature lookup
daniel309 Mar 15, 2026
d7fd335
fix: remove trailing whitespace for linter
daniel309 Mar 15, 2026
8dcdc6a
fix: correct indentation for gci linter
daniel309 Mar 15, 2026
7c9ab6c
fix: remove all trailing whitespace from blank lines
daniel309 Mar 15, 2026
2ce3d68
feat: add loadpoint-specific energy tracking to metrics
daniel309 Mar 15, 2026
1618227
Increase loadpoint meter ID offset to 1000 and extract as constant
daniel309 Mar 15, 2026
ce86770
Fix formatting (golangci-lint)
daniel309 Mar 15, 2026
2c5affb
Extract 24h average temperature calculation into separate function
daniel309 Mar 15, 2026
346f54c
Improve heater profile debug message with slot count
daniel309 Mar 16, 2026
976c63e
Add debug logging for temperature correction adjustments
daniel309 Mar 16, 2026
40796d5
Fix temperature correction debug message units (kWh -> Wh)
daniel309 Mar 16, 2026
9976bcb
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 16, 2026
ecd3cf7
Merge branch 'master' of https://github.com/evcc-io/evcc into feature…
daniel309 Mar 16, 2026
55225da
fix: scale kWh to Wh in 15min consumption debug logs
daniel309 Mar 17, 2026
1521829
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Mar 17, 2026
e632bd0
test: add temperature correction tests
daniel309 Mar 17, 2026
297cf68
fix: format test file
daniel309 Mar 17, 2026
61f8ae0
Remove heatingThreshold configuration and logic
daniel309 Mar 18, 2026
0e8a216
Replace heatingCoefficient with per-charger OutdoorTemperatureSensiti…
daniel309 Mar 18, 2026
bd67797
Shorten comments to match codebase style
daniel309 Mar 19, 2026
194671e
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 19, 2026
841cd7f
Add safety bounds to temperature correction factor
daniel309 Mar 19, 2026
027c7fd
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Mar 19, 2026
9bc25d1
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 20, 2026
5416b94
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 20, 2026
d90f825
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 23, 2026
8a0ef6f
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 24, 2026
a466035
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 25, 2026
7fc4cec
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 25, 2026
823e05d
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 26, 2026
717e40b
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 27, 2026
2cd27e3
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 30, 2026
51ea81d
Merge branch 'master' into feature/temperature-correction
daniel309 Mar 31, 2026
fac693d
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 3, 2026
3373291
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 3, 2026
142d8b1
Merge master into feature/temperature-correction
daniel309 Apr 9, 2026
18a8414
fix: resolve duplicate features key in luxtronik template
daniel309 Apr 9, 2026
6ed26b6
merge upstream/master, adapt to entity-based metrics, improve error m…
daniel309 Apr 18, 2026
00ee4fa
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 19, 2026
eac0554
fix loadpoint energy tracking: use AddEnergy instead of manual calcul…
daniel309 Apr 19, 2026
56106d3
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 20, 2026
4c6a36a
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 20, 2026
22d2d5f
fix: skip temp correction log when load is 0
daniel309 Apr 20, 2026
b2c68c8
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Apr 20, 2026
85da0d5
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 21, 2026
1e43c89
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 24, 2026
30bbead
refine temp correction debug logging
daniel309 Apr 24, 2026
a645f38
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Apr 24, 2026
3d92c9f
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 26, 2026
67d8626
merge upstream/master
daniel309 Apr 29, 2026
2d9da3c
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Apr 29, 2026
bf69bd1
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 29, 2026
6fa1b5a
fix error handling for metrics.ErrIncomplete
daniel309 Apr 29, 2026
761fbc0
Merge branch 'master' into feature/temperature-correction
daniel309 Apr 30, 2026
b764419
Merge branch 'master' into feature/temperature-correction
daniel309 May 3, 2026
23e0aa2
Merge branch 'master' into feature/temperature-correction
daniel309 May 4, 2026
31c9a54
Merge branch 'master' into feature/temperature-correction
daniel309 May 15, 2026
d0e0e80
fix formatting
daniel309 May 15, 2026
dac3e8b
Merge remote-tracking branch 'upstream/master' into feature/temperatu…
daniel309 May 15, 2026
192e22f
Merge upstream/master: resolve conflicts, simplify heating energy tra…
daniel309 May 15, 2026
19b0fb1
Merge branch 'master' into feature/temperature-correction
daniel309 May 17, 2026
23d9675
Merge branch 'master' into feature/temperature-correction
daniel309 May 18, 2026
c190abd
Merge branch 'master' into feature/temperature-correction
daniel309 May 19, 2026
a81c013
Merge branch 'master' into feature/temperature-correction
daniel309 May 20, 2026
fb8ed10
Merge branch 'master' into feature/temperature-correction
daniel309 May 20, 2026
d0881fa
Merge branch 'master' into feature/temperature-correction
daniel309 May 21, 2026
4573f71
Merge branch 'master' into feature/temperature-correction
daniel309 May 21, 2026
80fc47e
Merge branch 'master' into feature/temperature-correction
daniel309 May 26, 2026
8bc72ec
Merge branch 'master' into feature/temperature-correction
daniel309 May 27, 2026
3c78534
skip temp correction when forecast near room temp
daniel309 May 27, 2026
922d73e
Merge branch 'master' into feature/temperature-correction
daniel309 Jun 4, 2026
8bb7fc7
Merge branch 'master' into feature/temperature-correction
daniel309 Jun 5, 2026
e40a64d
Merge master
daniel309 Jun 7, 2026
5c6d961
Core: rename temperature forecast feature
daniel309 Jun 9, 2026
b9f73ef
Merge master
daniel309 Jun 9, 2026
b972f8b
Fix feature enum text parsing
daniel309 Jun 9, 2026
bc1a710
Fmt feature enum
daniel309 Jun 9, 2026
237576a
Merge branch 'master' into feature/temperature-correction
daniel309 Jun 11, 2026
893781b
Merge branch 'master' into feature/temperature-correction
daniel309 Jun 15, 2026
22be5ac
Merge remote-tracking branch 'origin/master' into feature/temperature…
daniel309 Jun 19, 2026
0d7223a
Merge upstream/master into feature/temperature-correction
daniel309 Jun 19, 2026
e5a9a58
Merge branch 'master' into feature/temperature-correction
daniel309 Jun 26, 2026
28bf49b
Merge remote-tracking branch 'upstream/master' into feature/temperatu…
daniel309 Jun 28, 2026
b7ca036
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Jun 28, 2026
1ca6c09
merge upstream/master
daniel309 Jul 19, 2026
a0f8f4b
revert loadpoint.go comment to upstream
daniel309 Jul 19, 2026
16abb22
remove redundant loadpoint energy tracking from site.go
daniel309 Jul 19, 2026
3698f95
fix redundant nil checks and shadowed lp variable
daniel309 Jul 19, 2026
2d7edef
refactor: replace ScaleLoadByTemperatureForecast with DemandProfileWe…
daniel309 Jul 19, 2026
56ad6fa
Merge branch 'master' into feature/temperature-correction
daniel309 Jul 19, 2026
689fc94
reduce base load history window from 30 to 7 days
daniel309 Jul 19, 2026
f5782c0
revert: restore 30-day base load history window
daniel309 Jul 21, 2026
bdf69a1
merge upstream/master
daniel309 Jul 21, 2026
c443bf8
Merge remote-tracking branch 'upstream/master' into feature/temperatu…
daniel309 Aug 10, 2026
74ec58f
add warmwaterswitch.tpl; enforce mutual exclusion of demand profiles
daniel309 Aug 10, 2026
3fc8000
rename DemandProfileTemperature to DemandProfileDailyTemperature
daniel309 Aug 10, 2026
736d2e8
rename DemandProfileWeekly to DemandProfileSameWeekday
daniel309 Aug 10, 2026
299d18f
DemandProfileSameWeekday: average over past 4 same-weekday occurrences
daniel309 Aug 10, 2026
b1c842e
homeProfile: use same-weekday avg for base load instead of 30-day all…
daniel309 Aug 10, 2026
cda9e20
extract load prediction logic into site_load_predictor.go
daniel309 Aug 10, 2026
570f945
openapi: add chargerFeatureDailyTemperature and chargerFeatureSameWee…
daniel309 Aug 10, 2026
7727ec1
fix gci formatting
daniel309 Aug 10, 2026
1a6d18c
openapi: generate chargerFeatureDailyTemperature and chargerFeatureSa…
daniel309 Aug 10, 2026
e5b48a2
openapi: update mcp/openapi.json with new charger features
daniel309 Aug 10, 2026
bac2104
openapi: fix charger feature key names to match Go enum strings
daniel309 Aug 10, 2026
767a637
fix enumer header to match go:generate directive
daniel309 Aug 10, 2026
a056e19
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 12, 2026
99b4463
Simplify home load profile and weekday energy query
andig Aug 12, 2026
5874492
Fix weekday energy profile never matching any row
andig Aug 12, 2026
0a90e81
Make weekday profile filter type-safe
andig Aug 12, 2026
420f2fe
Move heating demand profile to loadpoint
andig Aug 12, 2026
9a7a611
Stop heating demand above threshold, simplify profile tiling
andig Aug 12, 2026
b7e47b2
Move demandProfile to loadpoint_load_predictor.go
andig Aug 12, 2026
e9bf4d4
Remove unused warmwaterswitch template include
andig Aug 12, 2026
7e7b051
Add heating demand after measured blend, exclude heaters from unmodel…
andig Aug 12, 2026
85ca398
Simplify
andig Aug 12, 2026
819e63e
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 12, 2026
b4fb1b3
Simplify
andig Aug 13, 2026
139f391
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 13, 2026
68992dc
Tariff (Energy-Charts): cache forecast requests for 1h (#32800)
github-actions[bot] Aug 13, 2026
7b6b8da
Deye: simplify curtailment scaling (#32798)
andig Aug 13, 2026
3569ffc
Sonnenbatterie: cache repeated http status requests (#32797)
github-actions[bot] Aug 13, 2026
c4d2d14
Atmoce: remove battery curtailment (#32803)
github-actions[bot] Aug 13, 2026
3e9239e
chore: add api.CurrentLimiter (#32804)
andig Aug 13, 2026
6316948
Voltie: add the firmware 352 capabilities (#32783)
voltie-eu Aug 13, 2026
c597263
MCP: expose state, sessions and experimental endpoints (#32806)
andig Aug 13, 2026
446195e
Config UI: mobile optimized section navigation (#32810)
naltatis Aug 13, 2026
96cc567
UI: fix auto power unit for negative values (#32813)
naltatis Aug 13, 2026
9b31cf4
Fronius Gen24: add PV curtailment support (#32823)
tilalx Aug 14, 2026
a63ddac
ioBroker: update installation and auth details (#32817)
kscholty Aug 14, 2026
63a850b
Goodwe: add curtailment (BC) (#32795)
github-actions[bot] Aug 14, 2026
9ab5146
SunEnergyXT: add SunEnergyXT 500 template (#30852)
ThorbenCarl Aug 14, 2026
1264475
Battery Boost: allow scaling to 3p while active (#32776)
mfuchs1984 Aug 14, 2026
d7b2258
UI: fix sessions table covering heading in app (#32830)
naltatis Aug 14, 2026
03ebcff
Optimizer UI: migrate charts to echarts, remove chart.js (#32837)
naltatis Aug 14, 2026
df7bb70
Config UI: prevent accidental modal close with unsaved changes (#32826)
naltatis Aug 14, 2026
4c5f33a
PV: reserve only min power for higher-priority loadpoints starting up…
andig Aug 14, 2026
8833cf5
Alpitronic: update handling for power absorption and fix status logic…
premultiply Aug 14, 2026
7f50952
EEBus: fix stated limit duration expiring at half its length (#32856)
andig Aug 15, 2026
425c581
Optimizer: consider planner precondition (late charging) (#32872)
andig Aug 16, 2026
3811447
Kia/Hyundai EU: add OneApp/CCI login to fix new-login WAF block (#32868)
TMA84 Aug 16, 2026
4b219b6
SunEnergyXT 500: fix battery control (#32866)
epplea Aug 16, 2026
e815894
chore: publish the homebrew package as a cask (#32874)
andig Aug 16, 2026
e24d1b1
chore: fix release notes changelog template (#32877)
andig Aug 16, 2026
3606078
chore: make the restored docker cache mounts writable (#32882)
andig Aug 16, 2026
78645c6
chore: build the release and nightly images on depot (#32883)
andig Aug 16, 2026
2e63480
GoodWe: list ESA series under hybrid template (#32884)
andig Aug 16, 2026
08ef55c
Modbus templates: share block reads (#32887)
andig Aug 16, 2026
ce7eac0
Optimizer: respect session energy limit when vehicle soc is unknown (…
andig Aug 16, 2026
97783e8
Add CHINT ECH10K-TH-EU inverter (#32858)
Wolle141 Aug 16, 2026
e2c59cf
Optimizer chart: day boundaries with weekday at 00:00 (#32894)
andig Aug 16, 2026
e82e744
Add Solplanet hybrid inverter (Modbus TCP) (#32888)
andig Aug 16, 2026
c698074
Site: feed the optimizer a trailing percentile solar scale (#32849)
iseeberg79 Aug 16, 2026
0fc384d
Loadpoint: fix config error for disabled loadpoints (#32880)
github-actions[bot] Aug 17, 2026
ab74ddb
Optimizer: extend horizon to 48h plus end of day (#32893)
andig Aug 17, 2026
3cfb7cd
fix: address review comments and merge upstream/master
daniel309 Aug 17, 2026
f279e8d
Merge upstream/master - resolve conflicts
daniel309 Aug 17, 2026
e9807d2
Update api/feature.go
daniel309 Aug 17, 2026
d06ceeb
EnergyProfileWeekday: fix 4x7 day window, remove from param
daniel309 Aug 17, 2026
7700045
rename DemandProfile to PredictorProfile
daniel309 Aug 17, 2026
c0fe4fc
warmwaterswitch.tpl: always-DHW devices use predictorprofileweekday
daniel309 Aug 17, 2026
954ca5f
fix gci formatting
daniel309 Aug 17, 2026
5a357c3
EnergyProfileWeekday: use now.BeginningOfDay for DST correctness
daniel309 Aug 18, 2026
4ae52b4
heatpumpswitch: always predictorprofiletemperature - combined heatpum…
daniel309 Aug 18, 2026
8e874e4
Merge remote-tracking branch 'upstream/master' into feature/temperatu…
daniel309 Aug 18, 2026
6eaba77
move warmwaterswitch.tpl to charger includes dir (upstream #32871)
daniel309 Aug 18, 2026
fa42758
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 18, 2026
a97ef2b
rename PredictorProfileWeekday to PredictorProfileSameWeekday
daniel309 Aug 18, 2026
71d22b7
fix gci alignment for PredictorProfileSameWeekday
daniel309 Aug 18, 2026
152db5f
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 18, 2026
b64c434
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 19, 2026
53493f4
homeProfile: prefer same-weekday profile, fall back to all-days avg
daniel309 Aug 20, 2026
47832d7
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 20, 2026
6d932b4
homeProfile: log weekday profile path and fallback reason
daniel309 Aug 20, 2026
1e41dd6
rename feature flags: PredictorProfile* -> Demand*
daniel309 Aug 20, 2026
c7a1843
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 20, 2026
ee7d8b3
rename feature flags in mcp openapi.json
daniel309 Aug 20, 2026
8e9e998
rename feature flags in device templates
daniel309 Aug 20, 2026
206f07c
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 21, 2026
add6ede
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 24, 2026
c8db2ea
demand forecast: use 7-day window for demandtemperature profile
daniel309 Aug 24, 2026
c783add
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 24, 2026
b8339e1
Askoheat: add warmwaterswitch tpl as demandWeekday example
daniel309 Aug 25, 2026
1d20681
chore: revert warmwaterswitch to heatpumpswitch in emsesp, lg-therma,…
daniel309 Aug 25, 2026
dcea485
Demand forecast: set demandtemperature/demandweekday directly in temp…
daniel309 Aug 25, 2026
925ebb0
Demand forecast: set demandtemperature/demandweekday directly in temp…
daniel309 Aug 25, 2026
89f182e
Merge remote-tracking branch 'upstream/master' into feature/temperatu…
daniel309 Aug 30, 2026
3d4edba
Demand forecast: remove template tags, add DemandDaily feature, clean…
daniel309 Aug 30, 2026
7110617
Optimizer: restore now.With(horizon).EndOfDay() from master
daniel309 Aug 30, 2026
37403de
openapi: regenerate mcp/openapi.json for DemandDaily
daniel309 Aug 30, 2026
89f7d8d
Charger: add predictor config key for demand forecast features
daniel309 Aug 31, 2026
06b4e57
Demand forecast: fix temperature correction and weekday profile tiling
daniel309 Aug 31, 2026
426704b
Demand forecast: fix temperature correction and weekday profile tiling
daniel309 Aug 31, 2026
82aa3f7
Merge branch 'master' into feature/temperature-correction
daniel309 Aug 31, 2026
8428799
Merge branch 'feature/temperature-correction' of https://github.com/d…
daniel309 Aug 31, 2026
fae766b
Demand forecast: fix TestApplyTemperatureCorrection after heating thr…
daniel309 Aug 31, 2026
e83027a
Update core/site_load_predictor.go
daniel309 Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions api/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ type Feature int

//go:generate go tool enumer -type Feature -text
const (
_ Feature = iota
CoarseCurrent // charger
IntegratedDevice // charger - always connected - no vehicle, no charging sessions
SwitchDevice // charger - no current control - heat pumps or switch sockets
Heating // charger - heating device - soc ist temperature (°C)
Continuous // charger - heating device where disabled means "normal operation"
Average // tariff
Cacheable // tariff
Offline // vehicle
Retryable // vehicle
Streaming // vehicle
WelcomeCharge // vehicle
ClimaterDisabled // vehicle - ignore climater state for charge control
AutodetectDisabled // vehicle - do not try to identify vehicle by status
WakeUpDisabled // vehicle - do not send wake-up calls
_ Feature = iota
CoarseCurrent // charger
IntegratedDevice // charger - always connected - no vehicle, no charging sessions
SwitchDevice // charger - no current control - heat pumps or switch sockets
Heating // charger - heating device - soc ist temperature (°C)
PredictorProfileSameWeekday // charger - demand forecast: same weekday last week (warm water)
PredictorProfileTemperature // charger - demand forecast: daily avg scaled by outdoor temp (room heating)
Continuous // charger - heating device where disabled means "normal operation"
Average // tariff
Cacheable // tariff
Offline // vehicle
Retryable // vehicle
Streaming // vehicle
WelcomeCharge // vehicle
ClimaterDisabled // vehicle - ignore climater state for charge control
AutodetectDisabled // vehicle - do not try to identify vehicle by status
WakeUpDisabled // vehicle - do not send wake-up calls
)
96 changes: 52 additions & 44 deletions api/feature_enumer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions assets/js/types/evcc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,10 @@ export interface Loadpoint {
chargerFeatureCoarseCurrent: boolean;
/** Charger is a heating device where disabled means normal operation. */
chargerFeatureContinuous: boolean;
/** Heating device demand forecast uses daily average profile scaled by outdoor temperature. */
chargerFeaturePredictorProfileTemperature: boolean;
/** Heating device demand forecast uses same-weekday average over past 4 weeks. */
chargerFeaturePredictorProfileSameWeekday: boolean;
/** Charger is a heating device. SoC values represent temperature in degrees. */
chargerFeatureHeating: boolean;
/** Charger is an always-connected device without vehicles and charging sessions, like a heat pump. */
Expand Down
39 changes: 39 additions & 0 deletions core/loadpoint_load_predictor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package core

import (
"time"

"github.com/evcc-io/evcc/api"
)

// demandProfile returns the heating demand profile of a heating loadpoint and whether
// it needs to be scaled by the outdoor temperature forecast. Returns nil when unavailable.
func (lp *Loadpoint) demandProfile(from time.Time) (*[96]float64, bool) {
if lp.chargeEnergy == nil || !lp.chargerHasFeature(api.Heating) {
Comment thread
andig marked this conversation as resolved.
return nil, false
}

var profile *[96]float64
var err error

// daily avg scaled by outdoor temp
temp := lp.chargerHasFeature(api.PredictorProfileTemperature)

switch {
case temp:
profile, err = lp.chargeEnergy.EnergyProfile(from)

case lp.chargerHasFeature(api.PredictorProfileSameWeekday):
profile, err = lp.chargeEnergy.EnergyProfileWeekday(time.Now().Weekday())
Comment thread
andig marked this conversation as resolved.
Outdated

default:
return nil, false
}

if err != nil {
lp.log.DEBUG.Printf("demand profile: %v", err)
return nil, false
}

return profile, temp
}
9 changes: 8 additions & 1 deletion core/metrics/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/evcc-io/evcc/server/db"
"github.com/evcc-io/evcc/tariff"
"github.com/jinzhu/now"
)

const (
Expand Down Expand Up @@ -173,7 +174,13 @@ func (c *Collector) SetSocTemp(value float64, isTemp bool) error {
}

func (c *Collector) EnergyProfile(from time.Time) (*[96]float64, error) {
return energyProfile(c.entity, from)
return energyProfileFiltered(c.entity, from, nil)
}

func (c *Collector) EnergyProfileWeekday(weekday time.Weekday) (*[96]float64, error) {
wd := int(weekday)
from := now.BeginningOfDay().AddDate(0, 0, -28)
return energyProfileFiltered(c.entity, from, &wd)
}

// LastSlotEnergy returns the energy in kWh of the most recently completed
Expand Down
27 changes: 18 additions & 9 deletions core/metrics/db_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,30 @@ import (

var ErrIncomplete = errors.New("meter profile incomplete")

// energyProfile returns a 15min average meter profile in Wh. The profile
// is sorted by timestamp starting at 00:00. It is guaranteed to contain 96 15min values.
func energyProfile(entity entity, from time.Time) (*[96]float64, error) {
db, err := db.Instance.DB()
// energyProfileFiltered queries the 96-slot profile, optionally restricted to a
// single weekday (strftime %w, 0=Sunday).
func energyProfileFiltered(entity entity, from time.Time, weekday *int) (*[96]float64, error) {
database, err := db.Instance.DB()
if err != nil {
return nil, err
}

args := []any{entity.Id, from.Unix()}

var weekdayFilter string
if weekday != nil {
// CAST is required, strftime returns TEXT which never compares equal to an integer
weekdayFilter = ` AND CAST(strftime('%w', ts, 'unixepoch', 'localtime') AS INTEGER) = ?`
args = append(args, *weekday)
}

// COALESCE guards against legacy rows with NULL energy
rows, err := db.Query(`SELECT min(ts) AS ts, COALESCE(avg(energy), 0) AS energy
rows, err := database.Query(`SELECT min(ts) AS ts, COALESCE(avg(energy), 0) AS energy
FROM meters
WHERE meter = ? AND ts >= ? AND COALESCE(recovered, 0) = 0
GROUP BY strftime("%H:%M", ts, 'unixepoch', 'localtime')
ORDER BY strftime("%H:%M", ts, 'unixepoch', 'localtime') ASC`,
entity.Id, from.Unix(),
WHERE meter = ? AND ts >= ? AND COALESCE(recovered, 0) = 0`+weekdayFilter+`
GROUP BY strftime('%H:%M', ts, 'unixepoch', 'localtime')
ORDER BY strftime('%H:%M', ts, 'unixepoch', 'localtime') ASC`,
args...,
)
if err != nil {
return nil, err
Expand Down
44 changes: 44 additions & 0 deletions core/metrics/db_profile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package metrics

import (
"testing"
"time"

"github.com/evcc-io/evcc/server/db"
"github.com/evcc-io/evcc/tariff"
"github.com/jinzhu/now"
"github.com/stretchr/testify/require"
)

func TestEnergyProfileWeekday(t *testing.T) {
Comment thread
daniel309 marked this conversation as resolved.
require.NoError(t, db.NewInstance("sqlite", ":memory:"))
require.NoError(t, SetupSchema())

e := entity{Id: 2, Name: "pv1", Group: PV}
require.NoError(t, db.Instance.Create(&e).Error)

// 4 weeks of full days, today's weekday carries a distinct energy value
today := time.Now().Weekday()
for day := -28; day < 0; day++ {
base := now.BeginningOfDay().AddDate(0, 0, day)

energy := 1.0
if base.Weekday() == today {
energy = 2.0
}

for slot := range 96 {
ts := base.Add(time.Duration(slot) * tariff.SlotDuration)
require.NoError(t, persist(e, ts, energy, 0, nil, false))
}
}

weekday := int(today)
res, err := energyProfileFiltered(e, now.BeginningOfDay().AddDate(0, 0, -28), &weekday)
require.NoError(t, err)

// only same-weekday slots must be averaged
for i, v := range res {
require.Equal(t, 2.0, v, "slot %d", i)
}
}
4 changes: 2 additions & 2 deletions core/metrics/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ func TestUpdateProfile(t *testing.T) {
{
from := clock.Now().Local().AddDate(0, 0, -2).Add(12 * time.Hour) // 12:00 of day 0

prof, err := energyProfile(entity, from)
prof, err := energyProfileFiltered(entity, from, nil)
require.NoError(t, err)

var expected [96]float64
Expand All @@ -267,7 +267,7 @@ func TestUpdateProfile(t *testing.T) {
{
from := clock.Now().Local().AddDate(0, 0, -3).Add(12 * time.Hour) // 12:00 of day -1

prof, err := energyProfile(entity, from)
prof, err := energyProfileFiltered(entity, from, nil)
require.NoError(t, err)

var expected [96]float64
Expand Down
Loading
Loading