Hardybarth Salia: add phase switching (#16683)

This commit is contained in:
andig 2024-10-16 23:06:54 +02:00 • committed by GitHub
parent 730ad8f3af
commit 96e6c97256
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 275 additions and 18 deletions

View file

@ -4,6 +4,7 @@ const (
HeartBeat = "salia/heartbeat"
ChargeMode = "salia/chargemode"
PauseCharging = "salia/pausecharging"
SetPhase = "salia/phase_switching/setphase"
GridCurrentLimit = "grid_current_limit"
)
@ -33,8 +34,13 @@ type Port struct {
}
}
Salia struct {
ChargeMode string
PauseCharging int `json:"pausecharging,string"`
ChargeMode string
PauseCharging int `json:"pausecharging,string"`
PhaseSwitching struct {
Actual int `json:",string"`
Status string
SetPhase string `json:"setphase,omitempty"`
} `json:"phase_switching"`
}
Metering struct {
Meter struct {

View file

@ -52,7 +52,7 @@ func init() {
registry.Add("hardybarth-salia", NewSaliaFromConfig)
}
//go:generate go run ../cmd/tools/decorate.go -f decorateSalia -b *Salia -r api.Charger -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseCurrents,Currents,func() (float64, float64, float64, error)"
//go:generate go run ../cmd/tools/decorate.go -f decorateSalia -b *Salia -r api.Charger -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.PhaseSwitcher,Phases1p3p,func(int) error" -t "api.PhaseGetter,GetPhases,func() (int, error)"
// NewSaliaFromConfig creates a Salia cPH2 charger from generic config
func NewSaliaFromConfig(other map[string]interface{}) (api.Charger, error) {
@ -118,17 +118,34 @@ func NewSalia(uri string, cache time.Duration) (api.Charger, error) {
}
}
if err == nil {
go wb.heartbeat()
wb.pause(false)
if res.Secc.Port0.Metering.Meter.Available > 0 {
return decorateSalia(wb, wb.currentPower, wb.totalEnergy, wb.currents), nil
}
if err != nil {
return nil, err
}
return wb, err
go wb.heartbeat()
wb.pause(false)
var (
currentPower func() (float64, error)
totalEnergy func() (float64, error)
currents func() (float64, float64, float64, error)
phasesG func() (int, error)
phasesS func(int) error
)
if res.Secc.Port0.Metering.Meter.Available > 0 {
currentPower = wb.currentPower
totalEnergy = wb.totalEnergy
currents = wb.currents
}
if res.Secc.Port0.Salia.PhaseSwitching.Actual > 0 {
phasesG = wb.getPhases
phasesS = wb.phases1p3p
}
return decorateSalia(wb, currentPower, totalEnergy, currents, phasesS, phasesG), nil
}
func (wb *Salia) heartbeat() {
@ -250,6 +267,30 @@ func (wb *Salia) currents() (float64, float64, float64, error) {
// return "", api.ErrNotAvailable
// }
func (wb *Salia) getPhases() (int, error) {
res, err := wb.apiG.Get()
if err != nil {
return 0, err
}
if res.Secc.Port0.Salia.PhaseSwitching.Actual == 0 {
return 0, api.ErrNotAvailable
}
return res.Secc.Port0.Salia.PhaseSwitching.Actual, nil
}
func (wb *Salia) phases1p3p(phases int) error {
p, err := wb.getPhases()
if err != nil {
return err
}
if p == phases {
return nil
}
return wb.post(salia.SetPhase, "toggle")
}
var _ api.Diagnosis = (*Salia)(nil)
// Diagnose implements the api.Diagnosis interface

View file

@ -6,12 +6,12 @@ import (
"github.com/evcc-io/evcc/api"
)
func decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func() (float64, error), phaseCurrents func() (float64, float64, float64, error)) api.Charger {
func decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func() (float64, error), phaseCurrents func() (float64, float64, float64, error), phaseSwitcher func(int) error, phaseGetter func() (int, error)) api.Charger {
switch {
case meter == nil:
case meter == nil && phaseSwitcher == nil:
return base
case meter != nil && meterEnergy == nil && phaseCurrents == nil:
case meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher == nil:
return &struct {
*Salia
api.Meter
@ -22,7 +22,7 @@ func decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func(
},
}
case meter != nil && meterEnergy != nil && phaseCurrents == nil:
case meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher == nil:
return &struct {
*Salia
api.Meter
@ -37,7 +37,7 @@ func decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func(
},
}
case meter != nil && meterEnergy == nil && phaseCurrents != nil:
case meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher == nil:
return &struct {
*Salia
api.Meter
@ -52,7 +52,7 @@ func decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func(
},
}
case meter != nil && meterEnergy != nil && phaseCurrents != nil:
case meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher == nil:
return &struct {
*Salia
api.Meter
@ -70,6 +70,200 @@ func decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func(
phaseCurrents: phaseCurrents,
},
}
case meter == nil && phaseGetter == nil && phaseSwitcher != nil:
return &struct {
*Salia
api.PhaseSwitcher
}{
Salia: base,
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseGetter == nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseGetter == nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.MeterEnergy
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
MeterEnergy: &decorateSaliaMeterEnergyImpl{
meterEnergy: meterEnergy,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseGetter == nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.PhaseCurrents
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
PhaseCurrents: &decorateSaliaPhaseCurrentsImpl{
phaseCurrents: phaseCurrents,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseGetter == nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.MeterEnergy
api.PhaseCurrents
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
MeterEnergy: &decorateSaliaMeterEnergyImpl{
meterEnergy: meterEnergy,
},
PhaseCurrents: &decorateSaliaPhaseCurrentsImpl{
phaseCurrents: phaseCurrents,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter == nil && phaseGetter != nil && phaseSwitcher != nil:
return &struct {
*Salia
api.PhaseGetter
api.PhaseSwitcher
}{
Salia: base,
PhaseGetter: &decorateSaliaPhaseGetterImpl{
phaseGetter: phaseGetter,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseGetter != nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.PhaseGetter
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
PhaseGetter: &decorateSaliaPhaseGetterImpl{
phaseGetter: phaseGetter,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseGetter != nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.MeterEnergy
api.PhaseGetter
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
MeterEnergy: &decorateSaliaMeterEnergyImpl{
meterEnergy: meterEnergy,
},
PhaseGetter: &decorateSaliaPhaseGetterImpl{
phaseGetter: phaseGetter,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseGetter != nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.PhaseCurrents
api.PhaseGetter
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
PhaseCurrents: &decorateSaliaPhaseCurrentsImpl{
phaseCurrents: phaseCurrents,
},
PhaseGetter: &decorateSaliaPhaseGetterImpl{
phaseGetter: phaseGetter,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
case meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseGetter != nil && phaseSwitcher != nil:
return &struct {
*Salia
api.Meter
api.MeterEnergy
api.PhaseCurrents
api.PhaseGetter
api.PhaseSwitcher
}{
Salia: base,
Meter: &decorateSaliaMeterImpl{
meter: meter,
},
MeterEnergy: &decorateSaliaMeterEnergyImpl{
meterEnergy: meterEnergy,
},
PhaseCurrents: &decorateSaliaPhaseCurrentsImpl{
phaseCurrents: phaseCurrents,
},
PhaseGetter: &decorateSaliaPhaseGetterImpl{
phaseGetter: phaseGetter,
},
PhaseSwitcher: &decorateSaliaPhaseSwitcherImpl{
phaseSwitcher: phaseSwitcher,
},
}
}
return nil
@ -98,3 +292,19 @@ type decorateSaliaPhaseCurrentsImpl struct {
func (impl *decorateSaliaPhaseCurrentsImpl) Currents() (float64, float64, float64, error) {
return impl.phaseCurrents()
}
type decorateSaliaPhaseGetterImpl struct {
phaseGetter func() (int, error)
}
func (impl *decorateSaliaPhaseGetterImpl) GetPhases() (int, error) {
return impl.phaseGetter()
}
type decorateSaliaPhaseSwitcherImpl struct {
phaseSwitcher func(int) error
}
func (impl *decorateSaliaPhaseSwitcherImpl) Phases1p3p(p0 int) error {
return impl.phaseSwitcher(p0)
}