diff --git a/charger/go-e.go b/charger/go-e.go index 27f14057c..2bd8b6a66 100644 --- a/charger/go-e.go +++ b/charger/go-e.go @@ -41,7 +41,7 @@ func init() { registry.Add("go-e", NewGoEFromConfig) } -// go:generate go run ../cmd/tools/decorate.go -f decorateGoE -b *GoE -r api.Charger -t "api.MeterEnergy,func() (float64, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) (error)" +// go:generate go run ../cmd/tools/decorate.go -f decorateGoE -b *GoE -r api.Charger -t "api.MeterEnergy,func() (float64, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error" // NewGoEFromConfig creates a go-e charger from generic config func NewGoEFromConfig(other map[string]interface{}) (api.Charger, error) { diff --git a/charger/ocpp.go b/charger/ocpp.go index 20b3369e5..9e2e943f6 100644 --- a/charger/ocpp.go +++ b/charger/ocpp.go @@ -96,7 +96,7 @@ func NewOCPPFromConfig(other map[string]interface{}) (api.Charger, error) { return decorateOCPP(c, powerG, totalEnergyG, currentsG, phasesS), nil } -// go:generate go run ../cmd/tools/decorate.go -f decorateOCPP -b *OCPP -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)" +// go:generate go run ../cmd/tools/decorate.go -f decorateOCPP -b *OCPP -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" // NewOCPP creates OCPP charger func NewOCPP(id string, connector int, idtag string, diff --git a/charger/openwb.go b/charger/openwb.go index f7895d72d..49256438d 100644 --- a/charger/openwb.go +++ b/charger/openwb.go @@ -29,7 +29,7 @@ type OpenWB struct { authS func(string) error } -// go:generate go run ../cmd/tools/decorate.go -f decorateOpenWB -b *OpenWB -r api.Charger -t "api.PhaseSwitcher,Phases1p3p,func(int) (error)" -t "api.Battery,Soc,func() (float64, error)" +// go:generate go run ../cmd/tools/decorate.go -f decorateOpenWB -b *OpenWB -r api.Charger -t "api.PhaseSwitcher,Phases1p3p,func(int) error" -t "api.Battery,Soc,func() (float64, error)" // NewOpenWBFromConfig creates a new configurable charger func NewOpenWBFromConfig(other map[string]interface{}) (api.Charger, error) { diff --git a/charger/warp.go b/charger/warp.go deleted file mode 100644 index 954ab3646..000000000 --- a/charger/warp.go +++ /dev/null @@ -1,313 +0,0 @@ -package charger - -import ( - "encoding/json" - "errors" - "fmt" - "time" - - "github.com/evcc-io/evcc/api" - "github.com/evcc-io/evcc/charger/warp" - v1 "github.com/evcc-io/evcc/charger/warp/v1" - "github.com/evcc-io/evcc/provider" - "github.com/evcc-io/evcc/provider/mqtt" - "github.com/evcc-io/evcc/util" -) - -// Warp is the Warp charger implementation -type Warp struct { - log *util.Logger - root string - client *mqtt.Client - enabledG func() (string, error) - statusG func() (string, error) - meterG func() (string, error) - meterDetailsG func() (string, error) - enableS func(bool) error - maxcurrentS func(int64) error - enabled bool // cache -} - -func init() { - registry.Add("warp", NewWarpFromConfig) -} - -//go:generate go run ../cmd/tools/decorate.go -f decorateWarp -b *Warp -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)" - -// NewWarpFromConfig creates a new configurable charger -func NewWarpFromConfig(other map[string]interface{}) (api.Charger, error) { - cc := struct { - mqtt.Config `mapstructure:",squash"` - Topic string - Timeout time.Duration - }{ - Topic: warp.RootTopic, - Timeout: warp.Timeout, - } - - if err := util.DecodeOther(other, &cc); err != nil { - return nil, err - } - - wb, err := NewWarp(cc.Config, cc.Topic, cc.Timeout) - if err != nil { - return nil, err - } - - hasMeter := wb.hasMeter() - - var currentPower, totalEnergy func() (float64, error) - if hasMeter { - currentPower = wb.currentPower - totalEnergy = wb.totalEnergy - } - - var currents func() (float64, float64, float64, error) - if hasMeter && wb.hasCurrents() { - currents = wb.currents - } - - return decorateWarp(wb, currentPower, totalEnergy, currents), err -} - -// NewWarp creates a new configurable charger -func NewWarp(mqttconf mqtt.Config, topic string, timeout time.Duration) (*Warp, error) { - log := util.NewLogger("warp") - - client, err := mqtt.RegisteredClientOrDefault(log, mqttconf) - if err != nil { - return nil, err - } - - wb := &Warp{ - log: log, - root: topic, - client: client, - } - - // timeout handler - to := provider.NewTimeoutHandler(provider.NewMqtt(log, client, - fmt.Sprintf("%s/evse/state", topic), timeout, - ).StringGetter()) - - stringG := func(topic string) func() (string, error) { - g := provider.NewMqtt(log, client, topic, 0).StringGetter() - return to.StringGetter(g) - } - - wb.enabledG = stringG(fmt.Sprintf("%s/evse/auto_start_charging", topic)) - wb.statusG = stringG(fmt.Sprintf("%s/evse/state", topic)) - wb.meterG = stringG(fmt.Sprintf("%s/meter/state", topic)) - wb.meterDetailsG = stringG(fmt.Sprintf("%s/meter/detailed_values", topic)) - - wb.enableS = provider.NewMqtt(log, client, - fmt.Sprintf("%s/evse/auto_start_charging_update", topic), 0). - WithPayload(`{ "auto_start_charging": ${enable} }`). - BoolSetter("enable") - - wb.maxcurrentS = provider.NewMqtt(log, client, - fmt.Sprintf("%s/evse/current_limit", topic), 0). - WithPayload(`{ "current": ${maxcurrent} }`). - IntSetter("maxcurrent") - - return wb, nil -} - -func (wb *Warp) hasMeter() bool { - topic := fmt.Sprintf("%s/meter/state", wb.root) - - if state, err := provider.NewMqtt(wb.log, wb.client, topic, 0).StringGetter()(); err == nil { - var res v1.MeterState - if err := json.Unmarshal([]byte(state), &res); err == nil { - return res.State == 2 || len(res.PhasesConnected) > 0 - } - } - - return false -} - -func (wb *Warp) hasCurrents() bool { - topic := fmt.Sprintf("%s/meter/detailed_values", wb.root) - - if state, err := provider.NewMqtt(wb.log, wb.client, topic, 0).StringGetter()(); err == nil { - var res []float64 - if err := json.Unmarshal([]byte(state), &res); err == nil { - return len(res) > 5 - } - } - - return false -} - -// Enable implements the api.Charger interface -func (wb *Warp) Enable(enable bool) error { - // set auto_start_charging - if err := wb.enableS(enable); err != nil { - return err - } - - // trigger start/stop - action := "stop_charging" - if enable { - action = "start_charging" - } - - topic := fmt.Sprintf("%s/%s/%s", wb.root, "evse", action) - - err := wb.client.Publish(topic, false, "null") - if err == nil { - wb.enabled = enable - } - - return err -} - -func (wb *Warp) status() (v1.EvseState, error) { - var res v1.EvseState - - s, err := wb.statusG() - if err == nil { - err = json.Unmarshal([]byte(s), &res) - } - - return res, err -} - -// autostart reads the enabled state from charger -// use function instead of jq to honor evse/state updates -func (wb *Warp) autostart() (bool, error) { - var res struct { - AutoStartCharging bool `json:"auto_start_charging"` - } - - s, err := wb.enabledG() - if err == nil { - err = json.Unmarshal([]byte(s), &res) - } - - return res.AutoStartCharging, err -} - -// isEnabled reads enabled status from mqtt -func (wb *Warp) isEnabled() (bool, error) { - enabled, err := wb.autostart() - - var status v1.EvseState - if err == nil { - status, err = wb.status() - } - - if enabled { - // check that charge_release is not blocked - enabled = status.ChargeRelease != 2 - } else { - // check that vehicle is really not charging - enabled = status.VehicleState == 2 - } - - return enabled, err -} - -// Enabled implements the api.Charger interface -func (wb *Warp) Enabled() (bool, error) { - enabled, err := wb.isEnabled() - - if err == nil && enabled != wb.enabled { - start := time.Now() - - // retry to avoid out of sync errors in case of slow warp updates - for time.Since(start) <= 2*time.Second { - if enabled, err = wb.isEnabled(); err != nil { - break - } - - if enabled == wb.enabled { - break - } - - time.Sleep(50 * time.Millisecond) - } - } - - return enabled, err -} - -// Status implements the api.Charger interface -func (wb *Warp) Status() (api.ChargeStatus, error) { - var status v1.EvseState - - s, err := wb.statusG() - if err == nil { - err = json.Unmarshal([]byte(s), &status) - } - - res := api.StatusNone - switch status.VehicleState { - case 0: - res = api.StatusA - case 1: - res = api.StatusB - case 2: - res = api.StatusC - default: - if err == nil { - err = fmt.Errorf("invalid status: %d", status.VehicleState) - } - } - - return res, err -} - -// MaxCurrent implements the api.Charger interface -func (wb *Warp) MaxCurrent(current int64) error { - return wb.maxcurrentS(1000 * current) -} - -var _ api.ChargerEx = (*Warp)(nil) - -// MaxCurrentMillis implements the api.ChargerEx interface -func (wb *Warp) MaxCurrentMillis(current float64) error { - return wb.maxcurrentS(int64(1000 * current)) -} - -// CurrentPower implements the api.Meter interface -func (wb *Warp) currentPower() (float64, error) { - var res v1.MeterState - - s, err := wb.meterG() - if err == nil { - err = json.Unmarshal([]byte(s), &res) - } - - return res.Power, err -} - -// TotalEnergy implements the api.MeterEnergy interface -func (wb *Warp) totalEnergy() (float64, error) { - var res v1.MeterState - - s, err := wb.meterG() - if err == nil { - err = json.Unmarshal([]byte(s), &res) - } - - return res.EnergyAbs, err -} - -// currents implements the api.MeterCurrrents interface -func (wb *Warp) currents() (float64, float64, float64, error) { - var res []float64 - - s, err := wb.meterDetailsG() - if err == nil { - if err = json.Unmarshal([]byte(s), &res); err == nil { - if len(res) > 5 { - return res[3], res[4], res[5], nil - } - - err = errors.New("invalid length") - } - } - - return 0, 0, 0, err -} diff --git a/charger/warp/externalcontrol_enumer.go b/charger/warp/externalcontrol_enumer.go new file mode 100644 index 000000000..1a02f0d59 --- /dev/null +++ b/charger/warp/externalcontrol_enumer.go @@ -0,0 +1,86 @@ +// Code generated by "enumer -type ExternalControl -trimprefix ExternalControl -transform whitespace"; DO NOT EDIT. + +package warp + +import ( + "fmt" + "strings" +) + +const _ExternalControlName = "availabledeactivatedruntime conditions not metcurrently switching" + +var _ExternalControlIndex = [...]uint8{0, 9, 20, 46, 65} + +const _ExternalControlLowerName = "availabledeactivatedruntime conditions not metcurrently switching" + +func (i ExternalControl) String() string { + if i < 0 || i >= ExternalControl(len(_ExternalControlIndex)-1) { + return fmt.Sprintf("ExternalControl(%d)", i) + } + return _ExternalControlName[_ExternalControlIndex[i]:_ExternalControlIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _ExternalControlNoOp() { + var x [1]struct{} + _ = x[ExternalControlAvailable-(0)] + _ = x[ExternalControlDeactivated-(1)] + _ = x[ExternalControlRuntimeConditionsNotMet-(2)] + _ = x[ExternalControlCurrentlySwitching-(3)] +} + +var _ExternalControlValues = []ExternalControl{ExternalControlAvailable, ExternalControlDeactivated, ExternalControlRuntimeConditionsNotMet, ExternalControlCurrentlySwitching} + +var _ExternalControlNameToValueMap = map[string]ExternalControl{ + _ExternalControlName[0:9]: ExternalControlAvailable, + _ExternalControlLowerName[0:9]: ExternalControlAvailable, + _ExternalControlName[9:20]: ExternalControlDeactivated, + _ExternalControlLowerName[9:20]: ExternalControlDeactivated, + _ExternalControlName[20:46]: ExternalControlRuntimeConditionsNotMet, + _ExternalControlLowerName[20:46]: ExternalControlRuntimeConditionsNotMet, + _ExternalControlName[46:65]: ExternalControlCurrentlySwitching, + _ExternalControlLowerName[46:65]: ExternalControlCurrentlySwitching, +} + +var _ExternalControlNames = []string{ + _ExternalControlName[0:9], + _ExternalControlName[9:20], + _ExternalControlName[20:46], + _ExternalControlName[46:65], +} + +// ExternalControlString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func ExternalControlString(s string) (ExternalControl, error) { + if val, ok := _ExternalControlNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _ExternalControlNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to ExternalControl values", s) +} + +// ExternalControlValues returns all values of the enum +func ExternalControlValues() []ExternalControl { + return _ExternalControlValues +} + +// ExternalControlStrings returns a slice of all String values of the enum +func ExternalControlStrings() []string { + strs := make([]string, len(_ExternalControlNames)) + copy(strs, _ExternalControlNames) + return strs +} + +// IsAExternalControl returns "true" if the value is listed in the enum definition. "false" otherwise +func (i ExternalControl) IsAExternalControl() bool { + for _, v := range _ExternalControlValues { + if i == v { + return true + } + } + return false +} diff --git a/charger/warp/v2/types.go b/charger/warp/types.go similarity index 75% rename from charger/warp/v2/types.go rename to charger/warp/types.go index 749ed9cb5..6589d74b1 100644 --- a/charger/warp/v2/types.go +++ b/charger/warp/types.go @@ -1,4 +1,4 @@ -package v2 +package warp const ( FeatureMeter = "meter" @@ -80,3 +80,27 @@ type LastNfcTag struct { Type int `json:"tag_type"` ID string `json:"tag_id"` } + +type EmConfig struct { + ContactorInstalled bool `json:"contactor_installed"` + PhaseSwitchingMode int `json:"phase_switching_mode"` +} + +//go:generate enumer -type ExternalControl -trimprefix ExternalControl -transform whitespace +type ExternalControl int + +const ( + ExternalControlAvailable ExternalControl = iota + ExternalControlDeactivated + ExternalControlRuntimeConditionsNotMet + ExternalControlCurrentlySwitching +) + +type EmState struct { + ExternalControl ExternalControl `json:"external_control"` + PhasesSwitched int `json:"phases_switched"` + Input3State bool `json:"input3_state"` + Input4State bool `json:"input4_state"` + RelayState bool `json:"relay_state"` + ErrorFlags int `json:"error_flags"` +} diff --git a/charger/warp/v1/types.go b/charger/warp/v1/types.go deleted file mode 100644 index 9483530a7..000000000 --- a/charger/warp/v1/types.go +++ /dev/null @@ -1,46 +0,0 @@ -package v1 - -import "time" - -const ( - RootTopic = "warp" - Timeout = 30 * time.Second - - FeatureMeter = "meter" - FeatureMeterPhases = "meter_phases" - FeatureNfc = "nfc" -) - -// https://www.warp-charger.com/api.html#evse_state -type EvseState struct { - Iec61851State int `json:"iec61851_state"` - VehicleState int `json:"vehicle_state"` - ChargeRelease int `json:"charge_release"` - ContactorState int `json:"contactor_state"` - ContactorError int `json:"contactor_error"` - AllowedChargingCurrent int64 `json:"allowed_charging_current"` - ErrorState int `json:"error_state"` - LockState int `json:"lock_state"` - TimeSinceStateChange int64 `json:"time_since_state_change"` - Uptime int64 `json:"uptime"` -} - -// https://www.warp-charger.com/api.html#evse_low_level_state -type LowLevelState struct { - LedState int `json:"led_state"` - CpPwmDutyCycle int `json:"cp_pwm_duty_cycle"` - AdcValues []int `json:"adc_values"` - Voltages []int - Resistances []int - Gpio []bool -} - -// https://www.warp-charger.com/api.html#meter_state -type MeterState struct { - State int `json:"state"` // Warp 1 only - Power float64 `json:"power"` - EnergyRel float64 `json:"energy_rel"` - EnergyAbs float64 `json:"energy_abs"` - PhasesActive []bool `json:"phases_active"` - PhasesConnected []bool `json:"phases_connected"` -} diff --git a/charger/warp2.go b/charger/warp2.go index 9f8a11221..3e8e4c601 100644 --- a/charger/warp2.go +++ b/charger/warp2.go @@ -8,7 +8,6 @@ import ( "github.com/evcc-io/evcc/api" "github.com/evcc-io/evcc/charger/warp" - v2 "github.com/evcc-io/evcc/charger/warp/v2" "github.com/evcc-io/evcc/provider" "github.com/evcc-io/evcc/provider/mqtt" "github.com/evcc-io/evcc/util" @@ -18,7 +17,6 @@ import ( // Warp2 is the Warp charger v2 firmware implementation type Warp2 struct { log *util.Logger - root string client *mqtt.Client features []string maxcurrentG func() (string, error) @@ -28,21 +26,26 @@ type Warp2 struct { chargeG func() (string, error) userconfigG func() (string, error) maxcurrentS func(int64) error - current int64 + // emConfigG func() (string, error) + emStateG func() (string, error) + phasesS func(int64) error + current int64 } func init() { - registry.Add("warp-fw2", NewWarp2FromConfig) + registry.Add("warp2", NewWarp2FromConfig) + registry.Add("warp-fw2", NewWarp2FromConfig) // deprecated } -//go:generate go run ../cmd/tools/decorate.go -f decorateWarp2 -b *Warp2 -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.Identifier,Identify,func() (string, error)" +// go:generate go run ../cmd/tools/decorate.go -f decorateWarp2 -b *Warp2 -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.Identifier,Identify,func() (string, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error" // NewWarpFromConfig creates a new configurable charger func NewWarp2FromConfig(other map[string]interface{}) (api.Charger, error) { cc := struct { - mqtt.Config `mapstructure:",squash"` - Topic string - Timeout time.Duration + mqtt.Config `mapstructure:",squash"` + Topic string + EnergyManager string + Timeout time.Duration }{ Topic: warp.RootTopic, Timeout: warp.Timeout, @@ -52,32 +55,39 @@ func NewWarp2FromConfig(other map[string]interface{}) (api.Charger, error) { return nil, err } - wb, err := NewWarp2(cc.Config, cc.Topic, cc.Timeout) + wb, err := NewWarp2(cc.Config, cc.Topic, cc.EnergyManager, cc.Timeout) if err != nil { return nil, err } var currentPower, totalEnergy func() (float64, error) - if wb.hasFeature(v2.FeatureMeter) { + if wb.hasFeature(cc.Topic, warp.FeatureMeter) { currentPower = wb.currentPower totalEnergy = wb.totalEnergy } var currents func() (float64, float64, float64, error) - if wb.hasFeature(v2.FeatureMeterPhases) { + if wb.hasFeature(cc.Topic, warp.FeatureMeterPhases) { currents = wb.currents } var identity func() (string, error) - if wb.hasFeature(v2.FeatureNfc) { + if wb.hasFeature(cc.Topic, warp.FeatureNfc) { identity = wb.identify } - return decorateWarp2(wb, currentPower, totalEnergy, currents, identity), err + var phases func(int) error + if cc.EnergyManager != "" { + if res, err := wb.emState(); err == nil && res.ExternalControl != 1 { + phases = wb.phases1p3p + } + } + + return decorateWarp2(wb, currentPower, totalEnergy, currents, identity, phases), err } // NewWarp2 creates a new configurable charger -func NewWarp2(mqttconf mqtt.Config, topic string, timeout time.Duration) (*Warp2, error) { +func NewWarp2(mqttconf mqtt.Config, topic, emTopic string, timeout time.Duration) (*Warp2, error) { log := util.NewLogger("warp") client, err := mqtt.RegisteredClientOrDefault(log, mqttconf) @@ -87,7 +97,6 @@ func NewWarp2(mqttconf mqtt.Config, topic string, timeout time.Duration) (*Warp2 wb := &Warp2{ log: log, - root: topic, client: client, current: 6000, // mA } @@ -114,15 +123,22 @@ func NewWarp2(mqttconf mqtt.Config, topic string, timeout time.Duration) (*Warp2 WithPayload(`{ "current": ${maxcurrent} }`). IntSetter("maxcurrent") + // wb.emConfigG = stringG(fmt.Sprintf("%s/energy_manager/config", emTopic)) + wb.emStateG = stringG(fmt.Sprintf("%s/energy_manager/state", emTopic)) + wb.phasesS = provider.NewMqtt(log, client, + fmt.Sprintf("%s/energy_manager/external_control_update", emTopic), 0). + WithPayload(`{ "phases_wanted": ${phases} }`). + IntSetter("phases") + return wb, nil } -func (wb *Warp2) hasFeature(feature string) bool { +func (wb *Warp2) hasFeature(root, feature string) bool { if wb.features != nil { return slices.Contains(wb.features, feature) } - topic := fmt.Sprintf("%s/info/features", wb.root) + topic := fmt.Sprintf("%s/info/features", root) if data, err := provider.NewMqtt(wb.log, wb.client, topic, 0).StringGetter()(); err == nil { if err := json.Unmarshal([]byte(data), &wb.features); err == nil { @@ -144,7 +160,7 @@ func (wb *Warp2) Enable(enable bool) error { // Enabled implements the api.Charger interface func (wb *Warp2) Enabled() (bool, error) { - var res v2.EvseExternalCurrent + var res warp.EvseExternalCurrent s, err := wb.maxcurrentG() if err == nil { @@ -156,14 +172,18 @@ func (wb *Warp2) Enabled() (bool, error) { // Status implements the api.Charger interface func (wb *Warp2) Status() (api.ChargeStatus, error) { - var status v2.EvseState + res := api.StatusNone s, err := wb.statusG() - if err == nil { - err = json.Unmarshal([]byte(s), &status) + if err != nil { + return res, err + } + + var status warp.EvseState + if err := json.Unmarshal([]byte(s), &status); err != nil { + return res, err } - res := api.StatusNone switch status.Iec61851State { case 0: res = api.StatusA @@ -172,9 +192,7 @@ func (wb *Warp2) Status() (api.ChargeStatus, error) { case 2: res = api.StatusC default: - if err == nil { - err = fmt.Errorf("invalid status: %d", status.Iec61851State) - } + err = fmt.Errorf("invalid status: %d", status.Iec61851State) } return res, err @@ -203,7 +221,7 @@ func (wb *Warp2) MaxCurrentMillis(current float64) error { // CurrentPower implements the api.Meter interface func (wb *Warp2) currentPower() (float64, error) { - var res v2.MeterValues + var res warp.MeterValues s, err := wb.meterG() if err == nil { @@ -215,7 +233,7 @@ func (wb *Warp2) currentPower() (float64, error) { // TotalEnergy implements the api.MeterEnergy interface func (wb *Warp2) totalEnergy() (float64, error) { - var res v2.MeterValues + var res warp.MeterValues s, err := wb.meterG() if err == nil { @@ -230,21 +248,23 @@ func (wb *Warp2) currents() (float64, float64, float64, error) { var res []float64 s, err := wb.meterDetailsG() - if err == nil { - if err = json.Unmarshal([]byte(s), &res); err == nil { - if len(res) > 5 { - return res[3], res[4], res[5], nil - } - - err = errors.New("invalid length") - } + if err != nil { + return 0, 0, 0, err } - return 0, 0, 0, err + if err := json.Unmarshal([]byte(s), &res); err != nil { + return 0, 0, 0, err + } + + if len(res) <= 5 { + return 0, 0, 0, errors.New("invalid length") + } + + return res[3], res[4], res[5], nil } func (wb *Warp2) identify() (string, error) { - var res v2.ChargeTrackerCurrentCharge + var res warp.ChargeTrackerCurrentCharge s, err := wb.chargeG() if err == nil { @@ -253,3 +273,38 @@ func (wb *Warp2) identify() (string, error) { return res.AuthorizationInfo.TagId, err } + +// func (wb *Warp2) emConfig() (warp.EmConfig, error) { +// var res warp.EmConfig + +// s, err := wb.emConfigG() +// if err == nil { +// err = json.Unmarshal([]byte(s), &res) +// } + +// return res, err +// } + +func (wb *Warp2) emState() (warp.EmState, error) { + var res warp.EmState + + s, err := wb.emStateG() + if err == nil { + err = json.Unmarshal([]byte(s), &res) + } + + return res, err +} + +func (wb *Warp2) phases1p3p(phases int) error { + res, err := wb.emState() + if err != nil { + return err + } + + if res.ExternalControl > 0 { + return fmt.Errorf("external control not available: %s", res.ExternalControl.String()) + } + + return wb.phasesS(int64(phases)) +} diff --git a/charger/warp2_decorators.go b/charger/warp2_decorators.go index 529e2f27a..14feea9bb 100644 --- a/charger/warp2_decorators.go +++ b/charger/warp2_decorators.go @@ -6,12 +6,12 @@ import ( "github.com/evcc-io/evcc/api" ) -func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func() (float64, error), phaseCurrents func() (float64, float64, float64, error), identifier func() (string, error)) api.Charger { +func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func() (float64, error), phaseCurrents func() (float64, float64, float64, error), identifier func() (string, error), phaseSwitcher func(int) error) api.Charger { switch { - case identifier == nil && meter == nil && meterEnergy == nil && phaseCurrents == nil: + case identifier == nil && meter == nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher == nil: return base - case identifier == nil && meter != nil && meterEnergy == nil && phaseCurrents == nil: + case identifier == nil && meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.Meter @@ -22,7 +22,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier == nil && meter == nil && meterEnergy != nil && phaseCurrents == nil: + case identifier == nil && meter == nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.MeterEnergy @@ -33,7 +33,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier == nil && meter != nil && meterEnergy != nil && phaseCurrents == nil: + case identifier == nil && meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.Meter @@ -48,7 +48,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier == nil && meter == nil && meterEnergy == nil && phaseCurrents != nil: + case identifier == nil && meter == nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.PhaseCurrents @@ -59,7 +59,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier == nil && meter != nil && meterEnergy == nil && phaseCurrents != nil: + case identifier == nil && meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.Meter @@ -74,7 +74,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier == nil && meter == nil && meterEnergy != nil && phaseCurrents != nil: + case identifier == nil && meter == nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.MeterEnergy @@ -89,7 +89,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier == nil && meter != nil && meterEnergy != nil && phaseCurrents != nil: + case identifier == nil && meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.Meter @@ -108,7 +108,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter == nil && meterEnergy == nil && phaseCurrents == nil: + case identifier != nil && meter == nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -119,7 +119,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter != nil && meterEnergy == nil && phaseCurrents == nil: + case identifier != nil && meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -134,7 +134,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter == nil && meterEnergy != nil && phaseCurrents == nil: + case identifier != nil && meter == nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -149,7 +149,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter != nil && meterEnergy != nil && phaseCurrents == nil: + case identifier != nil && meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -168,7 +168,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter == nil && meterEnergy == nil && phaseCurrents != nil: + case identifier != nil && meter == nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -183,7 +183,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter != nil && meterEnergy == nil && phaseCurrents != nil: + case identifier != nil && meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -202,7 +202,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter == nil && meterEnergy != nil && phaseCurrents != nil: + case identifier != nil && meter == nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -221,7 +221,7 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( }, } - case identifier != nil && meter != nil && meterEnergy != nil && phaseCurrents != nil: + case identifier != nil && meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher == nil: return &struct { *Warp2 api.Identifier @@ -243,6 +243,310 @@ func decorateWarp2(base *Warp2, meter func() (float64, error), meterEnergy func( phaseCurrents: phaseCurrents, }, } + + case identifier == nil && meter == nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.PhaseSwitcher + }{ + Warp2: base, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Meter + api.PhaseSwitcher + }{ + Warp2: base, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter == nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.MeterEnergy + api.PhaseSwitcher + }{ + Warp2: base, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Meter + api.MeterEnergy + api.PhaseSwitcher + }{ + Warp2: base, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter == nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Meter + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter == nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.MeterEnergy + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier == nil && meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Meter + api.MeterEnergy + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter == nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter != nil && meterEnergy == nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.Meter + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter == nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.MeterEnergy + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter != nil && meterEnergy != nil && phaseCurrents == nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.Meter + api.MeterEnergy + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter == nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter != nil && meterEnergy == nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.Meter + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter == nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.MeterEnergy + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + + case identifier != nil && meter != nil && meterEnergy != nil && phaseCurrents != nil && phaseSwitcher != nil: + return &struct { + *Warp2 + api.Identifier + api.Meter + api.MeterEnergy + api.PhaseCurrents + api.PhaseSwitcher + }{ + Warp2: base, + Identifier: &decorateWarp2IdentifierImpl{ + identifier: identifier, + }, + Meter: &decorateWarp2MeterImpl{ + meter: meter, + }, + MeterEnergy: &decorateWarp2MeterEnergyImpl{ + meterEnergy: meterEnergy, + }, + PhaseCurrents: &decorateWarp2PhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseSwitcher: &decorateWarp2PhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } } return nil @@ -279,3 +583,11 @@ type decorateWarp2PhaseCurrentsImpl struct { func (impl *decorateWarp2PhaseCurrentsImpl) Currents() (float64, float64, float64, error) { return impl.phaseCurrents() } + +type decorateWarp2PhaseSwitcherImpl struct { + phaseSwitcher func(int) error +} + +func (impl *decorateWarp2PhaseSwitcherImpl) Phases1p3p(phases int) error { + return impl.phaseSwitcher(phases) +} diff --git a/charger/warp_decorators.go b/charger/warp_decorators.go deleted file mode 100644 index b05fa6ed5..000000000 --- a/charger/warp_decorators.go +++ /dev/null @@ -1,137 +0,0 @@ -package charger - -// Code generated by github.com/evcc-io/evcc/cmd/tools/decorate.go. DO NOT EDIT. - -import ( - "github.com/evcc-io/evcc/api" -) - -func decorateWarp(base *Warp, meter func() (float64, error), meterEnergy func() (float64, error), phaseCurrents func() (float64, float64, float64, error)) api.Charger { - switch { - case meter == nil && meterEnergy == nil && phaseCurrents == nil: - return base - - case meter != nil && meterEnergy == nil && phaseCurrents == nil: - return &struct { - *Warp - api.Meter - }{ - Warp: base, - Meter: &decorateWarpMeterImpl{ - meter: meter, - }, - } - - case meter == nil && meterEnergy != nil && phaseCurrents == nil: - return &struct { - *Warp - api.MeterEnergy - }{ - Warp: base, - MeterEnergy: &decorateWarpMeterEnergyImpl{ - meterEnergy: meterEnergy, - }, - } - - case meter != nil && meterEnergy != nil && phaseCurrents == nil: - return &struct { - *Warp - api.Meter - api.MeterEnergy - }{ - Warp: base, - Meter: &decorateWarpMeterImpl{ - meter: meter, - }, - MeterEnergy: &decorateWarpMeterEnergyImpl{ - meterEnergy: meterEnergy, - }, - } - - case meter == nil && meterEnergy == nil && phaseCurrents != nil: - return &struct { - *Warp - api.PhaseCurrents - }{ - Warp: base, - PhaseCurrents: &decorateWarpPhaseCurrentsImpl{ - phaseCurrents: phaseCurrents, - }, - } - - case meter != nil && meterEnergy == nil && phaseCurrents != nil: - return &struct { - *Warp - api.Meter - api.PhaseCurrents - }{ - Warp: base, - Meter: &decorateWarpMeterImpl{ - meter: meter, - }, - PhaseCurrents: &decorateWarpPhaseCurrentsImpl{ - phaseCurrents: phaseCurrents, - }, - } - - case meter == nil && meterEnergy != nil && phaseCurrents != nil: - return &struct { - *Warp - api.MeterEnergy - api.PhaseCurrents - }{ - Warp: base, - MeterEnergy: &decorateWarpMeterEnergyImpl{ - meterEnergy: meterEnergy, - }, - PhaseCurrents: &decorateWarpPhaseCurrentsImpl{ - phaseCurrents: phaseCurrents, - }, - } - - case meter != nil && meterEnergy != nil && phaseCurrents != nil: - return &struct { - *Warp - api.Meter - api.MeterEnergy - api.PhaseCurrents - }{ - Warp: base, - Meter: &decorateWarpMeterImpl{ - meter: meter, - }, - MeterEnergy: &decorateWarpMeterEnergyImpl{ - meterEnergy: meterEnergy, - }, - PhaseCurrents: &decorateWarpPhaseCurrentsImpl{ - phaseCurrents: phaseCurrents, - }, - } - } - - return nil -} - -type decorateWarpMeterImpl struct { - meter func() (float64, error) -} - -func (impl *decorateWarpMeterImpl) CurrentPower() (float64, error) { - return impl.meter() -} - -type decorateWarpMeterEnergyImpl struct { - meterEnergy func() (float64, error) -} - -func (impl *decorateWarpMeterEnergyImpl) TotalEnergy() (float64, error) { - return impl.meterEnergy() -} - -type decorateWarpPhaseCurrentsImpl struct { - phaseCurrents func() (float64, float64, float64, error) -} - -func (impl *decorateWarpPhaseCurrentsImpl) Currents() (float64, float64, float64, error) { - return impl.phaseCurrents() -} diff --git a/templates/definition/charger/tinkerforge-warp.yaml b/templates/definition/charger/tinkerforge-warp.yaml index ab28f0e45..1ce0e05e6 100644 --- a/templates/definition/charger/tinkerforge-warp.yaml +++ b/templates/definition/charger/tinkerforge-warp.yaml @@ -11,20 +11,21 @@ products: capabilities: ["mA"] requirements: description: - en: An MQTT broker is required. The charger must be have a configured MQTT connection. - de: Es muss ein MQTT Broker installiert sein. Die MQTT Verbindung muss in der Wallbox eingerichtet sein. + en: Firmware v2 required. + de: Firmware v2 erforderlich. uri: https://docs.evcc.io/docs/devices/chargers#tinkerforge params: - - name: fw2 - required: true - type: bool - help: - de: Firmware v2 installiert - en: Firmware v2 installed - preset: mqtt - name: topic default: warp + - name: energymanager + help: + de: EnergyManager MQTT Topic (falls installiert) + en: EnergyManager MQTT topic if installed render: | - type: {{ if eq .fw2 "true" -}} warp-fw2 {{ else -}} warp {{ end }} + type: warp2 {{ include "mqtt" . }} topic: {{ .topic }} + {{- if .energymanager }} + energymanager: {{ .energymanager }} + {{- end }} diff --git a/templates/docs/charger/tinkerforge-warp_0.yaml b/templates/docs/charger/tinkerforge-warp_0.yaml index 1646a3f70..12fd6b197 100644 --- a/templates/docs/charger/tinkerforge-warp_0.yaml +++ b/templates/docs/charger/tinkerforge-warp_0.yaml @@ -3,22 +3,22 @@ product: description: WARP Charger Smart capabilities: ["mA"] description: | - Es muss ein MQTT Broker installiert sein. Die MQTT Verbindung muss in der Wallbox eingerichtet sein. + Firmware v2 erforderlich. render: - default: | type: template template: tinkerforge-warp - fw2: # Firmware v2 installiert host: 192.0.2.2 # IP Adresse oder der Hostname des MQTT Brokers port: 1883 # MQTT Broker Port (Optional) topic: warp # Topic (ohne / am Anfang) (Optional) + energymanager: # EnergyManager MQTT Topic (falls installiert) (Optional) advanced: | type: template template: tinkerforge-warp - fw2: # Firmware v2 installiert host: 192.0.2.2 # IP Adresse oder der Hostname des MQTT Brokers port: 1883 # MQTT Broker Port (Optional) user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.) (Optional) password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) (Optional) topic: warp # Topic (ohne / am Anfang) (Optional) timeout: 30s # Akzeptiere keine Daten die älter sind als dieser Wert (Optional) + energymanager: # EnergyManager MQTT Topic (falls installiert) (Optional) diff --git a/templates/docs/charger/tinkerforge-warp_1.yaml b/templates/docs/charger/tinkerforge-warp_1.yaml index db481902c..c9835fe00 100644 --- a/templates/docs/charger/tinkerforge-warp_1.yaml +++ b/templates/docs/charger/tinkerforge-warp_1.yaml @@ -3,22 +3,22 @@ product: description: WARP Charger Pro capabilities: ["mA"] description: | - Es muss ein MQTT Broker installiert sein. Die MQTT Verbindung muss in der Wallbox eingerichtet sein. + Firmware v2 erforderlich. render: - default: | type: template template: tinkerforge-warp - fw2: # Firmware v2 installiert host: 192.0.2.2 # IP Adresse oder der Hostname des MQTT Brokers port: 1883 # MQTT Broker Port (Optional) topic: warp # Topic (ohne / am Anfang) (Optional) + energymanager: # EnergyManager MQTT Topic (falls installiert) (Optional) advanced: | type: template template: tinkerforge-warp - fw2: # Firmware v2 installiert host: 192.0.2.2 # IP Adresse oder der Hostname des MQTT Brokers port: 1883 # MQTT Broker Port (Optional) user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.) (Optional) password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) (Optional) topic: warp # Topic (ohne / am Anfang) (Optional) timeout: 30s # Akzeptiere keine Daten die älter sind als dieser Wert (Optional) + energymanager: # EnergyManager MQTT Topic (falls installiert) (Optional)