Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lastmanagement #8427

Closed
wants to merge 65 commits into from
Closed
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
996d711
Loadmanagement_1
Feb 14, 2023
f5a208d
fix configure
Feb 20, 2023
339acb4
improve logging
hoermto Feb 24, 2023
d81e4c1
Rebased
andig Feb 25, 2023
e874df9
Simplify
andig Feb 25, 2023
1e2d53a
Konsistenz
andig Feb 25, 2023
367a123
Fix rebase
andig Feb 26, 2023
f20055b
revert order of initialization
Mar 2, 2023
ce5bce2
refactor setup, remove name from circuit, use id for logging circuit …
Mar 2, 2023
4977a36
numeric id for uichan
Mar 5, 2023
75e330c
flat circuit config with parents, removed title, remove DeviceCategor…
Mar 12, 2023
683cd91
Update core/site.go
hoermto Mar 14, 2023
8aeda87
remainings
Mar 14, 2023
299b4cb
typos
Mar 14, 2023
c6c34d7
move circuit creation to setup completely
Mar 15, 2023
321ea0f
fix use of grid meter in one circuit, check duplicate name on setup
Mar 15, 2023
28ad2e2
fix UI current publishing
Mar 25, 2023
596cddf
Reorder
andig Mar 26, 2023
07b8229
Formatting and loggers
andig Mar 26, 2023
662db62
More formatting
andig Mar 26, 2023
743c1dd
Document consumer usage
andig Mar 26, 2023
1aafc58
Loadpoint comments
andig Mar 26, 2023
f54b392
Simplify test
andig Mar 26, 2023
050d6f3
wip
andig Mar 26, 2023
12457b8
TODOs
andig Mar 26, 2023
093dbe8
refactor circuit config
Apr 3, 2023
98c4a95
processing TODOs
Apr 3, 2023
28f335f
remove check for duplicate meter usage
Apr 3, 2023
501417b
Merge tag '0.115.0' into feature/lastmanagement1_grid
Apr 3, 2023
be4b620
fix UI update
Apr 11, 2023
bbc1566
Merge tag '0.116.5' into feature/lastmanagement1_grid
Apr 27, 2023
94a26e5
ensure linters happyness
Apr 27, 2023
055d9ac
Merge tag '0.117.0' into feature/lastmanagement1_grid
May 10, 2023
40a2970
add power limit to circuits
May 10, 2023
b2a99d2
Readme
May 13, 2023
a4b8866
Merge tag '0.117.2' into feature/lastmanagement1_grid
May 13, 2023
95a96f9
Merge tag '0.117.4' into feature/lastmanagement1_grid
May 22, 2023
9001abf
Merge tag '0.118.0' into feature/lastmanagement
Jun 12, 2023
60ae81a
Merge tag '0.118.1' into feature/lastmanagement
Jun 20, 2023
502e84c
Merge tag '0.118.5' into feature/lastmanagement
Jul 4, 2023
fe583d4
Merge tag '0.118.8' into feature/lastmanagement
Jul 18, 2023
52f8d4a
allow small reserve on overload check
Oct 9, 2023
911c36a
Merge tag '0.119.0' into feature/lastmanagement
Oct 9, 2023
051da83
WIP: fixes after merge from master
Oct 9, 2023
17a3725
Merge tag '0.120.0' into feature/lastmanagement
Oct 9, 2023
83184b1
Merge tag '0.120.3' into feature/lastmanagement
Oct 9, 2023
e28eca8
start charging with minCurrent to prevent initial hit, probably to be…
Oct 10, 2023
018eaed
Merge tag '0.121.5' into feature/lastmanagement
Nov 20, 2023
b5b1837
Merge tag '0.122.1' into feature/lastmanagement
Dec 25, 2023
9796f99
Merge tag '0.123.1' into feature/lastmanagement
Dec 25, 2023
26c227b
linting
Dec 25, 2023
e9ce21d
Update loadmanagement.md
hoermto Dec 28, 2023
f0c8829
Merge tag '0.123.9' into feature/lastmanagement
Feb 12, 2024
0db0ec6
Merge tag '0.124.1' into feature/lastmanagement
Feb 12, 2024
7e362be
fixes after merge
Feb 19, 2024
bc38ce8
Merge tag '0.124.2' into feature/lastmanagement
Feb 27, 2024
dc47f65
Merge tag '0.124.4' into feature/lastmanagement
Feb 27, 2024
7ebb126
use GetPhases()
Feb 29, 2024
ab73d9a
circuit return error on fail to create vMeter, not only nil
Mar 9, 2024
d423428
fix loadpoint test (add Voltage for powerToCurrent() calculation), fi…
Mar 9, 2024
91359cc
Merge tag '0.124.8' into feature/lastmanagement
Mar 9, 2024
f2af6c9
Apply suggestions from code review
andig Mar 24, 2024
c034d8b
Simplify
andig Mar 24, 2024
919ebf4
Merge branch 'master' into feature/lastmanagement
andig Mar 24, 2024
901d7e0
Update core/circuit_vmeter.go
andig Mar 31, 2024
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
10 changes: 10 additions & 0 deletions cmd/configure/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,23 @@ type loadpoint struct {
MinCurrent int
MaxCurrent int
Phases int
Circuit string
}

