More template stuff (#2164)
Some checks failed
Default / Build (push) Failing after 2m0s
Default / Build UI (push) Failing after 13s
Release / Publish Docker :release (push) Has been cancelled
Release / call-build-workflow (push) Has been cancelled
Release / Publish Github & APT release (push) Has been cancelled
Some checks failed
Default / Build (push) Failing after 2m0s
Default / Build UI (push) Failing after 13s
Release / Publish Docker :release (push) Has been cancelled
Release / call-build-workflow (push) Has been cancelled
Release / Publish Github & APT release (push) Has been cancelled
- Configure now asks for the users knowledge level, so advanced mode can be reached without calling with `--advanced` - Add template for solaredge inverter - Add beta template for sungrow inverter - Add template for MQTT based meter - Add more template documentation - Add check and error message for invalid config properties when using templates - Option to specify language specific template descriptions - Option to make params dependent on values of other params - Option to add sponsortoken in advanced mode - Option to set minCurrent in advanced mode - Remove sponsorship requirement from Daheimladen wallbox - Multiple fixes (FritzDect meter, Kostsal Piko meter, ...)
This commit is contained in:
parent
8ba710ff5f
commit
cfb174f9f5
144 changed files with 935 additions and 265 deletions
|
|
@ -26,7 +26,7 @@ func NewChargerFromTemplateConfig(other map[string]interface{}) (api.Charger, er
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b, _, err := tmpl.RenderResult(false, other)
|
b, _, err := tmpl.RenderResult(templates.TemplateRenderModeInstance, other)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func TestChargerTemplates(t *testing.T) {
|
||||||
tmpl := tmpl
|
tmpl := tmpl
|
||||||
|
|
||||||
// set default values for all params
|
// set default values for all params
|
||||||
values := tmpl.Defaults(true)
|
values := tmpl.Defaults(templates.TemplateRenderModeUnitTest)
|
||||||
|
|
||||||
// set the template value which is needed for rendering
|
// set the template value which is needed for rendering
|
||||||
values["template"] = tmpl.Template
|
values["template"] = tmpl.Template
|
||||||
|
|
@ -43,6 +43,7 @@ func TestChargerTemplates(t *testing.T) {
|
||||||
// set modbus default test values
|
// set modbus default test values
|
||||||
if values[templates.ParamModbus] != nil {
|
if values[templates.ParamModbus] != nil {
|
||||||
modbusChoices := tmpl.ModbusChoices()
|
modbusChoices := tmpl.ModbusChoices()
|
||||||
|
// we only test one modbus setup
|
||||||
if funk.ContainsString(modbusChoices, templates.ModbusChoiceTCPIP) {
|
if funk.ContainsString(modbusChoices, templates.ModbusChoiceTCPIP) {
|
||||||
values[templates.ModbusTCPIP] = true
|
values[templates.ModbusTCPIP] = true
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -53,15 +54,17 @@ func TestChargerTemplates(t *testing.T) {
|
||||||
t.Run(tmpl.Template, func(t *testing.T) {
|
t.Run(tmpl.Template, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
b, values, err := tmpl.RenderResult(true, values)
|
b, values, err := tmpl.RenderResult(templates.TemplateRenderModeUnitTest, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("%s: %s", tmpl.Template, b)
|
t.Logf("Template: %s", tmpl.Template)
|
||||||
|
t.Logf("%s", string(b))
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = NewFromConfig("template", values)
|
_, err = NewFromConfig("template", values)
|
||||||
if err != nil && !test.Acceptable(err, acceptable) {
|
if err != nil && !test.Acceptable(err, acceptable) {
|
||||||
t.Logf("%s", tmpl.Template)
|
t.Logf("Template: %s", tmpl.Template)
|
||||||
|
t.Logf("%s", string(b))
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ type config struct {
|
||||||
}
|
}
|
||||||
Hems string
|
Hems string
|
||||||
EEBUS string
|
EEBUS string
|
||||||
|
MQTT string
|
||||||
SponsorToken string
|
SponsorToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func (d *DeviceTest) Test() (DeviceTestResult, error) {
|
||||||
|
|
||||||
// configure creates a configured device from a template so we can test it
|
// configure creates a configured device from a template so we can test it
|
||||||
func (d *DeviceTest) configure() (interface{}, error) {
|
func (d *DeviceTest) configure() (interface{}, error) {
|
||||||
b, _, err := d.Template.RenderResult(false, d.ConfigValues)
|
b, _, err := d.Template.RenderResult(templates.TemplateRenderModeInstance, d.ConfigValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ func (c *CmdConfigure) configureDeviceGuidedSetup() {
|
||||||
// we only ask for the configuration for the first usage
|
// we only ask for the configuration for the first usage
|
||||||
deviceCategory = supportedDeviceCategories[0]
|
deviceCategory = supportedDeviceCategories[0]
|
||||||
|
|
||||||
values = c.processConfig(templateItem.Params, deviceCategory)
|
values = c.processConfig(templateItem, deviceCategory)
|
||||||
|
|
||||||
deviceItem, err = c.processDeviceValues(values, templateItem, deviceItem, deviceCategory)
|
deviceItem, err = c.processDeviceValues(values, templateItem, deviceItem, deviceCategory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -86,7 +86,7 @@ func (c *CmdConfigure) configureDeviceGuidedSetup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(templateItem.Description + " " + c.localizedString("Device_Added", nil))
|
fmt.Println(templateItem.Description.String(c.lang) + " " + c.localizedString("Device_Added", nil))
|
||||||
|
|
||||||
c.configureLinkedTypes(templateItem)
|
c.configureLinkedTypes(templateItem)
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ func (c *CmdConfigure) configureLinkedTypes(templateItem templates.Template) {
|
||||||
category := DeviceCategory(linkedTemplate.Usage)
|
category := DeviceCategory(linkedTemplate.Usage)
|
||||||
|
|
||||||
localizeMap := localizeMap{
|
localizeMap := localizeMap{
|
||||||
"Linked": linkedTemplateItem.Description,
|
"Linked": linkedTemplateItem.Description.String(c.lang),
|
||||||
"Article": DeviceCategories[category].article,
|
"Article": DeviceCategories[category].article,
|
||||||
"Additional": DeviceCategories[category].additional,
|
"Additional": DeviceCategories[category].additional,
|
||||||
"Category": DeviceCategories[category].title,
|
"Category": DeviceCategories[category].title,
|
||||||
|
|
@ -148,7 +148,6 @@ func (c *CmdConfigure) configureLinkedTypes(templateItem templates.Template) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("DONE")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// configureLinkedTemplate lets the user configure a device that is marked as being linked to a guided device
|
// configureLinkedTemplate lets the user configure a device that is marked as being linked to a guided device
|
||||||
|
|
@ -157,7 +156,7 @@ func (c *CmdConfigure) configureLinkedTemplate(template templates.Template, cate
|
||||||
for ok := true; ok; {
|
for ok := true; ok; {
|
||||||
deviceItem := device{}
|
deviceItem := device{}
|
||||||
|
|
||||||
values := c.processConfig(template.Params, category)
|
values := c.processConfig(template, category)
|
||||||
deviceItem, err := c.processDeviceValues(values, template, deviceItem, category)
|
deviceItem, err := c.processDeviceValues(values, template, deviceItem, category)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, c.errDeviceNotValid) {
|
if !errors.Is(err, c.errDeviceNotValid) {
|
||||||
|
|
@ -173,7 +172,7 @@ func (c *CmdConfigure) configureLinkedTemplate(template templates.Template, cate
|
||||||
c.configuration.AddDevice(deviceItem, category)
|
c.configuration.AddDevice(deviceItem, category)
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(template.Description + " " + c.localizedString("Device_Added", nil))
|
fmt.Println(template.Description.String(c.lang) + " " + c.localizedString("Device_Added", nil))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
@ -182,7 +181,7 @@ func (c *CmdConfigure) configureLinkedTemplate(template templates.Template, cate
|
||||||
}
|
}
|
||||||
|
|
||||||
// configureDeviceCategory lets the user select and configure a device from a specific category
|
// configureDeviceCategory lets the user select and configure a device from a specific category
|
||||||
func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (device, error) {
|
func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (device, templates.Capabilities, error) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Printf("- %s %s\n", c.localizedString("Device_Configure", nil), DeviceCategories[deviceCategory].title)
|
fmt.Printf("- %s %s\n", c.localizedString("Device_Configure", nil), DeviceCategories[deviceCategory].title)
|
||||||
|
|
||||||
|
|
@ -191,6 +190,7 @@ func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (d
|
||||||
}
|
}
|
||||||
|
|
||||||
var deviceDescription string
|
var deviceDescription string
|
||||||
|
var capabilities templates.Capabilities
|
||||||
|
|
||||||
// repeat until the device is added or the user chooses to continue without adding a device
|
// repeat until the device is added or the user chooses to continue without adding a device
|
||||||
for ok := true; ok; {
|
for ok := true; ok; {
|
||||||
|
|
@ -198,11 +198,12 @@ func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (d
|
||||||
|
|
||||||
templateItem, err := c.processDeviceSelection(deviceCategory)
|
templateItem, err := c.processDeviceSelection(deviceCategory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return device, c.errItemNotPresent
|
return device, capabilities, c.errItemNotPresent
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceDescription = templateItem.Description
|
deviceDescription = templateItem.Description.String(c.lang)
|
||||||
values := c.processConfig(templateItem.Params, deviceCategory)
|
capabilities = templateItem.Capabilities
|
||||||
|
values := c.processConfig(templateItem, deviceCategory)
|
||||||
|
|
||||||
device, err = c.processDeviceValues(values, templateItem, device, deviceCategory)
|
device, err = c.processDeviceValues(values, templateItem, device, deviceCategory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -213,7 +214,7 @@ func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (d
|
||||||
// ask if the user wants to add the
|
// ask if the user wants to add the
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
if !c.askConfigFailureNextStep() {
|
if !c.askConfigFailureNextStep() {
|
||||||
return device, err
|
return device, capabilities, err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -231,5 +232,5 @@ func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (d
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(deviceDescription + deviceTitle + " " + c.localizedString("Device_Added", nil))
|
fmt.Println(deviceDescription + deviceTitle + " " + c.localizedString("Device_Added", nil))
|
||||||
|
|
||||||
return device, nil
|
return device, capabilities, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/evcc-io/evcc/provider/mqtt"
|
||||||
|
"github.com/evcc-io/evcc/util"
|
||||||
"github.com/evcc-io/evcc/util/sponsor"
|
"github.com/evcc-io/evcc/util/sponsor"
|
||||||
"github.com/evcc-io/evcc/util/templates"
|
"github.com/evcc-io/evcc/util/templates"
|
||||||
"github.com/thoas/go-funk"
|
"github.com/thoas/go-funk"
|
||||||
|
|
@ -15,7 +17,7 @@ import (
|
||||||
func (c *CmdConfigure) processDeviceSelection(deviceCategory DeviceCategory) (templates.Template, error) {
|
func (c *CmdConfigure) processDeviceSelection(deviceCategory DeviceCategory) (templates.Template, error) {
|
||||||
templateItem := c.selectItem(deviceCategory)
|
templateItem := c.selectItem(deviceCategory)
|
||||||
|
|
||||||
if templateItem.Description == c.localizedString("ItemNotPresent", nil) {
|
if templateItem.Description.String(c.lang) == c.localizedString("ItemNotPresent", nil) {
|
||||||
return templateItem, c.errItemNotPresent
|
return templateItem, c.errItemNotPresent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,7 +33,7 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa
|
||||||
c.addedDeviceIndex++
|
c.addedDeviceIndex++
|
||||||
|
|
||||||
device.Name = fmt.Sprintf("%s%d", DeviceCategories[deviceCategory].defaultName, c.addedDeviceIndex)
|
device.Name = fmt.Sprintf("%s%d", DeviceCategories[deviceCategory].defaultName, c.addedDeviceIndex)
|
||||||
device.Title = templateItem.Description
|
device.Title = templateItem.Description.String(c.lang)
|
||||||
for item, value := range values {
|
for item, value := range values {
|
||||||
if strings.ToLower(item) != "title" {
|
if strings.ToLower(item) != "title" {
|
||||||
continue
|
continue
|
||||||
|
|
@ -45,9 +47,9 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
if categoryWithUsage {
|
if categoryWithUsage {
|
||||||
fmt.Println(c.localizedString("TestingDevice_TitleUsage", localizeMap{"Device": templateItem.Description, "Usage": deviceCategory.String()}))
|
fmt.Println(c.localizedString("TestingDevice_TitleUsage", localizeMap{"Device": templateItem.Description.String(c.lang), "Usage": deviceCategory.String()}))
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(c.localizedString("TestingDevice_Title", localizeMap{"Device": templateItem.Description}))
|
fmt.Println(c.localizedString("TestingDevice_Title", localizeMap{"Device": templateItem.Description.String(c.lang)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceTest := DeviceTest{
|
deviceTest := DeviceTest{
|
||||||
|
|
@ -61,9 +63,9 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa
|
||||||
fmt.Println(" ", c.localizedString("Error", localizeMap{"Error": err}))
|
fmt.Println(" ", c.localizedString("Error", localizeMap{"Error": err}))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
question := c.localizedString("TestingDevice_AddFailed", localizeMap{"Device": templateItem.Description})
|
question := c.localizedString("TestingDevice_AddFailed", localizeMap{"Device": templateItem.Description.String(c.lang)})
|
||||||
if categoryWithUsage {
|
if categoryWithUsage {
|
||||||
question = c.localizedString("TestingDevice_AddFailedUsage", localizeMap{"Device": templateItem.Description, "Usage": deviceCategory.String()})
|
question = c.localizedString("TestingDevice_AddFailedUsage", localizeMap{"Device": templateItem.Description.String(c.lang), "Usage": deviceCategory.String()})
|
||||||
}
|
}
|
||||||
if !c.askYesNo(question) {
|
if !c.askYesNo(question) {
|
||||||
c.addedDeviceIndex--
|
c.addedDeviceIndex--
|
||||||
|
|
@ -77,7 +79,7 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa
|
||||||
|
|
||||||
templateItem.Params = append(templateItem.Params, templates.Param{Name: "name", Value: device.Name})
|
templateItem.Params = append(templateItem.Params, templates.Param{Name: "name", Value: device.Name})
|
||||||
if !c.expandedMode {
|
if !c.expandedMode {
|
||||||
b, err := templateItem.RenderProxyWithValues(values, false)
|
b, err := templateItem.RenderProxyWithValues(values, c.lang, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.addedDeviceIndex--
|
c.addedDeviceIndex--
|
||||||
return device, err
|
return device, err
|
||||||
|
|
@ -91,7 +93,7 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa
|
||||||
templateItem.Render = fmt.Sprintf("name: {{ .name }}\n%s", templateItem.Render)
|
templateItem.Render = fmt.Sprintf("name: {{ .name }}\n%s", templateItem.Render)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b, _, err := templateItem.RenderResult(false, values)
|
b, _, err := templateItem.RenderResult(templates.TemplateRenderModeInstance, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.addedDeviceIndex--
|
c.addedDeviceIndex--
|
||||||
return device, err
|
return device, err
|
||||||
|
|
@ -115,21 +117,9 @@ func (c *CmdConfigure) processDeviceRequirements(templateItem templates.Template
|
||||||
|
|
||||||
// check if sponsorship is required
|
// check if sponsorship is required
|
||||||
if templateItem.Requirements.Sponsorship && c.configuration.config.SponsorToken == "" {
|
if templateItem.Requirements.Sponsorship && c.configuration.config.SponsorToken == "" {
|
||||||
fmt.Println("-- Sponsorship -----------------------------")
|
if err := c.askSponsortoken(true); err != nil {
|
||||||
fmt.Println()
|
return err
|
||||||
fmt.Println(c.localizedString("Requirements_Sponsorship_Title", nil))
|
|
||||||
fmt.Println()
|
|
||||||
if !c.askYesNo(c.localizedString("Requirements_Sponsorship_Token", nil)) {
|
|
||||||
return c.errItemNotPresent
|
|
||||||
}
|
}
|
||||||
sponsortoken := c.askValue(question{
|
|
||||||
label: c.localizedString("Requirements_Sponsorship_Token_Input", nil),
|
|
||||||
mask: true,
|
|
||||||
required: true})
|
|
||||||
c.configuration.config.SponsorToken = sponsortoken
|
|
||||||
sponsor.Subject = sponsortoken
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("--------------------------------------------")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we need to setup a HEMS
|
// check if we need to setup a HEMS
|
||||||
|
|
@ -140,6 +130,23 @@ func (c *CmdConfigure) processDeviceRequirements(templateItem templates.Template
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if we need to setup an MQTT broker
|
||||||
|
if templateItem.Requirements.Mqtt {
|
||||||
|
if c.configuration.config.MQTT == "" {
|
||||||
|
mqttConfig, err := c.configureMQTT()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mqttYaml, err := yaml.Marshal(mqttConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.configuration.config.MQTT = string(mqttYaml)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if we need to setup an EEBUS HEMS
|
// check if we need to setup an EEBUS HEMS
|
||||||
if templateItem.Requirements.Eebus {
|
if templateItem.Requirements.Eebus {
|
||||||
if c.configuration.config.EEBUS == "" {
|
if c.configuration.config.EEBUS == "" {
|
||||||
|
|
@ -173,12 +180,90 @@ func (c *CmdConfigure) processDeviceRequirements(templateItem templates.Template
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CmdConfigure) askSponsortoken(required bool) error {
|
||||||
|
fmt.Println("-- Sponsorship -----------------------------")
|
||||||
|
if required {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(c.localizedString("Requirements_Sponsorship_Title", nil))
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
if !c.askYesNo(c.localizedString("Requirements_Sponsorship_Token", nil)) {
|
||||||
|
return c.errItemNotPresent
|
||||||
|
}
|
||||||
|
|
||||||
|
sponsortoken := c.askValue(question{
|
||||||
|
label: c.localizedString("Requirements_Sponsorship_Token_Input", nil),
|
||||||
|
mask: true,
|
||||||
|
required: true})
|
||||||
|
c.configuration.config.SponsorToken = sponsortoken
|
||||||
|
sponsor.Subject = sponsortoken
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("--------------------------------------------")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CmdConfigure) configureMQTT() (map[string]interface{}, error) {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("-- MQTT Broker ----------------------------")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for ok := true; ok; {
|
||||||
|
fmt.Println()
|
||||||
|
host := c.askValue(question{
|
||||||
|
label: c.localizedString("UserFriendly_Host_Name", nil),
|
||||||
|
mask: false,
|
||||||
|
required: true})
|
||||||
|
|
||||||
|
port := c.askValue(question{
|
||||||
|
label: c.localizedString("UserFriendly_Port_Name", nil),
|
||||||
|
mask: false,
|
||||||
|
required: true})
|
||||||
|
|
||||||
|
user := c.askValue(question{
|
||||||
|
label: c.localizedString("UserFriendly_User_Name", nil),
|
||||||
|
mask: false,
|
||||||
|
required: false})
|
||||||
|
|
||||||
|
password := c.askValue(question{
|
||||||
|
label: c.localizedString("UserFriendly_Password_Name", nil),
|
||||||
|
mask: true,
|
||||||
|
required: false})
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("-------------------------------------------")
|
||||||
|
|
||||||
|
broker := fmt.Sprintf("%s:%s", host, port)
|
||||||
|
|
||||||
|
mqttConfig := map[string]interface{}{
|
||||||
|
"broker": broker,
|
||||||
|
"user": user,
|
||||||
|
"password": password,
|
||||||
|
}
|
||||||
|
|
||||||
|
log := util.NewLogger("mqtt")
|
||||||
|
|
||||||
|
if mqtt.Instance, err = mqtt.RegisteredClient(log, broker, user, password, "", 1); err == nil {
|
||||||
|
return mqttConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
question := c.localizedString("TestingMQTTFailed", nil)
|
||||||
|
if !c.askYesNo(question) {
|
||||||
|
return nil, fmt.Errorf("failed configuring mqtt: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("failed configuring mqtt: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// fetchElements returns template items of a given class
|
// fetchElements returns template items of a given class
|
||||||
func (c *CmdConfigure) fetchElements(deviceCategory DeviceCategory) []templates.Template {
|
func (c *CmdConfigure) fetchElements(deviceCategory DeviceCategory) []templates.Template {
|
||||||
var items []templates.Template
|
var items []templates.Template
|
||||||
|
|
||||||
for _, tmpl := range templates.ByClass(DeviceCategories[deviceCategory].class.String()) {
|
for _, tmpl := range templates.ByClass(DeviceCategories[deviceCategory].class.String()) {
|
||||||
if len(tmpl.Params) == 0 || len(tmpl.Description) == 0 {
|
if len(tmpl.Params) == 0 || len(tmpl.Description.String(c.lang)) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +287,7 @@ func (c *CmdConfigure) fetchElements(deviceCategory DeviceCategory) []templates.
|
||||||
if !items[i].Generic && items[j].Generic {
|
if !items[i].Generic && items[j].Generic {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return strings.ToLower(items[i].Description) < strings.ToLower(items[j].Description)
|
return strings.ToLower(items[i].Description.String(c.lang)) < strings.ToLower(items[j].Description.String(c.lang))
|
||||||
})
|
})
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
|
@ -233,7 +318,7 @@ func (c *CmdConfigure) paramChoiceValues(params []templates.Param, name string)
|
||||||
// processConfig processes an EVCC configuration item
|
// processConfig processes an EVCC configuration item
|
||||||
// Returns:
|
// Returns:
|
||||||
// a map with param name and values
|
// a map with param name and values
|
||||||
func (c *CmdConfigure) processConfig(paramItems []templates.Param, deviceCategory DeviceCategory) map[string]interface{} {
|
func (c *CmdConfigure) processConfig(templateItem templates.Template, deviceCategory DeviceCategory) map[string]interface{} {
|
||||||
usageFilter := DeviceCategories[deviceCategory].categoryFilter
|
usageFilter := DeviceCategories[deviceCategory].categoryFilter
|
||||||
|
|
||||||
additionalConfig := make(map[string]interface{})
|
additionalConfig := make(map[string]interface{})
|
||||||
|
|
@ -242,7 +327,33 @@ func (c *CmdConfigure) processConfig(paramItems []templates.Param, deviceCategor
|
||||||
fmt.Println(c.localizedString("Config_Title", nil))
|
fmt.Println(c.localizedString("Config_Title", nil))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
for _, param := range paramItems {
|
for _, param := range templateItem.Params {
|
||||||
|
if param.Dependencies != nil {
|
||||||
|
valid := true
|
||||||
|
for _, dep := range param.Dependencies {
|
||||||
|
_, valueParam := templateItem.ParamByName(dep.Name)
|
||||||
|
if valueParam == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
value := valueParam.Value
|
||||||
|
switch dep.Check {
|
||||||
|
case templates.DependencyCheckEmpty:
|
||||||
|
valid = value == ""
|
||||||
|
case templates.DependencyCheckNotEmpty:
|
||||||
|
valid = value != ""
|
||||||
|
case templates.DependencyCheckEqual:
|
||||||
|
valid = value == dep.Value
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch param.Name {
|
switch param.Name {
|
||||||
case templates.ParamModbus:
|
case templates.ParamModbus:
|
||||||
c.processModbusConfig(param, deviceCategory, additionalConfig)
|
c.processModbusConfig(param, deviceCategory, additionalConfig)
|
||||||
|
|
@ -271,7 +382,7 @@ func (c *CmdConfigure) processConfig(paramItems []templates.Param, deviceCategor
|
||||||
func (c *CmdConfigure) processListInputConfig(param templates.Param) []string {
|
func (c *CmdConfigure) processListInputConfig(param templates.Param) []string {
|
||||||
var values []string
|
var values []string
|
||||||
|
|
||||||
// ask for values until the decides stops
|
// ask for values until the user decides to stop
|
||||||
for ok := true; ok; {
|
for ok := true; ok; {
|
||||||
newValue := c.processInputConfig(param)
|
newValue := c.processInputConfig(param)
|
||||||
values = append(values, newValue)
|
values = append(values, newValue)
|
||||||
|
|
@ -291,8 +402,15 @@ func (c *CmdConfigure) processListInputConfig(param templates.Param) []string {
|
||||||
// handle user input for a simple one value input
|
// handle user input for a simple one value input
|
||||||
func (c *CmdConfigure) processInputConfig(param templates.Param) string {
|
func (c *CmdConfigure) processInputConfig(param templates.Param) string {
|
||||||
userFriendly := c.userFriendlyTexts(param)
|
userFriendly := c.userFriendlyTexts(param)
|
||||||
|
|
||||||
|
label := userFriendly.Name
|
||||||
|
langLabel := param.Description.String(c.lang)
|
||||||
|
if langLabel != "" {
|
||||||
|
label = langLabel
|
||||||
|
}
|
||||||
|
|
||||||
return c.askValue(question{
|
return c.askValue(question{
|
||||||
label: userFriendly.Name,
|
label: label,
|
||||||
defaultValue: userFriendly.Default,
|
defaultValue: userFriendly.Default,
|
||||||
exampleValue: userFriendly.Example,
|
exampleValue: userFriendly.Example,
|
||||||
help: userFriendly.Help.String(c.lang),
|
help: userFriendly.Help.String(c.lang),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
Intro = "Die nächsten Schritte führen durch die Einrichtung einer Konfigurationsdatei für evcc.\nBeachte dass dieser Prozess nicht alle möglichen Szenarien berücksichtigen kann.\nDurch Drücken von CTRL-C kann der Prozess abgebrochen werden.\n\nACHTUNG: Diese Funktionalität hat experimentellen Status!\n D.h. es kann möglich sein, dass die hiermit erstellte Konfigurationsdatei\n in einem Update nicht mehr funktionieren könnte und neu erzeugt werden müsste.\n Wir freuen uns auf euer Feedback auf https://github.com/evcc-io/evcc/discussions/\n\nAuf geht`s:"
|
Intro = "Die nächsten Schritte führen durch die Einrichtung einer Konfigurationsdatei für evcc.\nBeachte dass dieser Prozess nicht alle möglichen Szenarien berücksichtigen kann.\nDurch Drücken von CTRL-C kann der Prozess abgebrochen werden.\n\nACHTUNG: Diese Funktionalität hat experimentellen Status!\n D.h. es kann möglich sein, dass die hiermit erstellte Konfigurationsdatei\n in einem Update nicht mehr funktionieren könnte und neu erzeugt werden müsste.\n Wir freuen uns auf euer Feedback auf https://github.com/evcc-io/evcc/discussions/\n\nAuf geht`s:"
|
||||||
|
|
||||||
|
Flow_Mode = "In welchem Modus soll die Konfiguration durchgeführt werden?"
|
||||||
|
Flow_Mode_Standard = "Standard Modus (So einfach und schnell wie möglich)"
|
||||||
|
Flow_Mode_Advanced = "Fortgeschrittener Modus (Detailliertere Fragen, erfordert jedoch technisches Know-How)"
|
||||||
|
|
||||||
Flow_Type = "Was möchtest du machen?"
|
Flow_Type = "Was möchtest du machen?"
|
||||||
Flow_Type_NewConfiguration = "Eine neue evcc Konfigurationsdatei erstellen"
|
Flow_Type_NewConfiguration = "Eine neue evcc Konfigurationsdatei erstellen"
|
||||||
Flow_Type_SingleDevice = "Ein einzelnes Gerät konfigurieren (muss manuell in eine Konfigurationsdatei eingetragen werden!)"
|
Flow_Type_SingleDevice = "Ein einzelnes Gerät konfigurieren (muss manuell in eine Konfigurationsdatei eingetragen werden!)"
|
||||||
|
|
@ -90,6 +94,8 @@ TestingDevice_RepeatStep = "Möchtest du erneut ein Gerät aus der Liste auswäh
|
||||||
TestingDevice_AddFailed = "Der Test von {{ .Device }} ist fehlgeschlagen. Soll es trotzdem in die Konfiguration aufgenommen werden?"
|
TestingDevice_AddFailed = "Der Test von {{ .Device }} ist fehlgeschlagen. Soll es trotzdem in die Konfiguration aufgenommen werden?"
|
||||||
TestingDevice_AddFailedUsage = "Der Test der {{ .Usage }} Konfiguration von {{ .Device }} ist fehlgeschlagen. Soll es trotzdem in die Konfiguration aufgenommen werden?"
|
TestingDevice_AddFailedUsage = "Der Test der {{ .Usage }} Konfiguration von {{ .Device }} ist fehlgeschlagen. Soll es trotzdem in die Konfiguration aufgenommen werden?"
|
||||||
|
|
||||||
|
TestingMQTTFailed = "Der Test der MQTT Konfiguration ist fehlgeschlagen. Möchten Sie die Konfiguration wiederholen?"
|
||||||
|
|
||||||
Requirements_Title = "Das Gerät muss die folgenden Voraussetzungen erfüllen:"
|
Requirements_Title = "Das Gerät muss die folgenden Voraussetzungen erfüllen:"
|
||||||
Requirements_More = "Weitere Informationen:"
|
Requirements_More = "Weitere Informationen:"
|
||||||
|
|
||||||
|
|
@ -131,7 +137,8 @@ Loadpoint_ResetOnDisconnect = "Soll beim Abstecken des Ladekables von einem Fahr
|
||||||
|
|
||||||
Loadpoint_WallboxWOMeter = "Die Wallbox hat keinen Ladestromzähler. Hast du einen externen Zähler dafür installiert, der verwendet werden kann?"
|
Loadpoint_WallboxWOMeter = "Die Wallbox hat keinen Ladestromzähler. Hast du einen externen Zähler dafür installiert, der verwendet werden kann?"
|
||||||
Loadpoint_WallboxMaxPower = "Was ist die maximale Leistung, welche die Wallbox zur Verfügung stellen kann?"
|
Loadpoint_WallboxMaxPower = "Was ist die maximale Leistung, welche die Wallbox zur Verfügung stellen kann?"
|
||||||
Loadpoint_WallboxMaxAmperage = "Was ist die maximale Stromstärke, welche die Wallbox auf einer Phase zur Verfügung stellen kann?"
|
Loadpoint_WallboxMinAmperage = "Was ist die MINIMALE Stromstärke, welche die Wallbox auf einer Phase zur Verfügung stellen kann?"
|
||||||
|
Loadpoint_WallboxMaxAmperage = "Was ist die MAXIMALE Stromstärke, welche die Wallbox auf einer Phase zur Verfügung stellen kann?"
|
||||||
Loadpoint_WallboxPhases = "Mit wievielen Phasen ist die Wallbox angeschlossen?"
|
Loadpoint_WallboxPhases = "Mit wievielen Phasen ist die Wallbox angeschlossen?"
|
||||||
Loadpoint_WallboxPower36kW = "3,6 kW"
|
Loadpoint_WallboxPower36kW = "3,6 kW"
|
||||||
Loadpoint_WallboxPower11kW = "11 kW"
|
Loadpoint_WallboxPower11kW = "11 kW"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
Intro = "The next steps will guide you through the creation of a configuration file for evcc.\nPlease note that this process cannot cover all possible scenarios.\nYou can cancel the process by pressing CTRL-C anytime.\n\nNOTE: This functionality is in an experimental state!\n This means that the created configuration file may not work\n in a future update of evcc and would need to be recreated.\n We are looking forward to your feedback at https://github.com/evcc-io/evcc/discussions/\n\nLet's go:"
|
Intro = "The next steps will guide you through the creation of a configuration file for evcc.\nPlease note that this process cannot cover all possible scenarios.\nYou can cancel the process by pressing CTRL-C anytime.\n\nNOTE: This functionality is in an experimental state!\n This means that the created configuration file may not work\n in a future update of evcc and would need to be recreated.\n We are looking forward to your feedback at https://github.com/evcc-io/evcc/discussions/\n\nLet's go:"
|
||||||
|
|
||||||
|
Flow_Mode = "In which mode should this process guide you through the configuration?"
|
||||||
|
Flow_Mode_Standard = "Standard mode (As simple and quick as possible)"
|
||||||
|
Flow_Mode_Advanced = "Advanced mode (Ask more details, requires technical know-how)"
|
||||||
|
|
||||||
Flow_Type = "What do you want to do?"
|
Flow_Type = "What do you want to do?"
|
||||||
Flow_Type_NewConfiguration = "Create a new evcc configuration file"
|
Flow_Type_NewConfiguration = "Create a new evcc configuration file"
|
||||||
Flow_Type_SingleDevice = "Configure a single device (has to be added manually to a configuration file!)"
|
Flow_Type_SingleDevice = "Configure a single device (has to be added manually to a configuration file!)"
|
||||||
|
|
@ -90,6 +94,8 @@ TestingDevice_RepeatStep = "Do you want to repeat choosing a device and configur
|
||||||
TestingDevice_AddFailed = "Testing {{ .Device }} failed. Do you want to add it anyway?"
|
TestingDevice_AddFailed = "Testing {{ .Device }} failed. Do you want to add it anyway?"
|
||||||
TestingDevice_AddFailedUsage = "Testing of the {{ .Usage }} configuration of {{ .Device }} failed. Do you want to add it anyway?"
|
TestingDevice_AddFailedUsage = "Testing of the {{ .Usage }} configuration of {{ .Device }} failed. Do you want to add it anyway?"
|
||||||
|
|
||||||
|
TestingMQTTFailed = "Testing the MQTT configuration failed. Do you want to repeat its configuration?"
|
||||||
|
|
||||||
Requirements_Title = "The device needs to provide the following requirements:"
|
Requirements_Title = "The device needs to provide the following requirements:"
|
||||||
Requirements_More = "Additional information:"
|
Requirements_More = "Additional information:"
|
||||||
|
|
||||||
|
|
@ -131,7 +137,8 @@ Loadpoint_ResetOnDisconnect = "Shall disconnecting the charging cable from the v
|
||||||
|
|
||||||
Loadpoint_WallboxWOMeter = "The wallbox does not provide power data. Do you have an external meter that can be used?"
|
Loadpoint_WallboxWOMeter = "The wallbox does not provide power data. Do you have an external meter that can be used?"
|
||||||
Loadpoint_WallboxMaxPower = "What is the maximum power your wallbox can provide?"
|
Loadpoint_WallboxMaxPower = "What is the maximum power your wallbox can provide?"
|
||||||
Loadpoint_WallboxMaxAmperage = "What is the maximum amperage your wallbox can provide on a single phase?"
|
Loadpoint_WallboxMinAmperage = "What is the MINIMUM amperage your wallbox can provide on a single phase?"
|
||||||
|
Loadpoint_WallboxMaxAmperage = "What is the MAXIMUM amperage your wallbox can provide on a single phase?"
|
||||||
Loadpoint_WallboxPhases = "How many phases are connected to the wallbox?"
|
Loadpoint_WallboxPhases = "How many phases are connected to the wallbox?"
|
||||||
Loadpoint_WallboxPower36kW = "3.6 kW"
|
Loadpoint_WallboxPower36kW = "3.6 kW"
|
||||||
Loadpoint_WallboxPower11kW = "11 kW"
|
Loadpoint_WallboxPower11kW = "11 kW"
|
||||||
|
|
|
||||||
|
|
@ -65,19 +65,31 @@ func (c *CmdConfigure) Run(log *util.Logger, flagLang string, advancedMode, expa
|
||||||
|
|
||||||
c.setDefaultTexts()
|
c.setDefaultTexts()
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(c.localizedString("Intro", nil))
|
||||||
|
|
||||||
|
if !c.advancedMode {
|
||||||
|
// ask the user for his knowledge, so advanced mode can also be turned on this way
|
||||||
|
fmt.Println()
|
||||||
|
flowIndex, _ := c.askChoice(c.localizedString("Flow_Mode", nil), []string{
|
||||||
|
c.localizedString("Flow_Mode_Standard", nil),
|
||||||
|
c.localizedString("Flow_Mode_Advanced", nil),
|
||||||
|
})
|
||||||
|
if flowIndex == 1 {
|
||||||
|
c.advancedMode = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !c.advancedMode {
|
if !c.advancedMode {
|
||||||
c.flowNewConfigFile()
|
c.flowNewConfigFile()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(c.localizedString("Intro", nil))
|
flowIndex, _ := c.askChoice(c.localizedString("Flow_Type", nil), []string{
|
||||||
flowChoices := []string{
|
|
||||||
c.localizedString("Flow_Type_NewConfiguration", nil),
|
c.localizedString("Flow_Type_NewConfiguration", nil),
|
||||||
c.localizedString("Flow_Type_SingleDevice", nil),
|
c.localizedString("Flow_Type_SingleDevice", nil),
|
||||||
}
|
})
|
||||||
fmt.Println()
|
|
||||||
flowIndex, _ := c.askChoice(c.localizedString("Flow_Type", nil), flowChoices)
|
|
||||||
switch flowIndex {
|
switch flowIndex {
|
||||||
case 0:
|
case 0:
|
||||||
c.flowNewConfigFile()
|
c.flowNewConfigFile()
|
||||||
|
|
@ -143,6 +155,10 @@ func (c *CmdConfigure) flowNewConfigFile() {
|
||||||
c.configureLoadpoints()
|
c.configureLoadpoints()
|
||||||
c.configureSite()
|
c.configureSite()
|
||||||
|
|
||||||
|
if c.advancedMode && c.configuration.config.SponsorToken == "" {
|
||||||
|
_ = c.askSponsortoken(true)
|
||||||
|
}
|
||||||
|
|
||||||
yaml, err := c.configuration.RenderConfiguration()
|
yaml, err := c.configuration.RenderConfiguration()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.log.FATAL.Fatal(err)
|
c.log.FATAL.Fatal(err)
|
||||||
|
|
@ -207,7 +223,7 @@ func (c *CmdConfigure) configureDevices(deviceCategory DeviceCategory, askAdding
|
||||||
}
|
}
|
||||||
|
|
||||||
for ok := true; ok; {
|
for ok := true; ok; {
|
||||||
device, err := c.configureDeviceCategory(deviceCategory)
|
device, _, err := c.configureDeviceCategory(deviceCategory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +259,7 @@ func (c *CmdConfigure) configureLoadpoints() {
|
||||||
MinCurrent: 6,
|
MinCurrent: 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
charger, err := c.configureDeviceCategory(DeviceCategoryCharger)
|
charger, capabilities, err := c.configureDeviceCategory(DeviceCategoryCharger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +269,7 @@ func (c *CmdConfigure) configureLoadpoints() {
|
||||||
|
|
||||||
if !chargerHasMeter {
|
if !chargerHasMeter {
|
||||||
if c.askYesNo(c.localizedString("Loadpoint_WallboxWOMeter", nil)) {
|
if c.askYesNo(c.localizedString("Loadpoint_WallboxWOMeter", nil)) {
|
||||||
chargeMeter, err := c.configureDeviceCategory(DeviceCategoryChargeMeter)
|
chargeMeter, _, err := c.configureDeviceCategory(DeviceCategoryChargeMeter)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
loadpoint.ChargeMeter = chargeMeter.Name
|
loadpoint.ChargeMeter = chargeMeter.Name
|
||||||
chargerHasMeter = true
|
chargerHasMeter = true
|
||||||
|
|
@ -272,39 +288,26 @@ func (c *CmdConfigure) configureLoadpoints() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
powerChoices := []string{
|
var minValue int = 6
|
||||||
c.localizedString("Loadpoint_WallboxPower36kW", nil),
|
if capabilities.ISO151182 {
|
||||||
c.localizedString("Loadpoint_WallboxPower11kW", nil),
|
minValue = 2
|
||||||
c.localizedString("Loadpoint_WallboxPower22kW", nil),
|
|
||||||
c.localizedString("Loadpoint_WallboxPowerOther", nil),
|
|
||||||
}
|
}
|
||||||
fmt.Println()
|
|
||||||
powerIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxMaxPower", nil), powerChoices)
|
if c.advancedMode {
|
||||||
loadpoint.MinCurrent = 6
|
minAmperage := c.askValue(question{
|
||||||
switch powerIndex {
|
label: c.localizedString("Loadpoint_WallboxMinAmperage", nil),
|
||||||
case 0:
|
valueType: templates.ParamValueTypeNumber,
|
||||||
loadpoint.MaxCurrent = 16
|
minNumberValue: int64(minValue),
|
||||||
if !chargerHasMeter {
|
maxNumberValue: 32,
|
||||||
loadpoint.Phases = 1
|
required: true})
|
||||||
}
|
loadpoint.MinCurrent, _ = strconv.Atoi(minAmperage)
|
||||||
case 1:
|
maxAmperage := c.askValue(question{
|
||||||
loadpoint.MaxCurrent = 16
|
|
||||||
if !chargerHasMeter {
|
|
||||||
loadpoint.Phases = 3
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
loadpoint.MaxCurrent = 32
|
|
||||||
if !chargerHasMeter {
|
|
||||||
loadpoint.Phases = 3
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
amperage := c.askValue(question{
|
|
||||||
label: c.localizedString("Loadpoint_WallboxMaxAmperage", nil),
|
label: c.localizedString("Loadpoint_WallboxMaxAmperage", nil),
|
||||||
valueType: templates.ParamValueTypeNumber,
|
valueType: templates.ParamValueTypeNumber,
|
||||||
minNumberValue: 6,
|
minNumberValue: 6,
|
||||||
maxNumberValue: 32,
|
maxNumberValue: 32,
|
||||||
required: true})
|
required: true})
|
||||||
loadpoint.MaxCurrent, _ = strconv.Atoi(amperage)
|
loadpoint.MaxCurrent, _ = strconv.Atoi(maxAmperage)
|
||||||
|
|
||||||
if !chargerHasMeter {
|
if !chargerHasMeter {
|
||||||
phaseChoices := []string{"1", "2", "3"}
|
phaseChoices := []string{"1", "2", "3"}
|
||||||
|
|
@ -312,6 +315,48 @@ func (c *CmdConfigure) configureLoadpoints() {
|
||||||
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases", nil), phaseChoices)
|
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases", nil), phaseChoices)
|
||||||
loadpoint.Phases = phaseIndex + 1
|
loadpoint.Phases = phaseIndex + 1
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
powerChoices := []string{
|
||||||
|
c.localizedString("Loadpoint_WallboxPower36kW", nil),
|
||||||
|
c.localizedString("Loadpoint_WallboxPower11kW", nil),
|
||||||
|
c.localizedString("Loadpoint_WallboxPower22kW", nil),
|
||||||
|
c.localizedString("Loadpoint_WallboxPowerOther", nil),
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
powerIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxMaxPower", nil), powerChoices)
|
||||||
|
loadpoint.MinCurrent = minValue
|
||||||
|
switch powerIndex {
|
||||||
|
case 0:
|
||||||
|
loadpoint.MaxCurrent = 16
|
||||||
|
if !chargerHasMeter {
|
||||||
|
loadpoint.Phases = 1
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
loadpoint.MaxCurrent = 16
|
||||||
|
if !chargerHasMeter {
|
||||||
|
loadpoint.Phases = 3
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
loadpoint.MaxCurrent = 32
|
||||||
|
if !chargerHasMeter {
|
||||||
|
loadpoint.Phases = 3
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
amperage := c.askValue(question{
|
||||||
|
label: c.localizedString("Loadpoint_WallboxMaxAmperage", nil),
|
||||||
|
valueType: templates.ParamValueTypeNumber,
|
||||||
|
minNumberValue: int64(minValue),
|
||||||
|
maxNumberValue: 32,
|
||||||
|
required: true})
|
||||||
|
loadpoint.MaxCurrent, _ = strconv.Atoi(amperage)
|
||||||
|
|
||||||
|
if !chargerHasMeter {
|
||||||
|
phaseChoices := []string{"1", "2", "3"}
|
||||||
|
fmt.Println()
|
||||||
|
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases", nil), phaseChoices)
|
||||||
|
loadpoint.Phases = phaseIndex + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
|
||||||
|
|
@ -64,15 +64,15 @@ func (c *CmdConfigure) askSelection(message string, items []string) (error, stri
|
||||||
// selectItem selects item from list
|
// selectItem selects item from list
|
||||||
func (c *CmdConfigure) selectItem(deviceCategory DeviceCategory) templates.Template {
|
func (c *CmdConfigure) selectItem(deviceCategory DeviceCategory) templates.Template {
|
||||||
var emptyItem templates.Template
|
var emptyItem templates.Template
|
||||||
emptyItem.Description = c.localizedString("ItemNotPresent", nil)
|
emptyItem.Description.SetString(c.localizedString("ItemNotPresent", nil), c.lang)
|
||||||
|
|
||||||
elements := c.fetchElements(deviceCategory)
|
elements := c.fetchElements(deviceCategory)
|
||||||
elements = append(elements, emptyItem)
|
elements = append(elements, emptyItem)
|
||||||
|
|
||||||
var items []string
|
var items []string
|
||||||
for _, item := range elements {
|
for _, item := range elements {
|
||||||
if item.Description != "" {
|
if item.Description.String(c.lang) != "" {
|
||||||
items = append(items, item.Description)
|
items = append(items, item.Description.String(c.lang))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ func NewMeterFromTemplateConfig(other map[string]interface{}) (api.Meter, error)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b, _, err := tmpl.RenderResult(false, other)
|
b, _, err := tmpl.RenderResult(templates.TemplateRenderModeInstance, other)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ func TestMeterTemplates(t *testing.T) {
|
||||||
tmpl := tmpl
|
tmpl := tmpl
|
||||||
|
|
||||||
// set default values for all params
|
// set default values for all params
|
||||||
values := tmpl.Defaults(true)
|
values := tmpl.Defaults(templates.TemplateRenderModeUnitTest)
|
||||||
|
|
||||||
// set the template value which is needed for rendering
|
// set the template value which is needed for rendering
|
||||||
values["template"] = tmpl.Template
|
values["template"] = tmpl.Template
|
||||||
|
|
@ -41,10 +41,11 @@ func TestMeterTemplates(t *testing.T) {
|
||||||
// set modbus default test values
|
// set modbus default test values
|
||||||
if values[templates.ParamModbus] != nil {
|
if values[templates.ParamModbus] != nil {
|
||||||
modbusChoices := tmpl.ModbusChoices()
|
modbusChoices := tmpl.ModbusChoices()
|
||||||
|
// we only test one modbus setup
|
||||||
if funk.ContainsString(modbusChoices, templates.ModbusChoiceTCPIP) {
|
if funk.ContainsString(modbusChoices, templates.ModbusChoiceTCPIP) {
|
||||||
values[templates.ModbusKeyTCPIP] = true
|
values[templates.ModbusTCPIP] = true
|
||||||
} else {
|
} else {
|
||||||
values[templates.ModbusKeyRS485TCPIP] = true
|
values[templates.ModbusRS485TCPIP] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,14 +71,16 @@ func runTest(t *testing.T, tmpl templates.Template, values map[string]interface{
|
||||||
t.Run(tmpl.Template, func(t *testing.T) {
|
t.Run(tmpl.Template, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
b, values, err := tmpl.RenderResult(true, values)
|
b, values, err := tmpl.RenderResult(templates.TemplateRenderModeUnitTest, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("%s: %s", tmpl.Template, b)
|
t.Logf("Template: %s", tmpl.Template)
|
||||||
|
t.Logf("%s", string(b))
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := NewFromConfig("template", values); err != nil && !test.Acceptable(err, acceptable) {
|
if _, err := NewFromConfig("template", values); err != nil && !test.Acceptable(err, acceptable) {
|
||||||
t.Logf("%s", tmpl.Template)
|
t.Logf("Template: %s", tmpl.Template)
|
||||||
|
t.Logf("%s", string(b))
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ The following describes each possible element in a yaml file
|
||||||
|
|
||||||
## `description`
|
## `description`
|
||||||
|
|
||||||
`description` expects a human readable description of the device, best language neutral and containing the name of the product
|
`description` expects a human readable description of the device, best containing the name of the product. Values are language specific names via `de`, `en`, `generic` (if string is language independent)
|
||||||
|
|
||||||
## `generic`
|
## `generic`
|
||||||
|
|
||||||
|
|
@ -60,6 +60,14 @@ Allows to define a list of meter devices that are typically installed with this
|
||||||
|
|
||||||
Example Use Case: With SMA Home Manager, there can be a SMA Energy Meter used for getting the PV generation or multiple SMA PV inverters. But never both together. So if the used added an SMA Energy Meter, then the flow shoudn't ask for SMA PV inverters.
|
Example Use Case: With SMA Home Manager, there can be a SMA Energy Meter used for getting the PV generation or multiple SMA PV inverters. But never both together. So if the used added an SMA Energy Meter, then the flow shoudn't ask for SMA PV inverters.
|
||||||
|
|
||||||
|
## `capabilities`
|
||||||
|
|
||||||
|
`capabilities` provides an option to define special capabilities of the devie
|
||||||
|
|
||||||
|
**Possible Values**:
|
||||||
|
|
||||||
|
- `iso151182: true`: If the charger supports communicating via ISO15118-2
|
||||||
|
|
||||||
## `requirements`
|
## `requirements`
|
||||||
|
|
||||||
`requirements` provides an option to define various requirements / dependencies that need to be setup
|
`requirements` provides an option to define various requirements / dependencies that need to be setup
|
||||||
|
|
@ -95,6 +103,39 @@ Example Use Case: With SMA Home Manager, there can be a SMA Energy Meter used fo
|
||||||
- `usage`: specifies a list of meter classes, the device can be used for. Possible values are `grid`, `pv`, `battery`, and `charger`
|
- `usage`: specifies a list of meter classes, the device can be used for. Possible values are `grid`, `pv`, `battery`, and `charger`
|
||||||
- `modbus`: specifies that this device is accessed via modbus. It requires the `choice` property to have a list of possible interface values the device provides. These values can be `rs485` and `tcpip`. The command will use either to ask the appropriate questions and settings. The `render` section needs to include the string `{{include "modbus" .}}` in all places where the configuration needs modbus settings.
|
- `modbus`: specifies that this device is accessed via modbus. It requires the `choice` property to have a list of possible interface values the device provides. These values can be `rs485` and `tcpip`. The command will use either to ask the appropriate questions and settings. The `render` section needs to include the string `{{include "modbus" .}}` in all places where the configuration needs modbus settings.
|
||||||
|
|
||||||
|
#### Modbus Options
|
||||||
|
|
||||||
|
- `id`: Device specific default for modbus ID
|
||||||
|
- `port`: Device specific default for modbus TCPIP port
|
||||||
|
- `baudrate`: Device specific default for modbus RS485 baudrate
|
||||||
|
- `comset`: Device specific default for modbus RS485 comset
|
||||||
|
|
||||||
|
### `description`
|
||||||
|
|
||||||
|
`description` allows to define user friendly and language specific names via `de`, `en`, `generic`
|
||||||
|
|
||||||
|
### `dependencies`
|
||||||
|
|
||||||
|
`dependencies` allows to define a list of checks, when this param should be presented to the user, if it should be only in special cases
|
||||||
|
|
||||||
|
#### `name`
|
||||||
|
|
||||||
|
`name` referenced the `param` `name` value
|
||||||
|
|
||||||
|
#### `check`
|
||||||
|
|
||||||
|
`check` defines which kind of check should be performed
|
||||||
|
|
||||||
|
**Possible values**:
|
||||||
|
|
||||||
|
- `empty`: if the `value` of the referenced `param` `name` should be empty
|
||||||
|
- `notempty`: if the `value` of the referenced `param` `name` should be **NOT** empty
|
||||||
|
- `equal`: if the `value` of the referenced `param` `name` should match the value of the `value` property
|
||||||
|
|
||||||
|
#### `value`
|
||||||
|
|
||||||
|
`value` property is used in the `equal` `check`
|
||||||
|
|
||||||
### `required`
|
### `required`
|
||||||
|
|
||||||
`required: true` defines if the user has to provide a value. Default is `false`
|
`required: true` defines if the user has to provide a value. Default is `false`
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: abl
|
template: abl
|
||||||
description: ABL eMH / SENEC.Wallbox pro
|
description:
|
||||||
|
generic: ABL eMH / SENEC.Wallbox pro
|
||||||
requirements:
|
requirements:
|
||||||
sponsorship: true
|
sponsorship: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: cfos_charger
|
template: cfos
|
||||||
description: cFos PowerBrain
|
description:
|
||||||
|
generic: cFos PowerBrain
|
||||||
requirements:
|
requirements:
|
||||||
sponsorship: true
|
sponsorship: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
template: daheimladen
|
template: daheimladen
|
||||||
description: Daheimladen (Cloud API)
|
description:
|
||||||
requirements:
|
generic: Daheimladen (Cloud API)
|
||||||
sponsorship: true
|
|
||||||
params:
|
params:
|
||||||
- name: token
|
- name: token
|
||||||
help:
|
help:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: easee
|
template: easee
|
||||||
description: Easee Home (Cloud API)
|
description:
|
||||||
|
generic: Easee Home (Cloud API)
|
||||||
requirements:
|
requirements:
|
||||||
sponsorship: true
|
sponsorship: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
template: eebus
|
template: eebus
|
||||||
description: EEBUS kompatible Wallbox
|
description:
|
||||||
|
de: EEBUS kompatible Wallbox
|
||||||
|
en: EEBUS compatible Wallbox
|
||||||
generic: true
|
generic: true
|
||||||
|
capabilities:
|
||||||
|
iso151182: true
|
||||||
requirements:
|
requirements:
|
||||||
eebus: true
|
eebus: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: evse_din
|
template: evse_din
|
||||||
description: EVSE DIN
|
description:
|
||||||
|
generic: EVSE DIN
|
||||||
params:
|
params:
|
||||||
- name: modbus
|
- name: modbus
|
||||||
choice: ["rs485"]
|
choice: ["rs485"]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: evsewifi
|
template: evsewifi
|
||||||
description: EVSE-Wifi
|
description:
|
||||||
|
generic: EVSE-Wifi
|
||||||
params:
|
params:
|
||||||
- name: host
|
- name: host
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: fritzdect
|
template: fritzdect
|
||||||
description: FritzDECT
|
description:
|
||||||
|
generic: FritzDECT
|
||||||
params:
|
params:
|
||||||
- name: uri
|
- name: uri
|
||||||
default: https://fritz.box
|
default: https://fritz.box
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: go-e
|
template: go-e
|
||||||
description: go-eCharger Home/Pro/V3
|
description:
|
||||||
|
generic: go-eCharger Home/Pro/V3
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: Home und PRO require firmware 040.0 or later, V3 requires firmware 052.1 or later.
|
en: Home und PRO require firmware 040.0 or later, V3 requires firmware 052.1 or later.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: heidelberg
|
template: heidelberg
|
||||||
description: Heidelberg Energy Control (Modbus RTU)
|
description:
|
||||||
|
generic: Heidelberg Energy Control (Modbus RTU)
|
||||||
requirements:
|
requirements:
|
||||||
sponsorship: true
|
sponsorship: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: ichargecion
|
template: ichargecion
|
||||||
description: i-CHARGE CION (Modbus RTU-over-TCP)
|
description:
|
||||||
|
generic: i-CHARGE CION (Modbus RTU-over-TCP)
|
||||||
params:
|
params:
|
||||||
- name: modbus
|
- name: modbus
|
||||||
choice: ["tcpip"]
|
choice: ["tcpip"]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: innogy-ebox
|
template: innogy-ebox
|
||||||
description: Innogy eBox
|
description:
|
||||||
|
generic: Innogy eBox
|
||||||
requirements:
|
requirements:
|
||||||
sponsorship: true
|
sponsorship: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: keba
|
template: keba
|
||||||
description: KEBA Connect
|
description:
|
||||||
|
generic: KEBA Connect
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: This requires the UDP function to be enabled with DIP 1.3 = ON, see the installation manual.
|
en: This requires the UDP function to be enabled with DIP 1.3 = ON, see the installation manual.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: nrgkick-bluetooth
|
template: nrgkick-bluetooth
|
||||||
description: NRGKick Bluetooth
|
description:
|
||||||
|
generic: NRGKick Bluetooth
|
||||||
params:
|
params:
|
||||||
- name: mac
|
- name: mac
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: nrgkick-connect
|
template: nrgkick-connect
|
||||||
description: NRGKick Connect
|
description:
|
||||||
|
generic: NRGKick Connect
|
||||||
params:
|
params:
|
||||||
- name: host
|
- name: host
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: openwb
|
template: openwb
|
||||||
description: openWB (MQTT)
|
description:
|
||||||
|
generic: openWB (MQTT)
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: The wallbox has to be configured running as a loadpoint.
|
en: The wallbox has to be configured running as a loadpoint.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: phoenix-em-eth
|
template: phoenix-em-eth
|
||||||
description: Phoenix EM-CP-PP-ETH Controller (Modbus TCP)
|
description:
|
||||||
|
generic: Phoenix EM-CP-PP-ETH Controller (Modbus TCP)
|
||||||
generic: true
|
generic: true
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: phoenix-ev-eth
|
template: phoenix-ev-eth
|
||||||
description: Phoenix EV-ETH Controller (Modbus TCP)
|
description:
|
||||||
|
generic: Phoenix EV-ETH Controller (Modbus TCP)
|
||||||
generic: true
|
generic: true
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: phoenix-ev-ser
|
template: phoenix-ev-ser
|
||||||
description: Phoenix EV-SER Controller (Modbus RTU)
|
description:
|
||||||
|
generic: Phoenix EV-SER Controller (Modbus RTU)
|
||||||
generic: true
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: modbus
|
- name: modbus
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
template: pmcc
|
template: pmcc
|
||||||
description: Porsche Mobile Charger Connect
|
description:
|
||||||
|
generic: Porsche Mobile Charger Connect
|
||||||
|
capabilities:
|
||||||
|
iso151182: true
|
||||||
requirements:
|
requirements:
|
||||||
eebus: true
|
eebus: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: pmcp
|
template: pmcp
|
||||||
description: Porsche Mobile Charger Plus
|
description:
|
||||||
|
generic: Porsche Mobile Charger Plus
|
||||||
requirements:
|
requirements:
|
||||||
eebus: true
|
eebus: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: shelly
|
template: shelly
|
||||||
description: Shelly
|
description:
|
||||||
|
generic: Shelly
|
||||||
params:
|
params:
|
||||||
- name: host
|
- name: host
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: tasmota
|
template: tasmota
|
||||||
description: Tasmota
|
description:
|
||||||
|
generic: Tasmota
|
||||||
params:
|
params:
|
||||||
- name: host
|
- name: host
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: tinkerforge-warp-pro
|
template: tinkerforge-warp-pro
|
||||||
description: TinkerForge WARP Charger Pro
|
description:
|
||||||
|
generic: TinkerForge WARP Charger Pro
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: A MQTT Broker software needs to be running on a computer. The MQTT connection also needs to be configured in the wallbox.
|
en: A MQTT Broker software needs to be running on a computer. The MQTT connection also needs to be configured in the wallbox.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: tinkerforge-warp
|
template: tinkerforge-warp
|
||||||
description: TinkerForge WARP Charger
|
description:
|
||||||
|
generic: TinkerForge WARP Charger
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: A MQTT Broker software needs to be running on a computer. The MQTT connection also needs to be configured in the wallbox.
|
en: A MQTT Broker software needs to be running on a computer. The MQTT connection also needs to be configured in the wallbox.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: tplink
|
template: tplink
|
||||||
description: TP-LINK Smart Plug
|
description:
|
||||||
|
generic: TP-LINK Smart Plug
|
||||||
params:
|
params:
|
||||||
- name: host
|
- name: host
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: wallbe-meter
|
template: wallbe-meter
|
||||||
description: Wallbe (Eco, Pro) with Meter
|
description:
|
||||||
|
de: Wallbe (Eco, Pro) mit Strommessgerät
|
||||||
|
en: Wallbe (Eco, Pro) with Meter
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: wallbe-pre2019-meter
|
template: wallbe-pre2019-meter
|
||||||
description: Wallbe (Eco, Pro) (pre ~2019) with Meter
|
description:
|
||||||
|
de: Wallbe (Eco, Pro) (vor ~2019) mit Strommessgerät
|
||||||
|
en: Wallbe (Eco, Pro) (pre ~2019) with Meter
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: wallbe-pre2019
|
template: wallbe-pre2019
|
||||||
description: Wallbe (Eco, Pro) (pre ~2019)
|
description:
|
||||||
|
de: Wallbe (Eco, Pro) (vor ~2019)
|
||||||
|
en: Wallbe (Eco, Pro) (pre ~2019)
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: wallbe
|
template: wallbe
|
||||||
description: Wallbe (Eco, Pro)
|
description:
|
||||||
|
generic: Wallbe (Eco, Pro)
|
||||||
requirements:
|
requirements:
|
||||||
description:
|
description:
|
||||||
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
en: The Wallbe must be connected using Ethernet and the DIP switch 10 must be set to 'ON'.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: cfos-meter
|
template: cfos
|
||||||
description: cFos PowerBrain Meter
|
description:
|
||||||
|
generic: cFos PowerBrain Meter
|
||||||
requirements:
|
requirements:
|
||||||
sponsorship: true
|
sponsorship: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: discovergy
|
template: discovergy
|
||||||
description: Discovergy (Cloud)
|
description:
|
||||||
|
generic: Discovergy (Cloud)
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: ["grid", "pv"]
|
choice: ["grid", "pv"]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: e3dc
|
template: e3dc
|
||||||
description: E3DC
|
description:
|
||||||
|
generic: E3DC
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: eastron
|
template: eastron
|
||||||
description: Eastron SDM Modbus Meter
|
description:
|
||||||
|
de: Eastron SDM Modbus Strommessgeräte
|
||||||
|
en: Eastron SDM Modbus Meter
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: ["grid", "pv", "battery", "charge"]
|
choice: ["grid", "pv", "battery", "charge"]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: fritzdect
|
template: fritzdect
|
||||||
description: FritzDECT
|
description:
|
||||||
|
generic: FritzDECT
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: ["pv", "charge"]
|
choice: ["pv", "charge"]
|
||||||
|
|
@ -17,12 +18,9 @@ params:
|
||||||
help:
|
help:
|
||||||
en: The AIN is printed on the type label on the back of the device.
|
en: The AIN is printed on the type label on the back of the device.
|
||||||
de: Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt.
|
de: Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt.
|
||||||
- name: standbypower
|
|
||||||
default: 15
|
|
||||||
render: |
|
render: |
|
||||||
type: fritzdect
|
type: fritzdect
|
||||||
uri: {{ .uri }}
|
uri: {{ .uri }}
|
||||||
user: {{ .user }}
|
user: {{ .user }}
|
||||||
password: {{ .password }}
|
password: {{ .password }}
|
||||||
ain: {{ .ain }} # switch actor identification number without blanks (see AIN number on switch sticker)
|
ain: {{ .ain }} # switch actor identification number without blanks (see AIN number on switch sticker)
|
||||||
standbypower: {{ .standbypower }} # treat as charging above this power
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: fronius-gen24
|
template: fronius-gen24
|
||||||
description: Fronius Symo GEN24 Plus
|
description:
|
||||||
|
generic: Fronius Symo GEN24 Plus
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: fronius-solarapi-v1
|
template: fronius-solarapi-v1
|
||||||
description: Fronius Solar API V1
|
description:
|
||||||
|
generic: Fronius Solar API V1
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: huawei-sun2000-8ktl
|
template: huawei-sun2000-8ktl
|
||||||
description: Huawei SUN2000-8KTL
|
description:
|
||||||
|
generic: Huawei SUN2000-8KTL
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: [ "pv" ]
|
choice: [ "pv" ]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: kostal-ksem-inverter
|
template: kostal-ksem-inverter
|
||||||
description: Kostal Smart Energy Meter via inverter
|
description:
|
||||||
|
de: Kostal Smart Energy Meter über den Wechselrichter
|
||||||
|
en: Kostal Smart Energy Meter via inverter
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: [ "grid" ]
|
choice: [ "grid" ]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: kostal-ksem
|
template: kostal-ksem
|
||||||
description: Kostal Smart Energy Meter
|
description:
|
||||||
|
generic: Kostal Smart Energy Meter
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: [ "grid" ]
|
choice: [ "grid" ]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: kostal-piko-mp-plus
|
template: kostal-piko-mp-plus
|
||||||
description: Kostal Piko MP Plus
|
description:
|
||||||
|
generic: Kostal Piko MP Plus
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
linked:
|
linked:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: kostal-piko
|
template: kostal-piko
|
||||||
description: Kostal Piko + Piko BA
|
description:
|
||||||
|
generic: Kostal Piko + Piko BA
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
@ -17,18 +18,18 @@ render: |
|
||||||
add:
|
add:
|
||||||
- source: http
|
- source: http
|
||||||
uri: http://{{ .host }}/api/dxs.json?dxsEntries=67109120 # PV AC Ausgang
|
uri: http://{{ .host }}/api/dxs.json?dxsEntries=67109120 # PV AC Ausgang
|
||||||
jq: .dxsEntries[0].value
|
jq: .dxsEntries[0].value | if . == null then 0 else . end
|
||||||
scale: -1.0
|
scale: -1.0
|
||||||
- source: http
|
- source: http
|
||||||
uri: http://{{ .host }}/api/dxs.json?dxsEntries=83886848 # Netzbezug
|
uri: http://{{ .host }}/api/dxs.json?dxsEntries=83886848 # Netzbezug
|
||||||
jq: .dxsEntries[0].value
|
jq: .dxsEntries[0].value | if . == null then 0 else . end
|
||||||
- source: http
|
- source: http
|
||||||
uri: http://{{ .host }}/api/dxs.json?dxsEntries=83886336 # PV Eigenverbrauch
|
uri: http://{{ .host }}/api/dxs.json?dxsEntries=83886336 # PV Eigenverbrauch
|
||||||
jq: .dxsEntries[0].value
|
jq: .dxsEntries[0].value | if . == null then 0 else . end
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if eq .usage "pv" }}
|
{{- if eq .usage "pv" }}
|
||||||
# PV
|
# PV
|
||||||
source: http
|
source: http
|
||||||
uri: http://{{ .host }}/api/dxs.json?dxsEntries=67109120 # PV AC Ausgang
|
uri: http://{{ .host }}/api/dxs.json?dxsEntries=67109120 # PV AC Ausgang
|
||||||
jq: .dxsEntries[0].value
|
jq: .dxsEntries[0].value | if . == null then 0 else . end
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: kostal-plenticore
|
template: kostal-plenticore
|
||||||
description: Kostal Plenticore Hybrid
|
description:
|
||||||
|
generic: Kostal Plenticore Hybrid
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
linked:
|
linked:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: lg-ess-home-8-10
|
template: lg-ess-home-8-10
|
||||||
description: LG ESS Home 8/10
|
description:
|
||||||
|
generic: LG ESS Home 8/10
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
105
templates/definition/meter/mqtt-meter.yaml
Normal file
105
templates/definition/meter/mqtt-meter.yaml
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
template: mqtt-meter
|
||||||
|
description:
|
||||||
|
de: MQTT Strommessgerät
|
||||||
|
en: MQTT Meter
|
||||||
|
generic: true
|
||||||
|
requirements:
|
||||||
|
mqtt: true
|
||||||
|
params:
|
||||||
|
- name: usage
|
||||||
|
choice: [ "grid", "pv", "charge", "battery" ]
|
||||||
|
- name: power
|
||||||
|
description:
|
||||||
|
de: MQTT Topic für die Leistung (W)
|
||||||
|
en: MQTT Topic for power (W)
|
||||||
|
required: true
|
||||||
|
- name: scalepower
|
||||||
|
description:
|
||||||
|
de: Skalierung der Leistungswerte
|
||||||
|
en: Scaling of the power value
|
||||||
|
default: 1
|
||||||
|
help:
|
||||||
|
de: Die Leistung wird in Watt erwartet. Falls z.b. kW geliefert wird, kann dies hier mit dem Wert 1000 angepasst werden
|
||||||
|
en: Power is expected to be provided in Watt. If it is provided in kW instead, set this value to 1000 to correct it
|
||||||
|
- name: energy
|
||||||
|
description:
|
||||||
|
de: MQTT Topic für Energiemenge (Wh)
|
||||||
|
en: MQTT Topic for energy (Wh)
|
||||||
|
- name: scaleenergy
|
||||||
|
dependencies:
|
||||||
|
- name: energy
|
||||||
|
check: notempty
|
||||||
|
description:
|
||||||
|
de: Skalierung der Energiement
|
||||||
|
en: Scaling of the energy value
|
||||||
|
default: 1
|
||||||
|
help:
|
||||||
|
de: Die Energiemenge wird in kWh erwartet. Falls z.b. Wh geliefert wird, kann dies hier mit dem Wert 0.001 angepasst werden
|
||||||
|
en: Power is expected to be provided in kWh. If it is provided in Wh instead, set this value to 0.001 to correct it
|
||||||
|
- name: soc
|
||||||
|
description:
|
||||||
|
de: MQTT Topic für den SoC der Batterie (%)
|
||||||
|
en: MQTT Topic for battery SoC (%)
|
||||||
|
dependencies:
|
||||||
|
- name: usage
|
||||||
|
check: equal
|
||||||
|
value: battery
|
||||||
|
- name: currentp1
|
||||||
|
description:
|
||||||
|
de: MQTT Topic Stromstärke (A) Phase 1
|
||||||
|
en: MQTT Topic Amperage (A) phase 1
|
||||||
|
- name: currentp2
|
||||||
|
description:
|
||||||
|
de: MQTT Topic Stromstärke (A) Phase 2
|
||||||
|
en: MQTT Topic Amperage (A) phase 2
|
||||||
|
dependencies:
|
||||||
|
- name: currentp1
|
||||||
|
check: notempty
|
||||||
|
- name: currentp3
|
||||||
|
description:
|
||||||
|
de: MQTT Topic Stromstärke (A) Phase 3
|
||||||
|
en: MQTT Topic Amperage (A) phase 3
|
||||||
|
dependencies:
|
||||||
|
- name: currentp1
|
||||||
|
check: notempty
|
||||||
|
- name: timeout
|
||||||
|
default: 30
|
||||||
|
help:
|
||||||
|
de: Akzeptiere keine Daten die älter als dieser Wert in Sekunden ist
|
||||||
|
en: Don't accept values older than this value in seconds
|
||||||
|
render: |
|
||||||
|
type: custom
|
||||||
|
power:
|
||||||
|
source: mqtt
|
||||||
|
topic: {{ .power }}
|
||||||
|
scale: {{ .scalepower }}
|
||||||
|
timeout: {{ .timeout }}
|
||||||
|
{{- if ne .energy1 "" }}
|
||||||
|
energy:
|
||||||
|
source: mqtt
|
||||||
|
topic: {{ .energy }}
|
||||||
|
scale: {{ .scaleenergy }}
|
||||||
|
timeout: {{ .timeout }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- if eq .usage "battery" }}
|
||||||
|
soc:
|
||||||
|
source: mqtt
|
||||||
|
topic: {{ .soc }}
|
||||||
|
timeout: {{ .timeout }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- if ne .currentp1 "" }}
|
||||||
|
currents:
|
||||||
|
- source: mqtt
|
||||||
|
topic: {{ .currentp1 }}
|
||||||
|
timeout: {{ .timeout }}
|
||||||
|
{{- if ne .currentp2 "" }}
|
||||||
|
- source: mqtt
|
||||||
|
topic: {{ .currentp2 }}
|
||||||
|
timeout: {{ .timeout }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- if ne .currentp3 "" }}
|
||||||
|
- source: mqtt
|
||||||
|
topic: {{ .currentp3 }}
|
||||||
|
timeout: {{ .timeout }}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: powerdog
|
template: powerdog
|
||||||
description: Powerdog
|
description:
|
||||||
|
generic: Powerdog
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: powerfox-poweropti
|
template: powerfox-poweropti
|
||||||
description: Powerfox Poweropti (Cloud)
|
description:
|
||||||
|
generic: Powerfox Poweropti (Cloud)
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: [ "grid" ]
|
choice: [ "grid" ]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: rct-power
|
template: rct-power
|
||||||
description: RCT Power
|
description:
|
||||||
|
generic: RCT Power
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: senec-home
|
template: senec-home
|
||||||
description: SENEC.Home
|
description:
|
||||||
|
generic: SENEC.Home
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: shelly-3em
|
template: shelly-3em
|
||||||
description: Shelly 3EM
|
description:
|
||||||
|
generic: Shelly 3EM
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: [ "grid" ]
|
choice: [ "grid" ]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: sma-energy-meter
|
template: sma-energy-meter
|
||||||
description: SMA Energy Meter
|
description:
|
||||||
|
generic: SMA Energy Meter (Produktname)
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: ["grid", "pv", "battery"]
|
choice: ["grid", "pv", "battery"]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: sma-home-manager
|
template: sma-home-manager
|
||||||
description: SMA Sunny Home Manager 2.0
|
description:
|
||||||
|
generic: SMA Sunny Home Manager 2.0
|
||||||
requirements:
|
requirements:
|
||||||
hems: sma
|
hems: sma
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: sma-inverter
|
template: sma-inverter
|
||||||
description: SMA Inverter/Wechselrichter
|
description:
|
||||||
|
de: SMA Wechselrichter
|
||||||
|
en: SMA Inverter
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: ["pv", "battery"]
|
choice: ["pv", "battery"]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
template: solaredge-hybrid
|
template: solaredge-hybrid
|
||||||
description: Solaredge Hybrid
|
description:
|
||||||
|
generic: Solaredge Hybrid
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
|
requirements:
|
||||||
|
description:
|
||||||
|
de: Nur ein System kann auf den Wechselrichter zugreifen!
|
||||||
|
en: Only one system may access the inverter!
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
choice: [ "grid", "pv", "battery" ]
|
choice: [ "grid", "pv", "battery" ]
|
||||||
|
|
|
||||||
17
templates/definition/meter/solaredge-inverter.yaml
Normal file
17
templates/definition/meter/solaredge-inverter.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
template: solaredge-inverter
|
||||||
|
description:
|
||||||
|
de: Solaredge Wechselrichter
|
||||||
|
en: Solaredge Inverter
|
||||||
|
guidedsetup:
|
||||||
|
enable: true
|
||||||
|
params:
|
||||||
|
- name: usage
|
||||||
|
choice: [ "pv" ]
|
||||||
|
- name: modbus
|
||||||
|
choice: [ "tcpip" ]
|
||||||
|
id: 1
|
||||||
|
port: 1502
|
||||||
|
render: |
|
||||||
|
type: modbus
|
||||||
|
model: sunspec
|
||||||
|
{{ include "modbus" . }}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: solarlog
|
template: solarlog
|
||||||
description: Solarlog
|
description:
|
||||||
|
generic: Solarlog
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: solarwatt-myreserve
|
template: solarwatt-myreserve
|
||||||
description: Solarwatt MyReserve
|
description:
|
||||||
|
generic: Solarwatt MyReserve
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: sonnenbatterie-eco10
|
template: sonnenbatterie-eco10
|
||||||
description: Sonnenbatterie Eco/10
|
description:
|
||||||
|
generic: Sonnenbatterie Eco/10
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
39
templates/definition/meter/sungrow.yaml
Normal file
39
templates/definition/meter/sungrow.yaml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
template: sungrow
|
||||||
|
description:
|
||||||
|
generic: Sungrow (Beta)
|
||||||
|
guidedsetup:
|
||||||
|
enable: true
|
||||||
|
params:
|
||||||
|
- name: usage
|
||||||
|
choice: [ "grid", "pv", "battery" ]
|
||||||
|
- name: modbus
|
||||||
|
choice: [ "rs485", "tcpip" ]
|
||||||
|
render: |
|
||||||
|
type: custom
|
||||||
|
power:
|
||||||
|
source: modbus
|
||||||
|
{{include "modbus" . | indent 2}}
|
||||||
|
register:
|
||||||
|
type: input
|
||||||
|
{{- if eq .usage "grid" }}
|
||||||
|
address: 13009 # Export power
|
||||||
|
decode: int32s
|
||||||
|
scale: -1
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .usage "pv" }}
|
||||||
|
address: 5016 # Total DC power
|
||||||
|
decode: uint32s
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .usage "battery" }}
|
||||||
|
address: 13021 # Battery power
|
||||||
|
decode: int16
|
||||||
|
#scale: -1 # charging sign form 13000 & 0x2
|
||||||
|
soc:
|
||||||
|
source: modbus
|
||||||
|
{{include "modbus" . | indent 2}}
|
||||||
|
register:
|
||||||
|
address: 13022 # Battery level
|
||||||
|
type: input
|
||||||
|
decode: int16
|
||||||
|
scale: 0.1
|
||||||
|
{{- end }}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: sunspec
|
template: sunspec
|
||||||
description: Inverter / Wechselrichter (SunSpec)
|
description:
|
||||||
|
de: Wechselrichter (SunSpec)
|
||||||
|
en: Inverter (SunSpec)
|
||||||
generic: true
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: tesla-powerwall
|
template: tesla-powerwall
|
||||||
description: Tesla Powerwall
|
description:
|
||||||
|
generic: Tesla Powerwall
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: varta-energiespeicher
|
template: varta-energiespeicher
|
||||||
description: VARTA Energiespeicher
|
description:
|
||||||
|
generic: VARTA Energiespeicher
|
||||||
guidedsetup:
|
guidedsetup:
|
||||||
enable: true
|
enable: true
|
||||||
params:
|
params:
|
||||||
|
|
|
||||||
69
templates/definition/meter/victron-energy.yaml
Normal file
69
templates/definition/meter/victron-energy.yaml
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
template: victron-energy
|
||||||
|
description:
|
||||||
|
generic: Victron Energy
|
||||||
|
guidedsetup:
|
||||||
|
enable: true
|
||||||
|
params:
|
||||||
|
- name: usage
|
||||||
|
choice: [ "grid", "pv", "battery" ]
|
||||||
|
- name: host
|
||||||
|
required: true
|
||||||
|
example: 192.0.2.2
|
||||||
|
- name: port
|
||||||
|
default: 502
|
||||||
|
render: |
|
||||||
|
type: custom
|
||||||
|
power:
|
||||||
|
{{- if eq .usage "grid" }}
|
||||||
|
source: calc
|
||||||
|
add:
|
||||||
|
- source: modbus
|
||||||
|
uri: {{ .host }}:{{ .port }}
|
||||||
|
id: 50 # com.victronenergy.grid
|
||||||
|
register:
|
||||||
|
address: 2600 # L1 grid power
|
||||||
|
type: input
|
||||||
|
decode: int16
|
||||||
|
- source: modbus
|
||||||
|
uri: {{ .host }}:{{ .port }}
|
||||||
|
id: 50 # com.victronenergy.grid
|
||||||
|
register:
|
||||||
|
address: 2601 # L2 grid power
|
||||||
|
type: input
|
||||||
|
decode: int16
|
||||||
|
- source: modbus
|
||||||
|
uri: {{ .host }}:{{ .port }}
|
||||||
|
id: 50 # com.victronenergy.grid
|
||||||
|
register:
|
||||||
|
address: 2602 # L3 grid power
|
||||||
|
type: input
|
||||||
|
decode: int16
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .usage "pv" }}
|
||||||
|
source: modbus
|
||||||
|
uri: {{ .host }}:{{ .port }}
|
||||||
|
id: 20 # com.victronenergy.pvinverter
|
||||||
|
register:
|
||||||
|
address: 1052 # Total AC Power
|
||||||
|
type: input
|
||||||
|
decode: int32
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .usage "battery" }}
|
||||||
|
source: modbus
|
||||||
|
uri: {{ .host }}:{{ .port }}
|
||||||
|
id: 100 # com.victronenergy.system
|
||||||
|
register:
|
||||||
|
address: 842 # active DC power
|
||||||
|
type: input
|
||||||
|
decode: int16
|
||||||
|
scale: -1
|
||||||
|
soc:
|
||||||
|
source: modbus
|
||||||
|
uri: {{ .host }}:{{ .port }}
|
||||||
|
id: 225 # com.victronenergy.battery
|
||||||
|
register:
|
||||||
|
address: 266 # SoC
|
||||||
|
type: input
|
||||||
|
decode: uint16
|
||||||
|
scale: 0.1
|
||||||
|
{{- end }}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: volkszaehler-http
|
template: volkszaehler-http
|
||||||
description: Volkszähler (HTTP API)
|
description:
|
||||||
|
generic: Volkszähler (HTTP API)
|
||||||
generic: true
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: volkszaehler-importexport
|
template: volkszaehler-importexport
|
||||||
description: Volkszähler (HTTP API, Import & Export)
|
description:
|
||||||
|
generic: Volkszähler (HTTP API, Import & Export)
|
||||||
generic: true
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: volkszaehler-ws
|
template: volkszaehler-ws
|
||||||
description: Volkszähler (WebSocket API)
|
description:
|
||||||
|
generic: Volkszähler (WebSocket API)
|
||||||
generic: true
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: vzlogger
|
template: vzlogger
|
||||||
description: vzlogger
|
description:
|
||||||
|
generic: vzlogger
|
||||||
generic: true
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: usage
|
- name: usage
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: audi
|
template: audi
|
||||||
description: Audi
|
description:
|
||||||
|
generic: Audi
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: bmw
|
template: bmw
|
||||||
description: BMW
|
description:
|
||||||
|
generic: BMW
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: carwings
|
template: carwings
|
||||||
description: Nissan Leaf (pre 2019)
|
description:
|
||||||
|
generic: Nissan Leaf (pre 2019)
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: citroen
|
template: citroen
|
||||||
description: Citroen
|
description:
|
||||||
|
generic: Citroen
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: dacia
|
template: dacia
|
||||||
description: Dacia
|
description:
|
||||||
|
generic: Dacia
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: ds
|
template: ds
|
||||||
description: DS
|
description:
|
||||||
|
generic: DS
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: evnotify
|
template: evnotify
|
||||||
description: evNotify
|
description:
|
||||||
|
generic: evNotify
|
||||||
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: title
|
- name: title
|
||||||
- name: akey
|
- name: akey
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: fiat
|
template: fiat
|
||||||
description: Fiat
|
description:
|
||||||
|
generic: Fiat
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- name: vin
|
- name: vin
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: ford
|
template: ford
|
||||||
description: Ford
|
description:
|
||||||
|
generic: Ford
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: hyundai
|
template: hyundai
|
||||||
description: Hyundai
|
description:
|
||||||
|
generic: Hyundai
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: kia
|
template: kia
|
||||||
description: Kia
|
description:
|
||||||
|
generic: Kia
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: mini
|
template: mini
|
||||||
description: Mini
|
description:
|
||||||
|
generic: Mini
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: nissan
|
template: nissan
|
||||||
description: Nissan
|
description:
|
||||||
|
generic: Nissan
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: niu-e-scooter
|
template: niu-e-scooter
|
||||||
description: NIU E-Scooter
|
description:
|
||||||
|
generic: NIU E-Scooter
|
||||||
params:
|
params:
|
||||||
- name: title
|
- name: title
|
||||||
- name: user
|
- name: user
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: opel
|
template: opel
|
||||||
description: Opel
|
description:
|
||||||
|
generic: Opel
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
template: ovms
|
template: ovms
|
||||||
description: Open Vehicle Monitoring System
|
description:
|
||||||
|
generic: Open Vehicle Monitoring System
|
||||||
|
generic: true
|
||||||
params:
|
params:
|
||||||
- name: title
|
- name: title
|
||||||
- name: user
|
- name: user
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: peugeot
|
template: peugeot
|
||||||
description: Peugeot
|
description:
|
||||||
|
generic: Peugeot
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: porsche
|
template: porsche
|
||||||
description: Porsche
|
description:
|
||||||
|
generic: Porsche
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: renault
|
template: renault
|
||||||
description: Renault
|
description:
|
||||||
|
generic: Renault
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
template: seat
|
template: seat
|
||||||
description: Seat (Cupra, Mii)
|
description:
|
||||||
|
generic: Seat (Cupra, Mii)
|
||||||
params:
|
params:
|
||||||
- base: vehiclebase
|
- base: vehiclebase
|
||||||
- base: vehicleidentify
|
- base: vehicleidentify
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue