Zaptec: add mA regulation and improve phase switching (#26573)

This commit is contained in:
Manuel Haag 2026-01-17 15:17:26 +01:00 • committed by GitHub
parent e3febd890a
commit 4d5f374576
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 22 deletions

View file

@ -22,6 +22,7 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"net/http"
"sort"
"time"
@ -44,7 +45,7 @@ type Zaptec struct {
log *util.Logger
statusG util.Cacheable[zaptec.StateResponse]
instance zaptec.Charger
maxCurrent int
maxCurrent float64
version int
enabled bool
priority bool
@ -266,9 +267,16 @@ func (c *Zaptec) sessionPriority(session string, data zaptec.SessionPriority) er
// MaxCurrent implements the api.Charger interface
func (c *Zaptec) MaxCurrent(current int64) error {
curr := int(current)
return c.MaxCurrentMillis(float64(current))
}
var _ api.ChargerEx = (*Zaptec)(nil)
// MaxCurrentMillis implements the api.ChargerEx interface
func (c *Zaptec) MaxCurrentMillis(current float64) error {
current = math.Round(current*10) / 10
data := zaptec.Update{
MaxChargeCurrent: &curr,
MaxChargeCurrent: &current,
}
return c.chargerUpdate(data)
@ -319,21 +327,39 @@ func (c *Zaptec) Currents() (float64, float64, float64, error) {
// phases1p3p implements the api.PhaseSwitcher interface
func (c *Zaptec) phases1p3p(phases int) error {
err := c.switchPhases(phases)
if err != nil || !c.priority {
if err := c.switchPhases(phases); err != nil {
return err
}
// priority configured
data := zaptec.SessionPriority{
PrioritizedPhases: &phases,
}
res, err := c.statusG.Get()
if err != nil {
return err
}
// adjust the current by +/- 0.1A; otherwise, the phase change will not happen
current, err := res.ObservationByID(zaptec.ChargerMaxCurrent).Float64()
if err != nil {
return err
}
current -= 0.1
if current < 6 {
current += 0.2
}
if err := c.MaxCurrentMillis(current); err != nil {
return err
}
if !c.priority {
return nil
}
// priority configured
data := zaptec.SessionPriority{
PrioritizedPhases: &phases,
}
if session := res.ObservationByID(zaptec.SessionIdentifier); session != nil {
return c.sessionPriority(session.ValueAsString, data)
}
@ -346,10 +372,11 @@ func (c *Zaptec) switchPhases(phases int) error {
data := zaptec.Update{
MaxChargePhases: &phases,
}
return c.chargerUpdate(data)
}
var zero int
var zero float64
data := zaptec.UpdateInstallation{
AvailableCurrentPhase1: &c.maxCurrent,
AvailableCurrentPhase2: &zero,
@ -382,7 +409,7 @@ func (c *Zaptec) Identify() (string, error) {
return "", nil
}
func (c *Zaptec) getInstallationMaxCurrent() (int, error) {
func (c *Zaptec) getInstallationMaxCurrent() (float64, error) {
var res zaptec.Installation
uri := fmt.Sprintf("%s/api/installation/%s", zaptec.ApiURL, c.instance.InstallationId)
@ -390,7 +417,7 @@ func (c *Zaptec) getInstallationMaxCurrent() (int, error) {
return 0, err
}
return int(res.MaxCurrent), nil
return res.MaxCurrent, nil
}
func (c *Zaptec) installationUpdate(data zaptec.UpdateInstallation) error {

View file

@ -72,12 +72,12 @@ func (o *Observation) Float64() (float64, error) {
}
type Update struct {
MaxChargeCurrent *int `json:"maxChargeCurrent,omitempty"`
MaxChargePhases *int `json:"maxChargePhases,omitempty"`
MinChargeCurrent *int `json:"minChargeCurrent,omitempty"`
OfflineChargeCurrent *int `json:"offlineChargeCurrent,omitempty"`
OfflineChargePhase *int `json:"offlineChargePhase,omitempty"`
MeterValueInterval *int `json:"meterValueInterval,omitempty"`
MaxChargeCurrent *float64 `json:"maxChargeCurrent,omitempty"`
MaxChargePhases *int `json:"maxChargePhases,omitempty"`
MinChargeCurrent *float64 `json:"minChargeCurrent,omitempty"`
OfflineChargeCurrent *float64 `json:"offlineChargeCurrent,omitempty"`
OfflineChargePhase *int `json:"offlineChargePhase,omitempty"`
MeterValueInterval *int `json:"meterValueInterval,omitempty"`
}
type SessionPriority struct {
@ -90,9 +90,9 @@ type Installation struct {
}
type UpdateInstallation struct {
AvailableCurrentPhase1 *int `json:"availableCurrentPhase1,omitempty"`
AvailableCurrentPhase2 *int `json:"availableCurrentPhase2,omitempty"`
AvailableCurrentPhase3 *int `json:"availableCurrentPhase3,omitempty"`
AvailableCurrentPhase1 *float64 `json:"availableCurrentPhase1,omitempty"`
AvailableCurrentPhase2 *float64 `json:"availableCurrentPhase2,omitempty"`
AvailableCurrentPhase3 *float64 `json:"availableCurrentPhase3,omitempty"`
}
type CapabilitiesResponse struct {