type circuit struct {
Name string `mapstructure:"name"` // unique name, used as reference in lp
andig marked this conversation as resolved.
Show resolved Hide resolved
MaxCurrent float64 `mapstructure:"maxCurrent"` // the max allowed current of this circuit
MaxPower float64 `mapstructure:"maxPower"` // the max allowed power of this circuit
MeterRef string `mapstructure:"meter"` // Charge meter reference
ParentRef string `mapstructure:"parent"` // name of parent circuit
}

type globalConfig struct {
Meters []device
Chargers []device
Vehicles []device
Loadpoints []loadpoint
Circuits []circuit
Site struct { // TODO Perspektivisch können wir was aus core wiederverwenden, für später
Title string
Grid string
Expand Down
11 changes: 11 additions & 0 deletions cmd/configure/configure.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,18 @@ loadpoints:
vehicle: {{ .Vehicle }}
{{- end }}
mode: {{ .Mode }}
{{- if .Circuit }}
circuit: {{ .Circuit }}
{{- end }}
{{- end }}

circuits:
{{- range .Circuits }}
- name: {{ .Name }}
maxCurrent: {{ .MaxCurrent }}
maxPower: {{ .MaxPower }}
meter: {{ .MeterRef }}
parent: {{ .ParentRef }}
{{- end }}

site:
Expand Down
38 changes: 36 additions & 2 deletions cmd/configure/localization/de.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Category_SystemAdditional = "ein weiteres"
Category_GridMeterTitle = "Netz-Stromzähler"
Category_GridMeterArticle = "einen"
Category_GridMeterAdditional = "einen weiteren"
Category_CircuitMeterTitle = "Unterverteilungs-Stromzähler"
Category_CircuitMeterArticle = "einen"
Category_CircuitMeterAdditional = "einen weiteren"
Category_PVMeterTitle = "PV Wechselrichter (oder entsprechender Stromzähler)"
Category_PVMeterArticle = "einen"
Category_PVMeterAdditional = "einen weiteren"
Expand Down Expand Up @@ -90,8 +93,10 @@ Loadpoint_Setup = "- Ladepunkt(e) einrichten"
Loadpoint_Title = "Titel des Ladepunktes"
Loadpoint_AddAnother = "Möchtest du einen weiteren Ladepunkt hinzufügen?"
Loadpoint_DefaultTitle = "Garage"
Loadpoint_ResetOnDisconnect = "Soll beim Abstecken des Ladekabels von einem Fahrzeug, die Lade-Standardeinstellungen wieder hergestellt werden?"
Loadpoint_WallboxWOMeter = "Das System konnte nicht erkennen, ob ein Ladestromzähler in der Wallbox eingebaut ist. Möchtest du einen externen Ladestromzähler hinzufügen?"
Loadpoint_CircuitYesNo = "Soll der Ladepunkt einem Stromkreis zugeordnet werden (für Lastmanagement)?"
Loadpoint_Circuit = "Stromkreis auswählen:"
Loadpoint_ResetOnDisconnect = "Soll beim Abstecken des Ladekables von einem Fahrzeug, die Lade-Standardeinstellungen wieder hergestellt werden?"
Loadpoint_WallboxWOMeter = "Das System konnte nicht erkennen ob ein Ladestromzähler in der Wallbox eingebaut ist. Möchtest du einen externen Ladestromzähler hinzufügen?"
Loadpoint_WallboxMaxPower = "Was ist die maximale Leistung, welche die Wallbox zur Verfügung stellen kann?"
Loadpoint_WallboxMinAmperage = "Was ist die MINIMALE Stromstärke, welche die Wallbox auf einer Phase zur Verfügung stellen kann?"
Loadpoint_WallboxMaxAmperage = "Was ist die MAXIMALE Stromstärke, welche die Wallbox auf einer Phase zur Verfügung stellen kann?"
Expand All @@ -111,3 +116,32 @@ ChargeModeNone = "Keinen (Benutzt den im Ladepunkt gesetzten Lademodus)"
Site_Setup = "- Standort einrichten"
Site_Title = "Titel des Standortes"
Site_DefaultTitle = "Mein Zuhause"
Circuit_Setup = "Stromkreise einrichten"
Circuit_Add = "Sollen ein oder mehrere Stromkreise konfiguriert werden?"
Circuit_AddAnother = "Möchtest Du einen weiteren Stromkreis hinzufügen?"
Circuit_Title = "Name des Stromkreises"
Circuit_TitleHelp = "Eindeutiger Name des Stromkreises"
Circuit_NameAlreadyUsed = "Name bereits vergeben"
Circuit_HasParent = "Ist der Stromkreis Teil eines anderen Stromkreises?"
Circuit_Parent = "Stromkreis auswählen"
Circuit_Meter = "Haben sie einen Stromzähler für diesen Stromkreis?"
Circuit_MaxCurrent = "Wie hoch ist der maximal zulässige Phasenstrom im Stromkreis?"
Circuit_MaxCurrentDisable = "kein Lastmanagement auf Basis Phasenstrom"
Circuit_MaxCurrent16A = "16A (max. 11 kVA)"
Circuit_MaxCurrent20A = "20A (max. 13,8 kVA)"
Circuit_MaxCurrent25A = "25A (max. 17,2 kVA)"
Circuit_MaxCurrent32A = "32A (max. 22 kVA)"
Circuit_MaxCurrent35A = "35A (max. 24 kVA)"
Circuit_MaxCurrent50A = "50A (max. 34,5 kVA)"
Circuit_MaxCurrent63A = "63A (max. 43 kVA)"
Circuit_MaxCurrent80A = "80A (max. 55,2 kVA)"
Circuit_MaxCurrent100A = "100A (max. 69 kVA)"
Circuit_MaxCurrentCustom = "anderer Wert (manuelle Eingabe)"
Circuit_MaxCurrentCustomInput = "Maximaler Strom"
Circuit_MaxPowerDisable = "kein Lastmanagement aus Basis der Leistung"
Circuit_MaxPower11kW = "11kW"
Circuit_MaxPower20kW = "20kW"
Circuit_MaxPower50kW = "50kW"
Circuit_MaxPower100kW = "100kW"
Circuit_MaxPowerCustom = "anderer Wert (manuelle Eingabe)"
Circuit_MaxPower = "Maximale Leistung"
36 changes: 35 additions & 1 deletion cmd/configure/localization/en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ Category_SystemArticle = "an"
Category_SystemAdditional = "another"
Category_GridMeterTitle = "grid meter"
Category_GridMeterArticle = "a"
Category_GridMeterAdditional = "another"
Category_GridMeterAdditional = "one more"
Category_CircuitMeterTitle = "circuit meter"
Category_CircuitMeterArticle = "a"
Category_CircuitMeterAdditional = "one more"
Category_PVMeterTitle = "PV inverter (or corresponding meter)"
Category_PVMeterArticle = "a"
Category_PVMeterAdditional = "another"
Expand Down Expand Up @@ -90,6 +93,8 @@ Loadpoint_Setup = "- Setup loadpoint(s), i.e. group of colocated chargers"
Loadpoint_Title = "Loadpoint title"
Loadpoint_AddAnother = "Do you want to add another loadpoint?"
Loadpoint_DefaultTitle = "Garage"
Loadpoint_CircuitYesNo = "Is this laodpoint attached to a circuit (for load management)?"
Loadpoint_Circuit = "Select circuit:"
Loadpoint_ResetOnDisconnect = "Will disconnecting the charging cable from the vehicle reset the charging settings to the defaults?"
Loadpoint_WallboxWOMeter = "The system could not detect if the charger provides power data. Do you want to add an external meter instead?"
Loadpoint_WallboxMaxPower = "What is the maximum power your charger can provide?"
Expand All @@ -111,3 +116,32 @@ ChargeModeNone = "None (Use what is set at the loadpoint)"
Site_Setup = "- Setup site"
Site_Title = "Site title"
Site_DefaultTitle = "My home"
Circuit_Setup = "Circuit Setup"
Circuit_Add = "Do you want to add circuits?"
Circuit_AddAnother = "Add more circuits?"
Circuit_Title = "Name of Circuit"
Circuit_TitleHelp = "Unique circuit name"
Circuit_NameAlreadyUsed = "Name already in use"
Circuit_HasParent = "Is this circuit member of another circuit?"
Circuit_Parent = "Select parent circuit"
Circuit_Meter = "Do you have a dedicated meter installed for this circuit?"
Circuit_MaxCurrent = "What is the max current (amperes) in this circuit?"
Circuit_MaxCurrentDisable = "no load management based on phase currents"
Circuit_MaxCurrent16A = "16A (max. 11 kVA)"
Circuit_MaxCurrent20A = "20A (max. 13,8 kVA)"
Circuit_MaxCurrent25A = "25A (max. 17,2 kVA)"
Circuit_MaxCurrent32A = "32A (max. 22 kVA)"
Circuit_MaxCurrent35A = "35A (max. 24 kVA)"
Circuit_MaxCurrent50A = "50A (max. 34,5 kVA)"
Circuit_MaxCurrent63A = "63A (max. 43 kVA)"
Circuit_MaxCurrent80A = "80A (max. 55,2 kVA)"
Circuit_MaxCurrent100A = "100A (max. 69 kVA)"
Circuit_MaxCurrentCustom = "other value (manual input)"
Circuit_MaxCurrentCustomInput = "max current in amperes"
Circuit_MaxPowerDisable = "no load management based on power"
Circuit_MaxPower11kW = "11kW"
Circuit_MaxPower20kW = "20kW"
Circuit_MaxPower50kW = "50kW"
Circuit_MaxPower100kW = "100kW"
Circuit_MaxPowerCustom = "other value (manual input)"
Circuit_MaxPower = "max power in kW"
149 changes: 148 additions & 1 deletion cmd/configure/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os"
"slices"
"sort"
"strconv"
"strings"

Expand Down Expand Up @@ -179,8 +180,11 @@ func (c *CmdConfigure) flowNewConfigFile() {
_ = c.configureDevices(DeviceCategoryBatteryMeter, true, true)
_ = c.configureDevices(DeviceCategoryVehicle, true, true)

c.configureLoadpoints()
c.configureSite()
if c.advancedMode {
c.configureCircuits()
}
c.configureLoadpoints()

// check if SMA HEMS is available and ask the user if it should be added
if c.capabilitySMAHems {
Expand Down Expand Up @@ -426,6 +430,17 @@ func (c *CmdConfigure) configureLoadpoints() {

fmt.Println()
loadpoint.Mode = c.askValue(question{valueType: templates.TypeChargeModes, excludeNone: true})

if len(c.configuration.config.Circuits) > 0 && c.askYesNo(c.localizedString("Loadpoint_CircuitYesNo")) {
var circuitNames []string
for _, cc := range c.configuration.config.Circuits {
circuitNames = append(circuitNames, cc.Name)
}

ccNameId, _ := c.askChoice(c.localizedString("Loadpoint_Circuit"), circuitNames)
loadpoint.Circuit = circuitNames[ccNameId]
}

c.configuration.AddLoadpoint(loadpoint)

fmt.Println()
Expand All @@ -447,3 +462,135 @@ func (c *CmdConfigure) configureSite() {
})
c.configuration.config.Site.Title = siteTitle
}

// configureCircuits asks for circuits
func (c *CmdConfigure) configureCircuits() {
fmt.Println()
fmt.Println(c.localizedString("Circuit_Setup"))

if !c.askYesNo(c.localizedString("Circuit_Add")) {
return
}

// helper to know used circuit names
circuitNames := []string{}

for {
ccName := c.askValue(question{
label: c.localizedString("Circuit_Title"),
help: c.localizedString("Circuit_TitleHelp"),
required: true,
})

if slices.Contains(circuitNames, ccName) {
fmt.Println(c.localizedString("Circuit_NameAlreadyUsed"))
continue
}
curCircuit := &circuit{Name: ccName}

curChoices := []string{
c.localizedString("Circuit_MaxCurrentDisable"), // no current checking
c.localizedString("Circuit_MaxCurrent16A"), // 11kVA
c.localizedString("Circuit_MaxCurrent20A"), // 13kVA
c.localizedString("Circuit_MaxCurrent25A"), // 17kVA
c.localizedString("Circuit_MaxCurrent32A"), // 22kVA
c.localizedString("Circuit_MaxCurrent35A"), // 24kVA
c.localizedString("Circuit_MaxCurrent50A"), // 34kVA
c.localizedString("Circuit_MaxCurrent63A"), // 43kVA
c.localizedString("Circuit_MaxCurrent80A"), // 55kVA
c.localizedString("Circuit_MaxCurrent100A"), // 69kVA
c.localizedString("Circuit_MaxCurrentCustom"),
}
fmt.Println()
curIndex, _ := c.askChoice(c.localizedString("Circuit_MaxCurrent"), curChoices)
switch curIndex {
case 0:
curCircuit.MaxCurrent = 16.0
case 1:
curCircuit.MaxCurrent = 16.0
case 2:
curCircuit.MaxCurrent = 20.0
case 3:
curCircuit.MaxCurrent = 25.0
case 4:
curCircuit.MaxCurrent = 32.0
case 5:
curCircuit.MaxCurrent = 35.0
case 6:
curCircuit.MaxCurrent = 50.0
case 7:
curCircuit.MaxCurrent = 63.0
case 8:
curCircuit.MaxCurrent = 80.0
case 9:
curCircuit.MaxCurrent = 100.0
case 10:
amperage := c.askValue(
question{
label: c.localizedString("Circuit_MaxCurrentCustomInput"),
valueType: templates.TypeNumber,
maxNumberValue: 1000, // 600kW ... enough?
required: true,
})
curCircuit.MaxCurrent, _ = strconv.ParseFloat(amperage, 64)
}
pwrChoices := []string{
c.localizedString("Circuit_MaxPowerDisable"), // no current checking
c.localizedString("Circuit_MaxPower11kW"),
c.localizedString("Circuit_MaxPower20kW"),
c.localizedString("Circuit_MaxPower50kW"),
c.localizedString("Circuit_MaxPower100kW"),
c.localizedString("Circuit_MaxCurrentCustom"),
}
fmt.Println()
pwrIndex, _ := c.askChoice(c.localizedString("Circuit_MaxPower"), pwrChoices)
switch pwrIndex {
case 0:
curCircuit.MaxPower = 0.0
case 1:
curCircuit.MaxPower = 11.0
case 2:
curCircuit.MaxPower = 20.0
case 3:
curCircuit.MaxPower = 50.0
case 4:
curCircuit.MaxPower = 100.0
case 5:
power := c.askValue(
question{
label: c.localizedString("Circuit_MaxPowerCustomInput"),
valueType: templates.TypeNumber,
maxNumberValue: 1000, // 1GkW ... enough?
required: true,
})
curCircuit.MaxPower, _ = strconv.ParseFloat(power, 64)
}

// check meter
if c.askYesNo(c.localizedString("Circuit_Meter")) {
ccMeter, _, err := c.configureDeviceCategory(DeviceCategoryGridMeter)
if err == nil {
curCircuit.MeterRef = ccMeter.Name
}
}

// in case we have already circuits, ask for parent circuit
if len(circuitNames) > 0 {
// circuits exist already, ask for parent
if c.askYesNo(c.localizedString("Circuit_HasParent")) {
sort.Strings(circuitNames)
parentCCNameId, _ := c.askChoice(c.localizedString("Circuit_Parent"), circuitNames)

// assign this circuit as child to the requested parent
curCircuit.ParentRef = circuitNames[parentCCNameId]
}
}
// append to known names for later lookup
circuitNames = append(circuitNames, curCircuit.Name)
c.configuration.config.Circuits = append(c.configuration.config.Circuits, *curCircuit)
fmt.Println()
if !c.askYesNo(c.localizedString("Circuit_AddAnother")) {
break
}
}
}
Loading
Loading