Add HardyBarth charger with Salia controller (#2894)
This commit is contained in:
parent
dedd3ba5c5
commit
1280118473
12 changed files with 550 additions and 62 deletions
32
charger/echarge/ecb1/types.go
Normal file
32
charger/echarge/ecb1/types.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package ecb1
|
||||
|
||||
type Meter struct {
|
||||
ID int
|
||||
Name string
|
||||
Data map[string]float64
|
||||
}
|
||||
|
||||
type ChargeControl struct {
|
||||
ID int
|
||||
Name string
|
||||
State string
|
||||
Mode string
|
||||
ManualModeAmp float64
|
||||
}
|
||||
|
||||
type Rfid struct {
|
||||
ID int
|
||||
Name string
|
||||
Data struct {
|
||||
Tag string
|
||||
}
|
||||
}
|
||||
|
||||
type All struct {
|
||||
ProtocolVersion string `json:"protocol-version"`
|
||||
Network struct{}
|
||||
System struct{}
|
||||
Meters []Meter
|
||||
ChargeControls []ChargeControl
|
||||
Rfid []Rfid
|
||||
}
|
||||
82
charger/echarge/salia/types.go
Normal file
82
charger/echarge/salia/types.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package salia
|
||||
|
||||
const (
|
||||
HeartBeat = "salia/heartbeat"
|
||||
ChargeMode = "salia/chargemode"
|
||||
GridCurrentLimit = "grid_current_limit"
|
||||
)
|
||||
|
||||
type Api struct {
|
||||
Device struct {
|
||||
ModelName string
|
||||
SoftwareVersion string `json:"software_version"`
|
||||
}
|
||||
Secc Secc
|
||||
}
|
||||
|
||||
type Secc struct {
|
||||
Port0 Port
|
||||
}
|
||||
|
||||
type Port struct {
|
||||
Ci struct {
|
||||
Evse struct {
|
||||
Basic struct {
|
||||
OfferedCurrentLimit float64 `json:"offered_current_limit,string"`
|
||||
}
|
||||
}
|
||||
Charge struct {
|
||||
Cp struct {
|
||||
Status string
|
||||
}
|
||||
}
|
||||
}
|
||||
Salia struct {
|
||||
ChargeMode string
|
||||
}
|
||||
Metering struct {
|
||||
Meter struct {
|
||||
Type string
|
||||
Available int `json:",string"`
|
||||
}
|
||||
Power struct {
|
||||
ActiveTotal struct {
|
||||
Actual float64 `json:",string"`
|
||||
} `json:"active_total"`
|
||||
Active struct {
|
||||
AC struct {
|
||||
L1 struct {
|
||||
Actual float64 `json:",string"`
|
||||
}
|
||||
L2 struct {
|
||||
Actual float64 `json:",string"`
|
||||
}
|
||||
L3 struct {
|
||||
Actual float64 `json:",string"`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Energy struct {
|
||||
ActiveImport struct {
|
||||
Actual float64 `json:",string"`
|
||||
} `json:"active_import"`
|
||||
}
|
||||
Current struct {
|
||||
AC struct {
|
||||
L1 struct {
|
||||
Actual float64 `json:",string"`
|
||||
}
|
||||
L2 struct {
|
||||
Actual float64 `json:",string"`
|
||||
}
|
||||
L3 struct {
|
||||
Actual float64 `json:",string"`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EvPresent int `json:"ev_present,string"`
|
||||
Charging int `json:",string"`
|
||||
GridCurrentLimit int `json:"grid_current_limit,string"`
|
||||
}
|
||||
|
|
@ -4,33 +4,3 @@ const (
|
|||
ModeEco = "eco"
|
||||
ModeManual = "manual"
|
||||
)
|
||||
|
||||
type Meter struct {
|
||||
ID int
|
||||
Name string
|
||||
Data map[string]float64
|
||||
}
|
||||
|
||||
type ChargeControl struct {
|
||||
ID int
|
||||
Name string
|
||||
State string
|
||||
Mode string
|
||||
ManualModeAmp float64
|
||||
}
|
||||
|
||||
type Rfid struct {
|
||||
ID int
|
||||
Name string
|
||||
Data struct {
|
||||
Tag string
|
||||
}
|
||||
}
|
||||
|
||||
type All struct {
|
||||
Network struct{}
|
||||
System struct{}
|
||||
Meters []Meter
|
||||
ChargeControls []ChargeControl
|
||||
Rfid []Rfid
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package charger
|
|||
// SOFTWARE.
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
|
@ -25,6 +26,7 @@ import (
|
|||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/charger/echarge"
|
||||
"github.com/evcc-io/evcc/charger/echarge/ecb1"
|
||||
"github.com/evcc-io/evcc/meter/obis"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/evcc-io/evcc/util/request"
|
||||
|
|
@ -44,7 +46,7 @@ type HardyBarth struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
registry.Add("hardybarth", NewHardyBarthFromConfig)
|
||||
registry.Add("hardybarth-ecb1", NewHardyBarthFromConfig)
|
||||
}
|
||||
|
||||
// NewHardyBarthFromConfig creates a HardyBarth cPH1 charger from generic config
|
||||
|
|
@ -67,11 +69,13 @@ func NewHardyBarthFromConfig(other map[string]interface{}) (api.Charger, error)
|
|||
|
||||
// NewHardyBarth creates HardyBarth charger
|
||||
func NewHardyBarth(uri string, chargecontrol, meter int) (api.Charger, error) {
|
||||
log := util.NewLogger("hardy")
|
||||
log := util.NewLogger("ecb1")
|
||||
|
||||
uri = strings.TrimSuffix(uri, "/") + "/api/v1"
|
||||
|
||||
wb := &HardyBarth{
|
||||
Helper: request.NewHelper(log),
|
||||
uri: util.DefaultScheme(strings.TrimSuffix(uri, "/"), "http"),
|
||||
uri: util.DefaultScheme(uri, "http"),
|
||||
chargecontrol: chargecontrol,
|
||||
meter: meter,
|
||||
current: 6,
|
||||
|
|
@ -81,19 +85,19 @@ func NewHardyBarth(uri string, chargecontrol, meter int) (api.Charger, error) {
|
|||
return nil, api.ErrSponsorRequired
|
||||
}
|
||||
|
||||
uri = fmt.Sprintf("%s/api/v1/chargecontrols/%d/mode", wb.uri, wb.chargecontrol)
|
||||
uri = fmt.Sprintf("%s/chargecontrols/%d/mode", wb.uri, wb.chargecontrol)
|
||||
data := url.Values{"mode": {echarge.ModeManual}}
|
||||
err := wb.post(uri, data)
|
||||
|
||||
return wb, err
|
||||
}
|
||||
|
||||
func (wb *HardyBarth) getChargeControl() (echarge.ChargeControl, error) {
|
||||
uri := fmt.Sprintf("%s/api/v1/chargecontrols/%d", wb.uri, wb.chargecontrol)
|
||||
func (wb *HardyBarth) getChargeControl() (ecb1.ChargeControl, error) {
|
||||
uri := fmt.Sprintf("%s/chargecontrols/%d", wb.uri, wb.chargecontrol)
|
||||
|
||||
var res struct {
|
||||
ChargeControl struct {
|
||||
echarge.ChargeControl
|
||||
ecb1.ChargeControl
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +113,10 @@ func (wb *HardyBarth) Status() (api.ChargeStatus, error) {
|
|||
return api.StatusNone, err
|
||||
}
|
||||
|
||||
if res.State == "" {
|
||||
return api.StatusNone, errors.New("invalid state- check controller type (eCB1 vs Salia)")
|
||||
}
|
||||
|
||||
switch s := res.State[:1]; s {
|
||||
case "A", "B", "C":
|
||||
return api.ChargeStatus(s), nil
|
||||
|
|
@ -150,7 +158,7 @@ func (wb *HardyBarth) post(uri string, data url.Values) error {
|
|||
}
|
||||
|
||||
func (wb *HardyBarth) setCurrent(current int64) error {
|
||||
uri := fmt.Sprintf("%s/api/v1/chargecontrols/%d/mode/manual/ampere", wb.uri, wb.chargecontrol)
|
||||
uri := fmt.Sprintf("%s/chargecontrols/%d/mode/manual/ampere", wb.uri, wb.chargecontrol)
|
||||
data := url.Values{"manualmodeamp": {fmt.Sprintf("%d", current)}}
|
||||
return wb.post(uri, data)
|
||||
}
|
||||
|
|
@ -164,12 +172,12 @@ func (wb *HardyBarth) MaxCurrent(current int64) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (wb *HardyBarth) getMeter() (echarge.Meter, error) {
|
||||
uri := fmt.Sprintf("%s/api/v1/meters/%d", wb.uri, wb.meter)
|
||||
func (wb *HardyBarth) getMeter() (ecb1.Meter, error) {
|
||||
uri := fmt.Sprintf("%s/meters/%d", wb.uri, wb.meter)
|
||||
|
||||
var res struct {
|
||||
Meter struct {
|
||||
echarge.Meter
|
||||
ecb1.Meter
|
||||
}
|
||||
}
|
||||
|
||||
238
charger/hardybarth-salia.go
Normal file
238
charger/hardybarth-salia.go
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
package charger
|
||||
|
||||
// LICENSE
|
||||
|
||||
// Copyright (c) 2019-2022 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 (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/charger/echarge"
|
||||
"github.com/evcc-io/evcc/charger/echarge/salia"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/evcc-io/evcc/util/request"
|
||||
)
|
||||
|
||||
// http://apidoc.ecb1.de
|
||||
// https://github.com/evcc-io/evcc/discussions/778
|
||||
|
||||
// Salia charger implementation
|
||||
type Salia struct {
|
||||
*request.Helper
|
||||
log *util.Logger
|
||||
uri string
|
||||
current int64
|
||||
res salia.Api
|
||||
cache time.Duration
|
||||
updated time.Time
|
||||
}
|
||||
|
||||
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.MeterCurrent,Currents,func() (float64, float64, float64, error)"
|
||||
|
||||
// NewSaliaFromConfig creates a Salia cPH1 charger from generic config
|
||||
func NewSaliaFromConfig(other map[string]interface{}) (api.Charger, error) {
|
||||
cc := struct {
|
||||
URI string
|
||||
ChargeControl int
|
||||
Meter int
|
||||
Cache time.Duration
|
||||
}{
|
||||
ChargeControl: 1,
|
||||
Meter: 1,
|
||||
}
|
||||
|
||||
if err := util.DecodeOther(other, &cc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSalia(cc.URI, cc.Cache)
|
||||
}
|
||||
|
||||
// NewSalia creates Hardy Barth charger with Salia controller
|
||||
func NewSalia(uri string, cache time.Duration) (api.Charger, error) {
|
||||
log := util.NewLogger("salia")
|
||||
|
||||
uri = strings.TrimSuffix(uri, "/") + "/api"
|
||||
|
||||
wb := &Salia{
|
||||
log: log,
|
||||
Helper: request.NewHelper(log),
|
||||
uri: util.DefaultScheme(uri, "http"),
|
||||
current: 6,
|
||||
cache: cache,
|
||||
}
|
||||
|
||||
// if !sponsor.IsAuthorized() {
|
||||
// return nil, api.ErrSponsorRequired
|
||||
// }
|
||||
|
||||
err := wb.post(salia.ChargeMode, echarge.ModeManual)
|
||||
if err == nil {
|
||||
go wb.heartbeat()
|
||||
|
||||
res, err := wb.get()
|
||||
if err == nil && res.Secc.Port0.Metering.Meter.Available > 0 {
|
||||
return decorateSalia(wb, wb.currentPower, wb.totalEnergy, wb.currents), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (wb *Salia) heartbeat() {
|
||||
_ = wb.post(salia.HeartBeat, "alive")
|
||||
for range time.NewTicker(30 * time.Second).C {
|
||||
if err := wb.post(salia.HeartBeat, "alive"); err != nil {
|
||||
wb.log.ERROR.Println("heartbeat:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (wb *Salia) get() (salia.Api, error) {
|
||||
if time.Since(wb.updated) < wb.cache {
|
||||
return wb.res, nil
|
||||
}
|
||||
|
||||
err := wb.GetJSON(wb.uri, &wb.res)
|
||||
if err == nil {
|
||||
wb.updated = time.Now()
|
||||
}
|
||||
|
||||
return wb.res, err
|
||||
}
|
||||
|
||||
func (wb *Salia) post(key, val string) error {
|
||||
data := map[string]string{key: val}
|
||||
uri := fmt.Sprintf("%s/secc", wb.uri)
|
||||
|
||||
req, err := request.New(http.MethodPut, uri, request.MarshalJSON(data), request.JSONEncoding)
|
||||
if err == nil {
|
||||
var res struct {
|
||||
Result string
|
||||
}
|
||||
|
||||
if err = wb.DoJSON(req, &res); err == nil {
|
||||
if res.Result != "ok" {
|
||||
err = fmt.Errorf("invalid result: %s", res.Result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Status implements the api.Charger interface
|
||||
func (wb *Salia) Status() (api.ChargeStatus, error) {
|
||||
res, err := wb.get()
|
||||
if err != nil {
|
||||
return api.StatusNone, err
|
||||
}
|
||||
|
||||
switch s := res.Secc.Port0.Ci.Charge.Cp.Status; s {
|
||||
case "A", "B", "C":
|
||||
return api.ChargeStatus(s), nil
|
||||
default:
|
||||
return api.StatusNone, fmt.Errorf("invalid state: %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Enabled implements the api.Charger interface
|
||||
func (wb *Salia) Enabled() (bool, error) {
|
||||
res, err := wb.get()
|
||||
if err == nil && res.Secc.Port0.Salia.ChargeMode != echarge.ModeManual {
|
||||
err = fmt.Errorf("invalid mode: %s", res.Secc.Port0.Salia.ChargeMode)
|
||||
}
|
||||
return res.Secc.Port0.GridCurrentLimit > 0, err
|
||||
}
|
||||
|
||||
// Enable implements the api.Charger interface
|
||||
func (wb *Salia) Enable(enable bool) error {
|
||||
var current int64
|
||||
if enable {
|
||||
current = wb.current
|
||||
}
|
||||
|
||||
err := wb.setCurrent(current)
|
||||
if err == nil {
|
||||
wb.updated = time.Time{}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (wb *Salia) setCurrent(current int64) error {
|
||||
err := wb.post(salia.GridCurrentLimit, strconv.Itoa(int(current)))
|
||||
if err == nil {
|
||||
wb.updated = time.Time{}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// MaxCurrent implements the api.Charger interface
|
||||
func (wb *Salia) MaxCurrent(current int64) error {
|
||||
err := wb.setCurrent(current)
|
||||
if err == nil {
|
||||
wb.current = current
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// currentPower implements the api.Meter interface
|
||||
func (wb *Salia) currentPower() (float64, error) {
|
||||
res, err := wb.get()
|
||||
return res.Secc.Port0.Metering.Power.ActiveTotal.Actual / 10, err
|
||||
}
|
||||
|
||||
// totalEnergy implements the api.MeterEnergy interface
|
||||
func (wb *Salia) totalEnergy() (float64, error) {
|
||||
res, err := wb.get()
|
||||
return res.Secc.Port0.Metering.Energy.ActiveImport.Actual / 1e3, err
|
||||
}
|
||||
|
||||
// currents implements the api.MeterCurrent interface
|
||||
func (wb *Salia) currents() (float64, float64, float64, error) {
|
||||
res, err := wb.get()
|
||||
i := res.Secc.Port0.Metering.Current.AC
|
||||
return i.L1.Actual / 1e3, i.L2.Actual / 1e3, i.L3.Actual / 1e3, err
|
||||
}
|
||||
|
||||
// var _ api.Identifier = (*Salia)(nil)
|
||||
|
||||
// // Identify implements the api.Identifier interface
|
||||
// func (wb *Salia) Identify() (string, error) {
|
||||
// return "", api.ErrNotAvailable
|
||||
// }
|
||||
|
||||
var _ api.Diagnosis = (*Salia)(nil)
|
||||
|
||||
// Diagnose implements the api.Diagnosis interface
|
||||
func (wb *Salia) Diagnose() {
|
||||
res, err := wb.get()
|
||||
if err == nil {
|
||||
fmt.Printf("Model name: %s\n", res.Device.ModelName)
|
||||
fmt.Printf("Software version: %s\n", res.Device.SoftwareVersion)
|
||||
}
|
||||
}
|
||||
137
charger/hardybarth-salia_decorators.go
Normal file
137
charger/hardybarth-salia_decorators.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
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 decorateSalia(base *Salia, meter func() (float64, error), meterEnergy func() (float64, error), meterCurrent func() (float64, float64, float64, error)) api.Charger {
|
||||
switch {
|
||||
case meter == nil && meterCurrent == nil && meterEnergy == nil:
|
||||
return base
|
||||
|
||||
case meter != nil && meterCurrent == nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.Meter
|
||||
}{
|
||||
Salia: base,
|
||||
Meter: &decorateSaliaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
}
|
||||
|
||||
case meter == nil && meterCurrent == nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Salia: base,
|
||||
MeterEnergy: &decorateSaliaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case meter != nil && meterCurrent == nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.Meter
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Salia: base,
|
||||
Meter: &decorateSaliaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterEnergy: &decorateSaliaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case meter == nil && meterCurrent != nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.MeterCurrent
|
||||
}{
|
||||
Salia: base,
|
||||
MeterCurrent: &decorateSaliaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
}
|
||||
|
||||
case meter != nil && meterCurrent != nil && meterEnergy == nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.Meter
|
||||
api.MeterCurrent
|
||||
}{
|
||||
Salia: base,
|
||||
Meter: &decorateSaliaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterCurrent: &decorateSaliaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
}
|
||||
|
||||
case meter == nil && meterCurrent != nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.MeterCurrent
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Salia: base,
|
||||
MeterCurrent: &decorateSaliaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
MeterEnergy: &decorateSaliaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
|
||||
case meter != nil && meterCurrent != nil && meterEnergy != nil:
|
||||
return &struct {
|
||||
*Salia
|
||||
api.Meter
|
||||
api.MeterCurrent
|
||||
api.MeterEnergy
|
||||
}{
|
||||
Salia: base,
|
||||
Meter: &decorateSaliaMeterImpl{
|
||||
meter: meter,
|
||||
},
|
||||
MeterCurrent: &decorateSaliaMeterCurrentImpl{
|
||||
meterCurrent: meterCurrent,
|
||||
},
|
||||
MeterEnergy: &decorateSaliaMeterEnergyImpl{
|
||||
meterEnergy: meterEnergy,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type decorateSaliaMeterImpl struct {
|
||||
meter func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSaliaMeterImpl) CurrentPower() (float64, error) {
|
||||
return impl.meter()
|
||||
}
|
||||
|
||||
type decorateSaliaMeterCurrentImpl struct {
|
||||
meterCurrent func() (float64, float64, float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSaliaMeterCurrentImpl) Currents() (float64, float64, float64, error) {
|
||||
return impl.meterCurrent()
|
||||
}
|
||||
|
||||
type decorateSaliaMeterEnergyImpl struct {
|
||||
meterEnergy func() (float64, error)
|
||||
}
|
||||
|
||||
func (impl *decorateSaliaMeterEnergyImpl) TotalEnergy() (float64, error) {
|
||||
return impl.meterEnergy()
|
||||
}
|
||||
12
templates/definition/charger/hardybarth-ecb1.yaml
Normal file
12
templates/definition/charger/hardybarth-ecb1.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
template: hardybarth-ecb1
|
||||
products:
|
||||
- brand: hardybarth-ecb1
|
||||
description:
|
||||
generic: HardyBarth cPH1 (eCB1 controller)
|
||||
params:
|
||||
- name: host
|
||||
required: true
|
||||
example: 192.0.2.2
|
||||
render: |
|
||||
type: hardybarth-ecb1
|
||||
uri: http://{{ .host }}
|
||||
12
templates/definition/charger/hardybarth-salia.yaml
Normal file
12
templates/definition/charger/hardybarth-salia.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
template: hardybarth-salia
|
||||
products:
|
||||
- brand: hardybarth-salia
|
||||
description:
|
||||
generic: HardyBarth (Salia PLCC controller)
|
||||
params:
|
||||
- name: host
|
||||
required: true
|
||||
example: 192.0.2.2
|
||||
render: |
|
||||
type: hardybarth-salia
|
||||
uri: http://{{ .host }}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
template: hardybarth-cph1
|
||||
products:
|
||||
- brand: hardybarth-cph1
|
||||
description:
|
||||
generic: HardyBarth cPH1
|
||||
params:
|
||||
- name: host
|
||||
required: true
|
||||
example: 192.0.2.2
|
||||
render: |
|
||||
type: hardybarth
|
||||
uri: http://{{ .host }}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
product:
|
||||
brand: hardybarth-cph1
|
||||
description: HardyBarth cPH1
|
||||
|
||||
render:
|
||||
- default: |
|
||||
type: template
|
||||
template: hardybarth-cph1
|
||||
host: 192.0.2.2 # IP-Adresse oder Hostname
|
||||
9
templates/docs/charger/hardybarth-ecb1_0.yaml
Normal file
9
templates/docs/charger/hardybarth-ecb1_0.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
product:
|
||||
brand: hardybarth-ecb1
|
||||
description: HardyBarth cPH1 (eCB1 controller)
|
||||
|
||||
render:
|
||||
- default: |
|
||||
type: template
|
||||
template: hardybarth-ecb1
|
||||
host: 192.0.2.2 # IP-Adresse oder Hostname
|
||||
9
templates/docs/charger/hardybarth-salia_0.yaml
Normal file
9
templates/docs/charger/hardybarth-salia_0.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
product:
|
||||
brand: hardybarth-salia
|
||||
description: HardyBarth (Salia PLCC controller)
|
||||
|
||||
render:
|
||||
- default: |
|
||||
type: template
|
||||
template: hardybarth-salia
|
||||
host: 192.0.2.2 # IP-Adresse oder Hostname
|
||||
Loading…
Add table
Add a link
Reference in a new issue