Add SG Ready charger (#17735)
This commit is contained in:
parent
5278f56c08
commit
fc38d155c2
7 changed files with 682 additions and 5 deletions
205
charger/sgready.go
Normal file
205
charger/sgready.go
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
package charger
|
||||
|
||||
// LICENSE
|
||||
|
||||
// Copyright (c) 2024 andig
|
||||
|
||||
// This module is NOT covered by the MIT license. All rights reserved.
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/provider"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
)
|
||||
|
||||
// SgReady charger implementation
|
||||
type SgReady struct {
|
||||
*embed
|
||||
_mode int64
|
||||
phases int
|
||||
get func() (int64, error)
|
||||
set func(int64) error
|
||||
maxPower func(int64) error
|
||||
}
|
||||
|
||||
func init() {
|
||||
registry.AddCtx("sgready", NewSgReadyFromConfig)
|
||||
}
|
||||
|
||||
const (
|
||||
_ int64 = iota
|
||||
Normal
|
||||
Boost
|
||||
Stop
|
||||
)
|
||||
|
||||
//go:generate decorate -f decorateSgReady -b *SgReady -r api.Charger -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.Battery,Soc,func() (float64, error)" -t "api.SocLimiter,GetLimitSoc,func() (int64, error)"
|
||||
|
||||
// NewSgReadyFromConfig creates an SG Ready configurable charger from generic config
|
||||
func NewSgReadyFromConfig(ctx context.Context, other map[string]interface{}) (api.Charger, error) {
|
||||
cc := struct {
|
||||
embed `mapstructure:",squash"`
|
||||
SetMode provider.Config
|
||||
GetMode *provider.Config // optional
|
||||
MaxPower *provider.Config // optional
|
||||
Power *provider.Config // optional
|
||||
Energy *provider.Config // optional
|
||||
Temp *provider.Config // optional
|
||||
LimitTemp *provider.Config // optional
|
||||
Phases int
|
||||
}{
|
||||
embed: embed{
|
||||
Icon_: "heatpump",
|
||||
Features_: []api.Feature{api.Heating, api.IntegratedDevice},
|
||||
},
|
||||
Phases: 1,
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
set, err := provider.NewIntSetterFromConfig(ctx, "mode", cc.SetMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var get func() (int64, error)
|
||||
if cc.GetMode != nil {
|
||||
get, err = provider.NewIntGetterFromConfig(ctx, *cc.GetMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var maxPower func(int64) error
|
||||
if cc.MaxPower != nil {
|
||||
maxPower, err = provider.NewIntSetterFromConfig(ctx, "maxpower", *cc.MaxPower)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
res, err := NewSgReady(ctx, &cc.embed, set, get, maxPower, cc.Phases)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// decorate power
|
||||
var powerG func() (float64, error)
|
||||
if cc.Power != nil {
|
||||
powerG, err = provider.NewFloatGetterFromConfig(ctx, *cc.Power)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("power: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// decorate energy
|
||||
var energyG func() (float64, error)
|
||||
if cc.Energy != nil {
|
||||
energyG, err = provider.NewFloatGetterFromConfig(ctx, *cc.Energy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("energy: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// decorate temp
|
||||
var tempG func() (float64, error)
|
||||
if cc.Temp != nil {
|
||||
tempG, err = provider.NewFloatGetterFromConfig(ctx, *cc.Temp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("temp: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var limitTempG func() (int64, error)
|
||||
if cc.LimitTemp != nil {
|
||||
limitTempG, err = provider.NewIntGetterFromConfig(ctx, *cc.LimitTemp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("limit temp: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return decorateSgReady(res, powerG, energyG, tempG, limitTempG), nil
|
||||
}
|
||||
|
||||
// NewSgReady creates SG Ready charger
|
||||
func NewSgReady(ctx context.Context, embed *embed, set func(int64) error, get func() (int64, error), maxPower func(int64) error, phases int) (*SgReady, error) {
|
||||
res := &SgReady{
|
||||
embed: embed,
|
||||
_mode: Normal,
|
||||
set: set,
|
||||
get: get,
|
||||
maxPower: maxPower,
|
||||
phases: phases,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (wb *SgReady) mode() (int64, error) {
|
||||
if wb.get == nil {
|
||||
return wb._mode, nil
|
||||
}
|
||||
return wb.get()
|
||||
}
|
||||
|
||||
// Status implements the api.Charger interface
|
||||
func (wb *SgReady) Status() (api.ChargeStatus, error) {
|
||||
mode, err := wb.mode()
|
||||
if err != nil {
|
||||
return api.StatusNone, err
|
||||
}
|
||||
|
||||
if mode == Stop {
|
||||
return api.StatusE, errors.New("stop mode")
|
||||
}
|
||||
|
||||
status := map[int64]api.ChargeStatus{Boost: api.StatusC, Normal: api.StatusB}[mode]
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// Enabled implements the api.Charger interface
|
||||
func (wb *SgReady) Enabled() (bool, error) {
|
||||
mode, err := wb.mode()
|
||||
return mode == Boost, err
|
||||
}
|
||||
|
||||
// Enable implements the api.Charger interface
|
||||
func (wb *SgReady) Enable(enable bool) error {
|
||||
mode := map[bool]int64{false: Normal, true: Boost}[enable]
|
||||
err := wb.set(mode)
|
||||
if err == nil {
|
||||
wb._mode = mode
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// MaxCurrent implements the api.Charger interface
|
||||
func (wb *SgReady) MaxCurrent(current int64) error {
|
||||
return wb.MaxCurrentEx(float64(current))
|
||||
}
|
||||
|
||||
// MaxCurrent implements the api.Charger interface
|
||||
func (wb *SgReady) MaxCurrentEx(current float64) error {
|
||||
if wb.maxPower == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return wb.maxPower(int64(230 * current * float64(wb.phases)))
|
||||
}
|
||||
221
charger/sgready_decorators.go
Normal file
221
charger/sgready_decorators.go
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
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 decorateSgReady(base *SgReady, meter func() (float64, error), meterEnergy func() (float64, error), battery func() (float64, error), socLimiter func() (int64, error)) api.Charger {
|
||||
switch {
|
||||
case battery == nil && meter == nil && socLimiter == nil:
|
||||
return base
|
||||
|
||||
case battery == nil && meter != nil && meterEnergy == nil && socLimiter == nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Meter
|
||||
}{
|
||||
SgReady: base,
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery == nil && meter != nil && meterEnergy != nil && socLimiter == nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}{
|
||||
SgReady: base,
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateSgReadyMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case battery != nil && meter == nil && socLimiter == nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Battery
|
||||
}{
|
||||
SgReady: base,
|
||||
Battery: &decorateSgReadyBatteryImpl{
|
||||
battery: battery,
|
||||
},
|
||||
}
|
||||
|
||||
case battery != nil && meter != nil && meterEnergy == nil && socLimiter == nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Battery
|
||||
api.Meter
|
||||
}{
|
||||
SgReady: base,
|
||||
Battery: &decorateSgReadyBatteryImpl{
|
||||
battery: battery,
|
||||
},
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery != nil && meter != nil && meterEnergy != nil && socLimiter == nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Battery
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}{
|
||||
SgReady: base,
|
||||
Battery: &decorateSgReadyBatteryImpl{
|
||||
battery: battery,
|
||||
},
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateSgReadyMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case battery == nil && meter == nil && socLimiter != nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.SocLimiter
|
||||
}{
|
||||
SgReady: base,
|
||||
SocLimiter: &decorateSgReadySocLimiterImpl{
|
||||
socLimiter: socLimiter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery == nil && meter != nil && meterEnergy == nil && socLimiter != nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Meter
|
||||
api.SocLimiter
|
||||
}{
|
||||
SgReady: base,
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
SocLimiter: &decorateSgReadySocLimiterImpl{
|
||||
socLimiter: socLimiter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery == nil && meter != nil && meterEnergy != nil && socLimiter != nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
api.SocLimiter
|
||||
}{
|
||||
SgReady: base,
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateSgReadyMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
SocLimiter: &decorateSgReadySocLimiterImpl{
|
||||
socLimiter: socLimiter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery != nil && meter == nil && socLimiter != nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Battery
|
||||
api.SocLimiter
|
||||
}{
|
||||
SgReady: base,
|
||||
Battery: &decorateSgReadyBatteryImpl{
|
||||
battery: battery,
|
||||
},
|
||||
SocLimiter: &decorateSgReadySocLimiterImpl{
|
||||
socLimiter: socLimiter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery != nil && meter != nil && meterEnergy == nil && socLimiter != nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Battery
|
||||
api.Meter
|
||||
api.SocLimiter
|
||||
}{
|
||||
SgReady: base,
|
||||
Battery: &decorateSgReadyBatteryImpl{
|
||||
battery: battery,
|
||||
},
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
SocLimiter: &decorateSgReadySocLimiterImpl{
|
||||
socLimiter: socLimiter,
|
||||
},
|
||||
}
|
||||
|
||||
case battery != nil && meter != nil && meterEnergy != nil && socLimiter != nil:
|
||||
return &struct {
|
||||
*SgReady
|
||||
api.Battery
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
api.SocLimiter
|
||||
}{
|
||||
SgReady: base,
|
||||
Battery: &decorateSgReadyBatteryImpl{
|
||||
battery: battery,
|
||||
},
|
||||
Meter: &decorateSgReadyMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateSgReadyMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
SocLimiter: &decorateSgReadySocLimiterImpl{
|
||||
socLimiter: socLimiter,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type decorateSgReadyBatteryImpl struct {
|
||||
battery func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSgReadyBatteryImpl) Soc() (float64, error) {
|
||||
return impl.battery()
|
||||
}
|
||||
|
||||
type decorateSgReadyMeterImpl struct {
|
||||
meter func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSgReadyMeterImpl) CurrentPower() (float64, error) {
|
||||
return impl.meter()
|
||||
}
|
||||
|
||||
type decorateSgReadyMeterEnergyImpl struct {
|
||||
meterEnergy func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSgReadyMeterEnergyImpl) TotalEnergy() (float64, error) {
|
||||
return impl.meterEnergy()
|
||||
}
|
||||
|
||||
type decorateSgReadySocLimiterImpl struct {
|
||||
socLimiter func() (int64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSgReadySocLimiterImpl) GetLimitSoc() (int64, error) {
|
||||
return impl.socLimiter()
|
||||
}
|
||||
|
|
@ -8,9 +8,9 @@ import (
|
|||
)
|
||||
|
||||
type mapProvider struct {
|
||||
ctx context.Context
|
||||
values map[int64]int64
|
||||
set Config
|
||||
ctx context.Context
|
||||
values map[int64]int64
|
||||
get, set Config
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
@ -20,8 +20,8 @@ func init() {
|
|||
// NewMapFromConfig creates type conversion provider
|
||||
func NewMapFromConfig(ctx context.Context, other map[string]interface{}) (Provider, error) {
|
||||
var cc struct {
|
||||
Values map[int64]int64
|
||||
Set Config
|
||||
Values map[int64]int64
|
||||
Get, Set Config
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
|
|
@ -34,6 +34,7 @@ func NewMapFromConfig(ctx context.Context, other map[string]interface{}) (Provid
|
|||
|
||||
o := &mapProvider{
|
||||
ctx: ctx,
|
||||
get: cc.Get,
|
||||
set: cc.Set,
|
||||
values: cc.Values,
|
||||
}
|
||||
|
|
@ -41,6 +42,26 @@ func NewMapFromConfig(ctx context.Context, other map[string]interface{}) (Provid
|
|||
return o, nil
|
||||
}
|
||||
|
||||
var _ IntProvider = (*mapProvider)(nil)
|
||||
|
||||
func (o *mapProvider) IntGetter() (func() (int64, error), error) {
|
||||
get, err := NewIntGetterFromConfig(o.ctx, o.get)
|
||||
|
||||
return func() (int64, error) {
|
||||
val, err := get()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
res, ok := o.values[val]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("map: value not found: %d", val)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}, err
|
||||
}
|
||||
|
||||
var _ SetIntProvider = (*mapProvider)(nil)
|
||||
|
||||
func (o *mapProvider) IntSetter(param string) (func(int64) error, error) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ products:
|
|||
- brand: my-PV
|
||||
description:
|
||||
generic: AC ELWA 2
|
||||
group: heating
|
||||
requirements:
|
||||
evcc: ["sponsorship"]
|
||||
params:
|
||||
|
|
|
|||
114
templates/definition/charger/stiebel-lwa.yaml
Normal file
114
templates/definition/charger/stiebel-lwa.yaml
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
template: stiebel-lwa
|
||||
products:
|
||||
- brand: Stiebel Eltron
|
||||
description:
|
||||
generic: LWA/LWZ (SG Ready)
|
||||
- brand: Tecalor
|
||||
description:
|
||||
generic: THZ (SG Ready)
|
||||
group: heating
|
||||
# requirements:
|
||||
# evcc: ["sponsorship"]
|
||||
params:
|
||||
- name: modbus
|
||||
choice: ["tcpip"]
|
||||
- name: tempsource
|
||||
validvalues: ["", "warmwater"]
|
||||
description:
|
||||
de: "Temperaturquelle"
|
||||
en: "Temperature source"
|
||||
render: |
|
||||
type: sgready
|
||||
getmode:
|
||||
source: map
|
||||
values:
|
||||
1: 3 # Frostschutz
|
||||
2: 1 # Normal
|
||||
3: 2 # Forcierter Betrieb
|
||||
4: 2 # Sofortige Ansteuerung
|
||||
get:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 4 }}
|
||||
register:
|
||||
address: 5000
|
||||
type: input
|
||||
encoding: uint16
|
||||
setmode:
|
||||
source: switch
|
||||
switch:
|
||||
- case: 1 # normal
|
||||
set:
|
||||
source: sequence
|
||||
set:
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4001
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4002
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- case: 2 # boost
|
||||
set:
|
||||
source: sequence
|
||||
set:
|
||||
- source: const
|
||||
value: 1
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4001
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4002
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- case: 3 # dimm
|
||||
set:
|
||||
source: sequence
|
||||
set:
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4001
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- source: const
|
||||
value: 1
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4002
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
{{- if .tempsource }}
|
||||
temp:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 2 }}
|
||||
register:
|
||||
address: 15
|
||||
type: input
|
||||
encoding: int16
|
||||
scale: 0.1
|
||||
{{- end }}
|
||||
111
templates/definition/charger/stiebel-wpm.yaml
Normal file
111
templates/definition/charger/stiebel-wpm.yaml
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
template: stiebel-wpm
|
||||
products:
|
||||
- brand: Stiebel Eltron
|
||||
description:
|
||||
generic: WPM (SG Ready)
|
||||
group: heating
|
||||
# requirements:
|
||||
# evcc: ["sponsorship"]
|
||||
params:
|
||||
- name: modbus
|
||||
choice: ["tcpip"]
|
||||
- name: tempsource
|
||||
validvalues: ["", "warmwater", "buffer"]
|
||||
description:
|
||||
de: "Temperaturquelle"
|
||||
en: "Temperature source"
|
||||
render: |
|
||||
type: sgready
|
||||
getmode:
|
||||
source: map
|
||||
values:
|
||||
1: 3 # Frostschutz
|
||||
2: 1 # Normal
|
||||
3: 2 # Forcierter Betrieb
|
||||
4: 2 # Sofortige Ansteuerung
|
||||
get:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 4 }}
|
||||
register:
|
||||
address: 5000
|
||||
type: input
|
||||
encoding: uint16
|
||||
setmode:
|
||||
source: switch
|
||||
switch:
|
||||
- case: 1 # normal
|
||||
set:
|
||||
source: sequence
|
||||
set:
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4001
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4002
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- case: 2 # boost
|
||||
set:
|
||||
source: sequence
|
||||
set:
|
||||
- source: const
|
||||
value: 1
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4001
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4002
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- case: 3 # dimm
|
||||
set:
|
||||
source: sequence
|
||||
set:
|
||||
- source: const
|
||||
value: 0
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4001
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
- source: const
|
||||
value: 1
|
||||
set:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 10 }}
|
||||
register:
|
||||
address: 4002
|
||||
type: writesingle
|
||||
encoding: uint16
|
||||
{{- if .tempsource }}
|
||||
temp:
|
||||
source: modbus
|
||||
{{- include "modbus" . | indent 2 }}
|
||||
register:
|
||||
address: {{ if eq .tempsource "warmwater" -}} 521 {{ else }} 517 {{- end }}
|
||||
type: input
|
||||
encoding: int16
|
||||
scale: 0.1
|
||||
{{- end }}
|
||||
|
|
@ -321,6 +321,7 @@ params:
|
|||
en: Power limit for grid charging.
|
||||
de: Leistungslimit für Netzladung.
|
||||
default: 100
|
||||
|
||||
presets:
|
||||
vehicle-base:
|
||||
params:
|
||||
|
|
@ -575,6 +576,9 @@ devicegroups:
|
|||
generic:
|
||||
de: Generische Unterstützung
|
||||
en: Generic support
|
||||
heating:
|
||||
de: Wärmeerzeuger
|
||||
en: Heating devices
|
||||
switchsockets:
|
||||
de: Schaltbare Steckdosen
|
||||
en: Switchable sockets
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue