Switch sockets: allow removing vehicle selection for integrated devices (#6368)

This commit is contained in:
andig 2023-02-26 13:40:15 +01:00 • committed by GitHub
parent 1d1d79bd44
commit 06a68d8c40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 427 additions and 242 deletions

View file

@ -24,12 +24,12 @@ func (c *CmdConfigure) eebusCertificate() (map[string]interface{}, error) {
cert, err := eebus.CreateCertificate()
if err != nil {
return eebusConfig, fmt.Errorf("%s", c.localizedString("Error_EEBUS_Certificate_Create", nil))
return eebusConfig, fmt.Errorf("%s", c.localizedString("Error_EEBUS_Certificate_Create"))
}
pubKey, privKey, err := eebus.GetX509KeyPair(cert)
if err != nil {
return eebusConfig, fmt.Errorf("%s", c.localizedString("Error_EEBUS_Certificate_Use", nil))
return eebusConfig, fmt.Errorf("%s", c.localizedString("Error_EEBUS_Certificate_Use"))
}
eebusConfig = map[string]interface{}{

View file

@ -88,7 +88,7 @@ func (c *CmdConfigure) configureDeviceGuidedSetup() {
}
fmt.Println()
fmt.Println(templateItem.Title() + " " + c.localizedString("Device_Added", nil))
fmt.Println(templateItem.Title() + " " + c.localizedString("Device_Added"))
c.configureLinkedTypes(templateItem)
}
@ -169,7 +169,7 @@ func (c *CmdConfigure) configureLinkedTemplate(templateItem templates.Template,
c.processDeviceCapabilities(templateItem.Capabilities)
fmt.Println()
fmt.Println(templateItem.Title() + " " + c.localizedString("Device_Added", nil))
fmt.Println(templateItem.Title() + " " + c.localizedString("Device_Added"))
return true
}
break
@ -180,7 +180,7 @@ func (c *CmdConfigure) configureLinkedTemplate(templateItem templates.Template,
// configureDeviceCategory lets the user select and configure a device from a specific category
func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (device, []string, error) {
fmt.Println()
fmt.Printf("- %s %s\n", c.localizedString("Device_Configure", nil), DeviceCategories[deviceCategory].title)
fmt.Printf("- %s %s\n", c.localizedString("Device_Configure"), DeviceCategories[deviceCategory].title)
device := device{
Name: DeviceCategories[deviceCategory].defaultName,
@ -227,7 +227,7 @@ func (c *CmdConfigure) configureDeviceCategory(deviceCategory DeviceCategory) (d
}
fmt.Println()
fmt.Println(deviceDescription + deviceTitle + " " + c.localizedString("Device_Added", nil))
fmt.Println(deviceDescription + deviceTitle + " " + c.localizedString("Device_Added"))
return device, capabilities, nil
}

View file

@ -19,7 +19,7 @@ import (
func (c *CmdConfigure) processDeviceSelection(deviceCategory DeviceCategory) (templates.Template, error) {
templateItem := c.selectItem(deviceCategory)
if templateItem.Title() == c.localizedString("ItemNotPresent", nil) {
if templateItem.Title() == c.localizedString("ItemNotPresent") {
return templateItem, c.errItemNotPresent
}
@ -123,10 +123,10 @@ func (c *CmdConfigure) processDeviceRequirements(templateItem templates.Template
if len(requirementDescription) > 0 {
fmt.Println()
fmt.Println("-------------------------------------------------")
fmt.Println(c.localizedString("Requirements_Title", nil))
fmt.Println(c.localizedString("Requirements_Title"))
fmt.Println(requirementDescription)
if len(templateItem.Requirements.URI) > 0 {
fmt.Println(" " + c.localizedString("Requirements_More", nil) + " " + templateItem.Requirements.URI)
fmt.Println(" " + c.localizedString("Requirements_More") + " " + templateItem.Requirements.URI)
}
fmt.Println("-------------------------------------------------")
}
@ -163,7 +163,7 @@ func (c *CmdConfigure) processDeviceRequirements(templateItem templates.Template
fmt.Println()
eebusConfig, err := c.eebusCertificate()
if err != nil {
return fmt.Errorf("%s: %s", c.localizedString("Requirements_EEBUS_Cert_Error", nil), err)
return fmt.Errorf("%s: %s", c.localizedString("Requirements_EEBUS_Cert_Error"), err)
}
if err := c.configureEEBus(eebusConfig); err != nil {
@ -181,7 +181,7 @@ func (c *CmdConfigure) processDeviceRequirements(templateItem templates.Template
}
fmt.Println()
fmt.Println(c.localizedString("Requirements_EEBUS_Pairing", nil))
fmt.Println(c.localizedString("Requirements_EEBUS_Pairing"))
fmt.Scanln()
}
@ -194,10 +194,10 @@ func (c *CmdConfigure) processParamRequirements(param templates.Param) error {
if len(requirementDescription) > 0 {
fmt.Println()
fmt.Println("-------------------------------------------------")
fmt.Println(c.localizedString("Requirements_Title", nil))
fmt.Println(c.localizedString("Requirements_Title"))
fmt.Println(requirementDescription)
if len(param.Requirements.URI) > 0 {
fmt.Println(" " + c.localizedString("Requirements_More", nil) + " " + param.Requirements.URI)
fmt.Println(" " + c.localizedString("Requirements_More") + " " + param.Requirements.URI)
}
fmt.Println("-------------------------------------------------")
}
@ -217,23 +217,23 @@ func (c *CmdConfigure) askSponsortoken(required, feature bool) error {
if required {
fmt.Println()
if feature {
fmt.Println(c.localizedString("Requirements_Sponsorship_Feature_Title", nil))
fmt.Println(c.localizedString("Requirements_Sponsorship_Feature_Title"))
} else {
fmt.Println(c.localizedString("Requirements_Sponsorship_Title", nil))
fmt.Println(c.localizedString("Requirements_Sponsorship_Title"))
}
} else {
fmt.Println()
fmt.Println(c.localizedString("Requirements_Sponsorship_Optional_Title", nil))
fmt.Println(c.localizedString("Requirements_Sponsorship_Optional_Title"))
}
fmt.Println()
if !c.askYesNo(c.localizedString("Requirements_Sponsorship_Token", nil)) {
if !c.askYesNo(c.localizedString("Requirements_Sponsorship_Token")) {
fmt.Println()
fmt.Println("--------------------------------------------")
return c.errItemNotPresent
}
sponsortoken := c.askValue(question{
label: c.localizedString("Requirements_Sponsorship_Token_Input", nil),
label: c.localizedString("Requirements_Sponsorship_Token_Input"),
mask: true,
required: true,
})
@ -267,29 +267,11 @@ func (c *CmdConfigure) configureMQTT(templateItem templates.Template) (map[strin
_, paramPort := templateItem.ConfigDefaults.ParamByName("port")
_, paramUser := templateItem.ConfigDefaults.ParamByName("user")
_, paramPassword := templateItem.ConfigDefaults.ParamByName("password")
host := c.askValue(question{
label: paramHost.Description.String(c.lang),
mask: false,
required: true,
})
port := c.askValue(question{
label: paramPort.Description.String(c.lang),
mask: false,
required: true,
})
user := c.askValue(question{
label: paramUser.Description.String(c.lang),
mask: false,
required: false,
})
password := c.askValue(question{
label: paramPassword.Description.String(c.lang),
mask: true,
required: false,
})
host := c.askParam(paramHost)
port := c.askParam(paramPort)
user := c.askParam(paramUser)
password := c.askParam(paramPassword)
fmt.Println()
fmt.Println("--------------------------------------------")
@ -309,7 +291,7 @@ func (c *CmdConfigure) configureMQTT(templateItem templates.Template) (map[strin
}
fmt.Println()
question := c.localizedString("TestingMQTTFailed", nil)
question := c.localizedString("TestingMQTTFailed")
if !c.askYesNo(question) {
return nil, fmt.Errorf("failed configuring mqtt: %w", err)
}
@ -392,7 +374,7 @@ func (c *CmdConfigure) paramChoiceValues(params []templates.Param, name string)
// Returns a map with param name and values
func (c *CmdConfigure) processConfig(templateItem *templates.Template, deviceCategory DeviceCategory) map[string]interface{} {
fmt.Println()
fmt.Println(c.localizedString("Config_Title", nil))
fmt.Println(c.localizedString("Config_Title"))
fmt.Println()
c.processModbusConfig(templateItem, deviceCategory)
@ -431,7 +413,7 @@ func (c *CmdConfigure) processParams(templateItem *templates.Template, deviceCat
}
switch param.Type {
case templates.ParamTypeStringList:
case templates.TypeStringList:
values := c.processListInputConfig(param)
var nonEmptyValues []string
for _, value := range values {
@ -466,7 +448,7 @@ func (c *CmdConfigure) processListInputConfig(param templates.Param) []string {
break
}
if !c.askYesNo(" " + c.localizedString("Config_AddAnotherValue", nil)) {
if !c.askYesNo(" " + c.localizedString("Config_AddAnotherValue")) {
break
}
}
@ -484,7 +466,7 @@ func (c *CmdConfigure) processInputConfig(param templates.Param) string {
help := param.Help.ShortString(c.lang)
if slices.Contains(param.Requirements.EVCC, templates.RequirementSponsorship) {
help = fmt.Sprintf("%s\n\n%s", help, c.localizedString("Requirements_Sponsorship_Feature_Title", nil))
help = fmt.Sprintf("%s\n\n%s", help, c.localizedString("Requirements_Sponsorship_Feature_Title"))
}
value := c.askValue(question{
@ -498,7 +480,7 @@ func (c *CmdConfigure) processInputConfig(param templates.Param) string {
required: param.IsRequired(),
})
if param.Type == templates.ParamTypeBool && value == "true" {
if param.Type == templates.TypeBool && value == "true" {
if err := c.processParamRequirements(param); err != nil {
return "false"
}
@ -539,7 +521,7 @@ func (c *CmdConfigure) processModbusConfig(templateItem *templates.Template, dev
// ask for modbus interface type
var index int
if len(choices) > 1 {
index, _ = c.askChoice(c.localizedString("Config_ModbusInterface", nil), choices)
index, _ = c.askChoice(c.localizedString("Config_ModbusInterface"), choices)
}
values := make(map[string]interface{})

View file

@ -71,6 +71,7 @@ Config_Yes = "Ja"
Config_No = "Nein"
Cancel = "Die Konfiguration wurde abgebrochen.\n\nFalls diese geführte Konfiguration für dich noch nicht funktioniert, versuche es doch mal mit der manuellen Konfiguration. Details findest du auf der folgenden Webseite: https://docs.evcc.io/docs/\n"
InputError = "Bei der Eingabe ist ein Fehler aufgetreten:"
Value_Choice = "Auswahl:"
Value_Help = "Hilfe:"
Value_Required = "erforderlich"
Value_Optional = "optional"

View file

@ -71,6 +71,7 @@ Config_Yes = "Yes"
Config_No = "No"
Cancel = "The configuration was cancelled.\n\nIf this guided configuration process doesn't work for you yet, please try the manual configuration. You can find more details about that on our website: https://docs.evcc.io/docs/\n"
InputError = "An input error occurred:"
Value_Choice = "Chose:"
Value_Help = "Help:"
Value_Required = "required"
Value_Optional = "optional"

View file

@ -71,14 +71,14 @@ func (c *CmdConfigure) Run(log *util.Logger, flagLang string, advancedMode, expa
c.setDefaultTexts()
fmt.Println()
fmt.Println(c.localizedString("Intro", nil))
fmt.Println(c.localizedString("Intro"))
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),
flowIndex, _ := c.askChoice(c.localizedString("Flow_Mode"), []string{
c.localizedString("Flow_Mode_Standard"),
c.localizedString("Flow_Mode_Advanced"),
})
if flowIndex == 1 {
c.advancedMode = true
@ -102,9 +102,9 @@ func (c *CmdConfigure) Run(log *util.Logger, flagLang string, advancedMode, expa
}
fmt.Println()
flowIndex, _ := c.askChoice(c.localizedString("Flow_Type", nil), []string{
c.localizedString("Flow_Type_NewConfiguration", nil),
c.localizedString("Flow_Type_SingleDevice", nil),
flowIndex, _ := c.askChoice(c.localizedString("Flow_Type"), []string{
c.localizedString("Flow_Type_NewConfiguration"),
c.localizedString("Flow_Type_SingleDevice"),
})
switch flowIndex {
case 0:
@ -117,9 +117,9 @@ func (c *CmdConfigure) Run(log *util.Logger, flagLang string, advancedMode, expa
// configureSingleDevice implements the flow for getting a single device configuration
func (c *CmdConfigure) flowSingleDevice(category DeviceCategory) {
fmt.Println()
fmt.Println(c.localizedString("Flow_SingleDevice_Setup", nil))
fmt.Println(c.localizedString("Flow_SingleDevice_Setup"))
fmt.Println()
fmt.Println(c.localizedString("Flow_SingleDevice_Select", nil))
fmt.Println(c.localizedString("Flow_SingleDevice_Select"))
// only consider the device categories that are marked for this flow
categoryChoices := []string{
@ -133,7 +133,7 @@ func (c *CmdConfigure) flowSingleDevice(category DeviceCategory) {
if category == "" {
fmt.Println()
_, categoryTitle := c.askChoice(c.localizedString("Flow_SingleDevice_Select", nil), categoryChoices)
_, categoryTitle := c.askChoice(c.localizedString("Flow_SingleDevice_Select"), categoryChoices)
for item, data := range DeviceCategories {
if data.title == categoryTitle {
@ -160,9 +160,9 @@ func (c *CmdConfigure) flowSingleDevice(category DeviceCategory) {
// configureNewConfigFile implements the flow for creating a new configuration file
func (c *CmdConfigure) flowNewConfigFile() {
fmt.Println()
fmt.Println(c.localizedString("Flow_NewConfiguration_Setup", nil))
fmt.Println(c.localizedString("Flow_NewConfiguration_Setup"))
fmt.Println()
fmt.Println(c.localizedString("Flow_NewConfiguration_Select", localizeMap{"ItemNotPresent": c.localizedString("ItemNotPresent", nil)}))
fmt.Println(c.localizedString("Flow_NewConfiguration_Select", localizeMap{"ItemNotPresent": c.localizedString("ItemNotPresent")}))
c.configureDeviceGuidedSetup()
_ = c.configureDevices(DeviceCategoryGridMeter, true, false)
@ -207,7 +207,7 @@ func (c *CmdConfigure) flowNewConfigFile() {
}
filename = c.askValue(question{
label: c.localizedString("File_NewFilename", nil),
label: c.localizedString("File_NewFilename"),
exampleValue: "evcc_neu.yaml",
required: true,
})
@ -276,10 +276,10 @@ func (c *CmdConfigure) configureSMAHems() {
}
fmt.Println()
fmt.Println(c.localizedString("Flow_SMAHems_Setup", nil))
fmt.Println(c.localizedString("Flow_SMAHems_Setup"))
fmt.Println()
if !c.askYesNo(c.localizedString("Flow_SMAHems_Add", nil)) {
if !c.askYesNo(c.localizedString("Flow_SMAHems_Add")) {
return
}
@ -290,13 +290,13 @@ func (c *CmdConfigure) configureSMAHems() {
// configureLoadpoints asks loadpoint specific questions
func (c *CmdConfigure) configureLoadpoints() {
fmt.Println()
fmt.Println(c.localizedString("Loadpoint_Setup", nil))
fmt.Println(c.localizedString("Loadpoint_Setup"))
for {
loadpointTitle := c.askValue(question{
label: c.localizedString("Loadpoint_Title", nil),
defaultValue: c.localizedString("Loadpoint_DefaultTitle", nil),
label: c.localizedString("Loadpoint_Title"),
defaultValue: c.localizedString("Loadpoint_DefaultTitle"),
required: true,
})
loadpoint := loadpoint{
@ -314,7 +314,7 @@ func (c *CmdConfigure) configureLoadpoints() {
loadpoint.Charger = charger.Name
if !chargerHasMeter {
if c.askYesNo(c.localizedString("Loadpoint_WallboxWOMeter", nil)) {
if c.askYesNo(c.localizedString("Loadpoint_WallboxWOMeter")) {
chargeMeter, _, err := c.configureDeviceCategory(DeviceCategoryChargeMeter)
if err == nil {
loadpoint.ChargeMeter = chargeMeter.Name
@ -326,7 +326,7 @@ func (c *CmdConfigure) configureLoadpoints() {
vehicles := c.configuration.DevicesOfClass(templates.Vehicle)
if len(vehicles) > 0 {
fmt.Println()
if c.askYesNo(c.localizedString("Loadpoint_VehicleDisableAutoDetection", nil)) {
if c.askYesNo(c.localizedString("Loadpoint_VehicleDisableAutoDetection")) {
if len(vehicles) == 1 {
loadpoint.Vehicle = vehicles[0].Name
} else {
@ -337,7 +337,7 @@ func (c *CmdConfigure) configureLoadpoints() {
vehicleTitles = append(vehicleTitles, vehicle.Title)
}
vehicleIndex, _ := c.askChoice(c.localizedString("Loadpoint_VehicleSelection", nil), vehicleTitles)
vehicleIndex, _ := c.askChoice(c.localizedString("Loadpoint_VehicleSelection"), vehicleTitles)
loadpoint.Vehicle = vehicles[vehicleIndex].Name
}
}
@ -351,16 +351,16 @@ func (c *CmdConfigure) configureLoadpoints() {
if c.advancedMode {
fmt.Println()
minAmperage := c.askValue(question{
label: c.localizedString("Loadpoint_WallboxMinAmperage", nil),
valueType: templates.ParamTypeNumber,
label: c.localizedString("Loadpoint_WallboxMinAmperage"),
valueType: templates.TypeNumber,
minNumberValue: int64(minValue),
maxNumberValue: 32,
required: true,
})
loadpoint.MinCurrent, _ = strconv.Atoi(minAmperage)
maxAmperage := c.askValue(question{
label: c.localizedString("Loadpoint_WallboxMaxAmperage", nil),
valueType: templates.ParamTypeNumber,
label: c.localizedString("Loadpoint_WallboxMaxAmperage"),
valueType: templates.TypeNumber,
minNumberValue: 6,
maxNumberValue: 32,
required: true,
@ -370,18 +370,18 @@ func (c *CmdConfigure) configureLoadpoints() {
if !chargerHasMeter {
phaseChoices := []string{"1", "2", "3"}
fmt.Println()
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases", nil), phaseChoices)
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases"), phaseChoices)
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),
c.localizedString("Loadpoint_WallboxPower36kW"),
c.localizedString("Loadpoint_WallboxPower11kW"),
c.localizedString("Loadpoint_WallboxPower22kW"),
c.localizedString("Loadpoint_WallboxPowerOther"),
}
fmt.Println()
powerIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxMaxPower", nil), powerChoices)
powerIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxMaxPower"), powerChoices)
loadpoint.MinCurrent = minValue
switch powerIndex {
case 0:
@ -401,8 +401,8 @@ func (c *CmdConfigure) configureLoadpoints() {
}
case 3:
amperage := c.askValue(question{
label: c.localizedString("Loadpoint_WallboxMaxAmperage", nil),
valueType: templates.ParamTypeNumber,
label: c.localizedString("Loadpoint_WallboxMaxAmperage"),
valueType: templates.TypeNumber,
minNumberValue: int64(minValue),
maxNumberValue: 32,
required: true,
@ -412,24 +412,24 @@ func (c *CmdConfigure) configureLoadpoints() {
if !chargerHasMeter {
phaseChoices := []string{"1", "2", "3"}
fmt.Println()
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases", nil), phaseChoices)
phaseIndex, _ := c.askChoice(c.localizedString("Loadpoint_WallboxPhases"), phaseChoices)
loadpoint.Phases = phaseIndex + 1
}
}
}
fmt.Println()
loadpoint.Mode = c.askValue(question{valueType: templates.ParamTypeChargeModes, excludeNone: true})
loadpoint.Mode = c.askValue(question{valueType: templates.TypeChargeModes, excludeNone: true})
fmt.Println()
loadpoint.ResetOnDisconnect = c.askValue(question{
label: c.localizedString("Loadpoint_ResetOnDisconnect", nil),
valueType: templates.ParamTypeBool,
label: c.localizedString("Loadpoint_ResetOnDisconnect"),
valueType: templates.TypeBool,
})
c.configuration.AddLoadpoint(loadpoint)
fmt.Println()
if !c.askYesNo(c.localizedString("Loadpoint_AddAnother", nil)) {
if !c.askYesNo(c.localizedString("Loadpoint_AddAnother")) {
break
}
}
@ -438,11 +438,11 @@ func (c *CmdConfigure) configureLoadpoints() {
// configureSite asks site specific questions
func (c *CmdConfigure) configureSite() {
fmt.Println()
fmt.Println(c.localizedString("Site_Setup", nil))
fmt.Println(c.localizedString("Site_Setup"))
siteTitle := c.askValue(question{
label: c.localizedString("Site_Title", nil),
defaultValue: c.localizedString("Site_DefaultTitle", nil),
label: c.localizedString("Site_Title"),
defaultValue: c.localizedString("Site_DefaultTitle"),
required: true,
})
c.configuration.config.Site.Title = siteTitle

View file

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/AlecAivazis/survey/v2"
@ -24,10 +25,10 @@ func (c *CmdConfigure) surveyAskOne(p survey.Prompt, response interface{}, opts
if err != nil {
if err == terminal.InterruptErr {
fmt.Println(c.localizedString("Cancel", nil))
fmt.Println(c.localizedString("Cancel"))
os.Exit(0)
}
fmt.Printf("%s %s\n", c.localizedString("InputError", nil), err)
fmt.Printf("%s %s\n", c.localizedString("InputError"), err)
}
return err
@ -36,7 +37,7 @@ func (c *CmdConfigure) surveyAskOne(p survey.Prompt, response interface{}, opts
// askConfigFailureNextStep asks the user if he/she wants to select another device because the current does not work, or continue
func (c *CmdConfigure) askConfigFailureNextStep() bool {
fmt.Println()
return c.askYesNo(c.localizedString("TestingDevice_RepeatStep", nil))
return c.askYesNo(c.localizedString("TestingDevice_RepeatStep"))
}
// select item from list
@ -55,7 +56,7 @@ func (c *CmdConfigure) askSelection(message string, items []string) (string, int
// selectItem selects item from list
func (c *CmdConfigure) selectItem(deviceCategory DeviceCategory) templates.Template {
var emptyItem templates.Template
emptyItem.SetTitle(c.localizedString("ItemNotPresent", nil))
emptyItem.SetTitle(c.localizedString("ItemNotPresent"))
elements := c.fetchElements(deviceCategory)
elements = append(elements, emptyItem)
@ -67,7 +68,7 @@ func (c *CmdConfigure) selectItem(deviceCategory DeviceCategory) templates.Templ
}
}
text := fmt.Sprintf("%s %s %s:", c.localizedString("Choose", nil), DeviceCategories[deviceCategory].article, DeviceCategories[deviceCategory].title)
text := fmt.Sprintf("%s %s %s:", c.localizedString("Choose"), DeviceCategories[deviceCategory].article, DeviceCategories[deviceCategory].title)
_, selected, err := c.askSelection(text, items)
if err != nil {
c.log.FATAL.Fatal(err)
@ -105,7 +106,7 @@ type question struct {
defaultValue, exampleValue string
invalidValues []string
validValues []string
valueType string
valueType templates.ParamType
minNumberValue, maxNumberValue int64
mask, required bool
excludeNone bool
@ -113,21 +114,39 @@ type question struct {
// askBoolValue asks for a boolean value selection for a given question
func (c *CmdConfigure) askBoolValue(label string) string {
choices := []string{c.localizedString("Config_No", nil), c.localizedString("Config_Yes", nil)}
choices := []string{c.localizedString("Config_No"), c.localizedString("Config_Yes")}
values := []string{"false", "true"}
index, _ := c.askChoice(label, choices)
return values[index]
}
func (c *CmdConfigure) askParam(p templates.Param) string {
var mask, required bool
if p.Mask != nil {
mask = *p.Mask
}
if p.Required != nil {
required = *p.Required
}
return c.askValue(question{
label: p.Description.String(c.lang),
valueType: p.Type,
validValues: p.Choice, // TODO proper choice handling
mask: mask,
required: required,
})
}
// askValue asks for value input for a given question (template param)
func (c *CmdConfigure) askValue(q question) string {
if q.valueType == templates.ParamTypeBool {
if q.valueType == templates.TypeBool {
label := q.label
if q.help != "" {
helpDescription := stripmd.Strip(q.help)
fmt.Println("-------------------------------------------------")
fmt.Println(c.localizedString("Value_Help", nil))
fmt.Println(c.localizedString("Value_Help"))
fmt.Println(helpDescription)
fmt.Println("-------------------------------------------------")
}
@ -135,51 +154,57 @@ func (c *CmdConfigure) askValue(q question) string {
return c.askBoolValue(label)
}
if q.valueType == templates.ParamTypeChargeModes {
if q.valueType == templates.TypeChoice {
label := strings.TrimSpace(strings.Join([]string{q.label, c.localizedString("Value_Choice")}, " "))
idx, _ := c.askChoice(label, q.validValues)
return q.validValues[idx]
}
if q.valueType == templates.TypeChargeModes {
chargingModes := []string{string(api.ModeOff), string(api.ModeNow), string(api.ModeMinPV), string(api.ModePV)}
chargeModes := []string{
c.localizedString("ChargeModeOff", nil),
c.localizedString("ChargeModeNow", nil),
c.localizedString("ChargeModeMinPV", nil),
c.localizedString("ChargeModePV", nil),
c.localizedString("ChargeModeOff"),
c.localizedString("ChargeModeNow"),
c.localizedString("ChargeModeMinPV"),
c.localizedString("ChargeModePV"),
}
if !q.excludeNone {
chargingModes = append(chargingModes, "")
chargeModes = append(chargeModes, c.localizedString("ChargeModeNone", nil))
chargeModes = append(chargeModes, c.localizedString("ChargeModeNone"))
}
modeChoice, _ := c.askChoice(c.localizedString("ChargeMode_Question", nil), chargeModes)
modeChoice, _ := c.askChoice(c.localizedString("ChargeMode_Question"), chargeModes)
return chargingModes[modeChoice]
}
validate := func(val interface{}) error {
value := val.(string)
if q.invalidValues != nil && slices.Contains(q.invalidValues, value) {
return errors.New(c.localizedString("ValueError_Used", nil))
return errors.New(c.localizedString("ValueError_Used"))
}
if q.validValues != nil && !slices.Contains(q.validValues, value) {
return errors.New(c.localizedString("ValueError_Invalid", nil))
return errors.New(c.localizedString("ValueError_Invalid"))
}
if q.required && len(value) == 0 {
return errors.New(c.localizedString("ValueError_Empty", nil))
return errors.New(c.localizedString("ValueError_Empty"))
}
if !q.required && len(value) == 0 {
return nil
}
if q.valueType == templates.ParamTypeFloat {
if q.valueType == templates.TypeFloat {
_, err := strconv.ParseFloat(value, 64)
if err != nil {
return errors.New(c.localizedString("ValueError_Float", nil))
return errors.New(c.localizedString("ValueError_Float"))
}
}
if q.valueType == templates.ParamTypeNumber {
if q.valueType == templates.TypeNumber {
intValue, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return errors.New(c.localizedString("ValueError_Number", nil))
return errors.New(c.localizedString("ValueError_Number"))
}
if q.minNumberValue != 0 && intValue < q.minNumberValue {
return errors.New(c.localizedString("ValueError_NumberLowerThanMin", localizeMap{"Min": q.minNumberValue}))
@ -189,10 +214,10 @@ func (c *CmdConfigure) askValue(q question) string {
}
}
if q.valueType == templates.ParamTypeDuration {
if q.valueType == templates.TypeDuration {
_, err := time.ParseDuration(value)
if err != nil {
return errors.New(c.localizedString("ValueError_Duration", nil))
return errors.New(c.localizedString("ValueError_Duration"))
}
}
@ -201,12 +226,12 @@ func (c *CmdConfigure) askValue(q question) string {
help := q.help
if q.required {
help += " (" + c.localizedString("Value_Required", nil) + ")"
help += " (" + c.localizedString("Value_Required") + ")"
} else {
help += " (" + c.localizedString("Value_Optional", nil) + ")"
help += " (" + c.localizedString("Value_Optional") + ")"
}
if q.exampleValue != "" {
help += fmt.Sprintf(" ("+c.localizedString("Value_Sample", nil)+": %s)", q.exampleValue)
help += fmt.Sprintf(" ("+c.localizedString("Value_Sample")+": %s)", q.exampleValue)
}
var prompt survey.Prompt

View file

@ -8,8 +8,8 @@ import (
// setDefaultTexts sets default language specific texts
func (c *CmdConfigure) setDefaultTexts() {
c.errItemNotPresent = errors.New(c.localizedString("Error_ItemNotPresent", nil))
c.errDeviceNotValid = errors.New(c.localizedString("Error_DeviceNotValid", nil))
c.errItemNotPresent = errors.New(c.localizedString("Error_ItemNotPresent"))
c.errDeviceNotValid = errors.New(c.localizedString("Error_DeviceNotValid"))
c.updateDeviceCategoryTexts(DeviceCategoryCharger, "Category_ChargerTitle", "Category_ChargerArticle", "Category_ChargerAdditional")
c.updateDeviceCategoryTexts(DeviceCategoryGuidedSetup, "Category_SystemTitle", "Category_SystemArticle", "Category_SystemAdditional")
@ -23,14 +23,18 @@ func (c *CmdConfigure) setDefaultTexts() {
// updateDeviceCategoryTexts updates the texts for a device category
func (c *CmdConfigure) updateDeviceCategoryTexts(category DeviceCategory, title, article, additional string) {
data := DeviceCategories[category]
data.title = c.localizedString(title, nil)
data.article = c.localizedString(article, nil)
data.additional = c.localizedString(additional, nil)
data.title = c.localizedString(title)
data.article = c.localizedString(article)
data.additional = c.localizedString(additional)
DeviceCategories[category] = data
}
// localizedString is a helper for getting a localized string
func (c *CmdConfigure) localizedString(key string, templateData localizeMap) string {
func (c *CmdConfigure) localizedString(key string, data ...localizeMap) string {
var templateData localizeMap
if len(data) == 1 {
templateData = data[0]
}
return c.localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: key,
TemplateData: templateData,

View file

@ -14,13 +14,9 @@ params:
mask: true
- name: ain
required: true
mask: true
example: "307788992233"
help:
en: The AIN is printed on the type label on the back of the device. Embed it in double quotes in case of leading zeroes.
de: Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.
- name: standbypower
default: 15
- preset: switchsocket
render: |
type: fritzdect
uri: {{ .uri }}

View file

@ -28,7 +28,7 @@ params:
mask: true
- name: meterchannel
default: 6
type: int
type: number
required: true
advanced: true
description:
@ -39,7 +39,7 @@ params:
de: Kanalnummer des Messwertkanals, wie im CCU Webfrontend angezeigt.
- name: switchchannel
default: 3
type: int
type: number
required: true
advanced: true
description:
@ -48,6 +48,7 @@ params:
help:
en: Homematic switch actor channel number like shown in the CCU web user interface.
de: Kanalnummer der schaltbaren Steckdose, wie im CCU Webfrontend angezeigt.
- preset: switchsocket
render: |
type: homematic
uri: {{ .host }}:{{ .port }}

View file

@ -44,7 +44,7 @@ params:
example: EVB-P12354
- name: connector
default: 1
type: int
type: number
advanced: true
help:
en: Connector number, usually 1 for first connector.

View file

@ -11,10 +11,11 @@ params:
default: 0
- name: standbypower
default: 15
- preset: switchsocket
render: |
type: shelly
uri: http://{{ .host }}
{{ if ne .user "" }}user: {{ .user }}{{ end }}
{{ if ne .password "" }}password: {{ .password }}{{ end }}
channel: {{ .channel }} # shelly device relay channel
{{ if ne .password "" }}password: {{ .password }}{{ end }}
channel: {{ .channel }} # shelly device relay channel
standbypower: {{ .standbypower }}

View file

@ -13,6 +13,7 @@ params:
mask: true
- name: standbypower
default: 15
- preset: switchsocket
render: |
type: tapo
uri: http://{{ .host }}

View file

@ -17,13 +17,14 @@ params:
default: 1
required: true
description:
de: Nummer des Schalt-Kanals
de: Nummer des Schaltkanals
en: Device relay channel number
help:
de: Nummer des Schalt-Kanals (1-8), bei Geräten mit mehr als einem Schalter
de: Nummer des Schaltkanals (1-8), bei Geräten mit mehr als einem Schalter
en: Device relay channel number (allowed range 1-8)
- name: standbypower
default: 15
- preset: switchsocket
render: |
type: tasmota
uri: http://{{ .host }}

View file

@ -8,6 +8,7 @@ params:
- name: host
- name: standbypower
default: 15
- preset: switchsocket
render: |
type: tplink
uri: {{ .host }}

View file

@ -13,11 +13,11 @@ params:
type: number
- name: modbusdevice
description:
de: Geräteadresse
en: Device address
de: Gerätename
en: Device name
help:
de: USB-RS485 Adapter Adresse
en: USB-RS485 Adapter address
de: USB-RS485 Gerätename
en: USB-RS485 device name
example: /dev/ttyUSB0
- name: modbusbaudrate
description:
@ -33,7 +33,7 @@ params:
de: ComSet
en: ComSet
help:
de: Kommunikationsparameter für den Adapter
de: Kommunikationsparameter des Adapters
en: Communication parameter for the adapter
default: 8N1
- name: host
@ -248,29 +248,46 @@ params:
de: Icon
en: Icon
help:
de: "Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater"
en: "Visible in UI. Possible values: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater"
de: "Icon in der Benutzeroberfläche"
en: "Icon as shown in user interface"
type: choice
validvalues:
[
"bike",
"bus",
"car",
"heater",
"heatercooler",
"heatpump",
"moped",
"motorcycle",
"plug",
"scooter",
"tractor",
"van",
"waterheater",
]
- bike
- bus
- car
- heater
- heatercooler
- heatpump
- moped
- motorcycle
- plug
- scooter
- tractor
- van
- waterheater
- name: ski
required: true
description:
en: Subject Key Identifier (SKI)
de: Identifikationsschlüssel (SKI)
help:
en: The SKI of the wallbox, can usually be found on the web interface of the wallbox
de: Die SKI der Wallbox, ist üblicherweise im Web Interface der Wallbox zu finden
en: The SKI of the wallbox, usually found on the web interface of the wallbox
de: Die SKI der Wallbox, üblicherweise im Web Interface der Wallbox zu finden
- name: uri
description:
generic: URI
help:
en: HTTP(S) address
de: HTTP(S) Adresse
- name: ain
mask: true
example: "307788992233"
description:
en: Actor Identification Number (AIN)
de: Aktoridentifikationsnummer (AIN)
help:
en: The AIN is printed on the type label on the back of the device. Embed it in double quotes in case of leading zeroes.
de: Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.
presets:
vehiclebase:
@ -389,6 +406,19 @@ presets:
ski: {{ .ski }}
{{ if ne .ip "" }}ip: {{ .ip }}{{ end }}
{{end}}
switchsocket:
params:
- name: integrateddevice
type: bool
advanced: true
description:
de: Integriertes Gerät (keine Fahrzeugverbindung)
en: Integrated device (no vehicle connection)
- name: icon
advanced: true
render: |
{{ if eq .integrateddevice "true" }}features: ["integrateddevice"]{{ end }}
{{ if ne .icon "" }}icon: {{ .icon }}{{ end }}
modbus:
interfaces:

View file

@ -16,11 +16,6 @@ params:
mask: true
- name: ain
required: true
mask: true
example: "307788992233"
help:
en: The AIN is printed on the type label on the back of the device. Embed it in double quotes in case of leading zeroes.
de: Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.
render: |
type: fritzdect
uri: {{ .uri }}

View file

@ -23,7 +23,7 @@ params:
mask: true
- name: meterchannel
default: 6
type: int
type: number
required: true
advanced: true
description:

View file

@ -7,5 +7,5 @@ render:
- default: |
type: template
template: eebus
ski: # Die SKI der Wallbox, ist üblicherweise im Web Interface der Wallbox zu finden
ski: # Die SKI der Wallbox, üblicherweise im Web Interface der Wallbox zu finden
ip: 192.0.2.2 # IP-Adresse # Optional

View file

@ -14,5 +14,5 @@ render:
- default: |
type: template
template: elliconnect
ski: # Die SKI der Wallbox, ist üblicherweise im Web Interface der Wallbox zu finden
ski: # Die SKI der Wallbox, üblicherweise im Web Interface der Wallbox zu finden
ip: 192.0.2.2 # IP-Adresse

View file

@ -14,5 +14,5 @@ render:
- default: |
type: template
template: ellipro
ski: # Die SKI der Wallbox, ist üblicherweise im Web Interface der Wallbox zu finden
ski: # Die SKI der Wallbox, üblicherweise im Web Interface der Wallbox zu finden
ip: 192.0.2.2 # IP-Adresse

View file

@ -6,8 +6,18 @@ render:
- default: |
type: template
template: fritzdect
uri: https://fritz.box # Optional
uri: https://fritz.box # HTTP(S) Adresse # Optional
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.)
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
ain: 307788992233 # Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
advanced: |
type: template
template: fritzdect
uri: https://fritz.box # HTTP(S) Adresse # Optional
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.)
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
ain: 307788992233 # Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
integrateddevice: # Optional
icon: # Icon in der Benutzeroberfläche # Optional

View file

@ -22,3 +22,5 @@ render:
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) # Optional
meterchannel: 6 # Kanalnummer des Messwertkanals, wie im CCU Webfrontend angezeigt.
switchchannel: 3 # Kanalnummer der schaltbaren Steckdose, wie im CCU Webfrontend angezeigt.
integrateddevice: # Optional
icon: # Icon in der Benutzeroberfläche # Optional

View file

@ -7,5 +7,5 @@ render:
- default: |
type: template
template: pmcc
ski: # Die SKI der Wallbox, ist üblicherweise im Web Interface der Wallbox zu finden
ski: # Die SKI der Wallbox, üblicherweise im Web Interface der Wallbox zu finden
ip: 192.0.2.2 # IP-Adresse # Optional

View file

@ -6,5 +6,5 @@ render:
- default: |
type: template
template: pmcp
ski: # Die SKI der Wallbox, ist üblicherweise im Web Interface der Wallbox zu finden
ski: # Die SKI der Wallbox, üblicherweise im Web Interface der Wallbox zu finden
ip: 192.0.2.2 # IP-Adresse # Optional

View file

@ -10,3 +10,13 @@ render:
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) # Optional
channel: 0 # Optional
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
advanced: |
type: template
template: shelly
host: 192.0.2.2 # IP-Adresse oder Hostname
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.) # Optional
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) # Optional
channel: 0 # Optional
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
integrateddevice: # Optional
icon: # Icon in der Benutzeroberfläche # Optional

View file

@ -10,3 +10,12 @@ render:
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.)
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
advanced: |
type: template
template: tapo
host: 192.0.2.2 # IP-Adresse oder Hostname
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.)
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
integrateddevice: # Optional
icon: # Icon in der Benutzeroberfläche # Optional

View file

@ -8,5 +8,15 @@ render:
host: 192.0.2.2 # IP-Adresse oder Hostname
user: # Standard-User ist admin # Optional
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) # Optional
channel: 1 # Nummer des Schalt-Kanals (1-8), bei Geräten mit mehr als einem Schalter
channel: 1 # Nummer des Schaltkanals (1-8), bei Geräten mit mehr als einem Schalter
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
advanced: |
type: template
template: tasmota
host: 192.0.2.2 # IP-Adresse oder Hostname
user: # Standard-User ist admin # Optional
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen) # Optional
channel: 1 # Nummer des Schaltkanals (1-8), bei Geräten mit mehr als einem Schalter
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
integrateddevice: # Optional
icon: # Icon in der Benutzeroberfläche # Optional

View file

@ -8,3 +8,10 @@ render:
template: tplink
host: 192.0.2.2 # IP-Adresse oder Hostname
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
advanced: |
type: template
template: tplink
host: 192.0.2.2 # IP-Adresse oder Hostname
standbypower: 15 # Leistung oberhalb des angegebenen Wertes wird als Ladeleistung gewertet # Optional
integrateddevice: # Optional
icon: # Icon in der Benutzeroberfläche # Optional

View file

@ -8,7 +8,7 @@ render:
type: template
template: fritzdect
usage: pv
uri: https://fritz.box # Optional
uri: https://fritz.box # HTTP(S) Adresse # Optional
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.)
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
ain: 307788992233 # Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.
@ -17,7 +17,7 @@ render:
type: template
template: fritzdect
usage: charge
uri: https://fritz.box # Optional
uri: https://fritz.box # HTTP(S) Adresse # Optional
user: # Benutzerkonto (bspw. E-Mail Adresse, User Id, etc.)
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
ain: 307788992233 # Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt. Bei führenden Nullen bitte in doppelte Hochkommata setzen.

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: WAUZZZ... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: WBMW... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 27.4 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: WAUZZZ... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -17,7 +17,7 @@ render:
token:
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional
targetSoc: 80 # Bis zu welchem Ladestand (Soc) soll das Fahrzeug geladen werden # Optional

View file

@ -19,7 +19,7 @@ render:
vin: ZFAE... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
pin: # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional

View file

@ -18,7 +18,7 @@ render:
vin: WF0FXX... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -20,7 +20,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
language: en # 'de' für Deutsch und 'en' für Englisch # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional

View file

@ -21,7 +21,7 @@ render:
vin: WVWZZZ... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -20,7 +20,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
language: en # 'de' für Deutsch und 'en' für Englisch # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional

View file

@ -18,7 +18,7 @@ render:
vin: WBMW... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -11,7 +11,7 @@ render:
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
serial:
capacity: 4 # Akkukapazität in kWh # Optional
icon: scooter # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: scooter # Icon in der Benutzeroberfläche # Optional
advanced: |
type: template
template: niu-e-scooter
@ -20,7 +20,7 @@ render:
password: # Passwort des Benutzerkontos (bei führenden Nullen bitte in einfache Hochkommata setzen)
serial:
capacity: 4 # Akkukapazität in kWh # Optional
icon: scooter # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: scooter # Icon in der Benutzeroberfläche # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional
targetSoc: 80 # Bis zu welchem Ladestand (Soc) soll das Fahrzeug geladen werden # Optional

View file

@ -11,7 +11,7 @@ render:
type: template
template: offline
title: # Wird in der Benutzeroberfläche angezeigt # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional

View file

@ -18,7 +18,7 @@ render:
vin: WP0... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -21,7 +21,7 @@ render:
vehicleid:
capacity: 12 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional
targetSoc: 80 # Bis zu welchem Ladestand (Soc) soll das Fahrzeug geladen werden # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: WREN... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -20,5 +20,5 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: scooter # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: scooter # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 17.6 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -26,7 +26,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional
targetSoc: 80 # Bis zu welchem Ladestand (Soc) soll das Fahrzeug geladen werden # Optional

View file

@ -20,7 +20,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 10 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional
targetSoc: 80 # Bis zu welchem Ladestand (Soc) soll das Fahrzeug geladen werden # Optional

View file

@ -19,7 +19,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -18,7 +18,7 @@ render:
vin: W... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -21,7 +21,7 @@ render:
vin: WVWZZZ... # Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind # Optional
capacity: 50 # Akkukapazität in kWh # Optional
phases: 3 # Die maximale Anzahl der Phasen welche genutzt werden können # Optional
icon: car # Darstellung in der UI. Mögliche Werte: bike, bus, car, heater, heatercooler, heatpump, moped, motorcycle, plug, scooter, tractor, van, waterheater # Optional
icon: car # Icon in der Benutzeroberfläche # Optional
cache: 15m # Zeitintervall nach dem Daten erneut vom Fahrzeug abgefragt werden # Optional
mode: # Möglich sind Off, Now, MinPV und PV, oder leer wenn keiner definiert werden soll # Optional
minSoc: 25 # Ladung mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand unabhängig PV-Erzeugung, wenn der Lademodus nicht auf 'Aus' steht # Optional

View file

@ -54,13 +54,6 @@ func FromBytes(b []byte) (Template, error) {
err = tmpl.Validate()
}
// set default value type
for _, p := range tmpl.Params {
if p.Type == "" {
p.Type = ParamTypeString
}
}
return tmpl, err
}

View file

@ -0,0 +1,23 @@
package templates
type ParamType int
func (c *ParamType) UnmarshalText(text []byte) error {
typ, err := ParamTypeString(string(text))
if err == nil {
*c = typ
}
return err
}
//go:generate enumer -type ParamType -trimprefix Type
const (
TypeString ParamType = iota // default type string
TypeBool
TypeChoice
TypeChargeModes
TypeDuration
TypeFloat
TypeNumber
TypeStringList
)

View file

@ -0,0 +1,102 @@
// Code generated by "enumer -type ParamType -trimprefix Type"; DO NOT EDIT.
package templates
import (
"fmt"
"strings"
)
const _ParamTypeName = "StringBoolChoiceChargeModesDurationFloatNumberStringList"
var _ParamTypeIndex = [...]uint8{0, 6, 10, 16, 27, 35, 40, 46, 56}
const _ParamTypeLowerName = "stringboolchoicechargemodesdurationfloatnumberstringlist"
func (i ParamType) String() string {
if i < 0 || i >= ParamType(len(_ParamTypeIndex)-1) {
return fmt.Sprintf("ParamType(%d)", i)
}
return _ParamTypeName[_ParamTypeIndex[i]:_ParamTypeIndex[i+1]]
}
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
func _ParamTypeNoOp() {
var x [1]struct{}
_ = x[TypeString-(0)]
_ = x[TypeBool-(1)]
_ = x[TypeChoice-(2)]
_ = x[TypeChargeModes-(3)]
_ = x[TypeDuration-(4)]
_ = x[TypeFloat-(5)]
_ = x[TypeNumber-(6)]
_ = x[TypeStringList-(7)]
}
var _ParamTypeValues = []ParamType{TypeString, TypeBool, TypeChoice, TypeChargeModes, TypeDuration, TypeFloat, TypeNumber, TypeStringList}
var _ParamTypeNameToValueMap = map[string]ParamType{
_ParamTypeName[0:6]: TypeString,
_ParamTypeLowerName[0:6]: TypeString,
_ParamTypeName[6:10]: TypeBool,
_ParamTypeLowerName[6:10]: TypeBool,
_ParamTypeName[10:16]: TypeChoice,
_ParamTypeLowerName[10:16]: TypeChoice,
_ParamTypeName[16:27]: TypeChargeModes,
_ParamTypeLowerName[16:27]: TypeChargeModes,
_ParamTypeName[27:35]: TypeDuration,
_ParamTypeLowerName[27:35]: TypeDuration,
_ParamTypeName[35:40]: TypeFloat,
_ParamTypeLowerName[35:40]: TypeFloat,
_ParamTypeName[40:46]: TypeNumber,
_ParamTypeLowerName[40:46]: TypeNumber,
_ParamTypeName[46:56]: TypeStringList,
_ParamTypeLowerName[46:56]: TypeStringList,
}
var _ParamTypeNames = []string{
_ParamTypeName[0:6],
_ParamTypeName[6:10],
_ParamTypeName[10:16],
_ParamTypeName[16:27],
_ParamTypeName[27:35],
_ParamTypeName[35:40],
_ParamTypeName[40:46],
_ParamTypeName[46:56],
}
// ParamTypeString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func ParamTypeString(s string) (ParamType, error) {
if val, ok := _ParamTypeNameToValueMap[s]; ok {
return val, nil
}
if val, ok := _ParamTypeNameToValueMap[strings.ToLower(s)]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to ParamType values", s)
}
// ParamTypeValues returns all values of the enum
func ParamTypeValues() []ParamType {
return _ParamTypeValues
}
// ParamTypeStrings returns a slice of all String values of the enum
func ParamTypeStrings() []string {
strs := make([]string, len(_ParamTypeNames))
copy(strs, _ParamTypeNames)
return strs
}
// IsAParamType returns "true" if the value is listed in the enum definition. "false" otherwise
func (i ParamType) IsAParamType() bool {
for _, v := range _ParamTypeValues {
if i == v {
return true
}
}
return false
}

View file

@ -31,10 +31,6 @@ func (t *Template) GuidedSetupEnabled() bool {
// UpdateParamWithDefaults adds default values to specific param name entries
func (t *Template) UpdateParamsWithDefaults() error {
for i, p := range t.Params {
if p.Type == "" || (p.Type != "" && !slices.Contains(ValidParamTypes, p.Type)) {
t.Params[i].Type = ParamTypeString
}
if index, resultMapItem := t.ConfigDefaults.ParamByName(strings.ToLower(p.Name)); index > -1 {
t.Params[i].OverwriteProperties(resultMapItem)
}
@ -72,10 +68,6 @@ func (t *Template) Validate() error {
}
}
}
if p.Type != "" && !slices.Contains(ValidParamTypes, p.Type) {
return fmt.Errorf("invalid value type '%s' in template %s", p.Type, t.Template)
}
}
return nil
@ -231,7 +223,7 @@ func (t *Template) RenderProxyWithValues(values map[string]interface{}, lang str
}
switch p.Type {
case ParamTypeStringList:
case TypeStringList:
for _, e := range v.([]string) {
t.Params[index].Values = append(p.Values, yamlQuote(e))
}
@ -251,7 +243,7 @@ func (t *Template) RenderProxyWithValues(values map[string]interface{}, lang str
for _, param := range t.Params {
if !param.IsRequired() {
switch param.Type {
case ParamTypeStringList:
case TypeStringList:
if len(param.Values) == 0 {
continue
}

View file

@ -25,7 +25,7 @@ func (t *Template) RenderDocumentation(product Product, values map[string]interf
}
switch p.Type {
case ParamTypeStringList:
case TypeStringList:
for _, e := range v.([]string) {
t.Params[index].Values = append(p.Values, yamlQuote(e))
}

View file

@ -40,18 +40,6 @@ const (
TemplateRenderModeInstance = "instance"
)
const (
ParamTypeString = "string"
ParamTypeNumber = "number"
ParamTypeFloat = "float"
ParamTypeBool = "bool"
ParamTypeStringList = "stringlist"
ParamTypeChargeModes = "chargemodes"
ParamTypeDuration = "duration"
)
var ValidParamTypes = []string{ParamTypeString, ParamTypeNumber, ParamTypeFloat, ParamTypeBool, ParamTypeStringList, ParamTypeChargeModes, ParamTypeDuration}
var (
ValidModbusChoices = []string{ModbusChoiceRS485, ModbusChoiceTCPIP}
ValidUsageChoices = []string{UsageChoiceGrid, UsageChoicePV, UsageChoiceBattery, UsageChoiceCharge}
@ -197,7 +185,7 @@ type Param struct {
Value string `json:"-"` // user provided value via cli configuration
Values []string `json:",omitempty"` // user provided list of values e.g. for Type "stringlist"
Usages []string `json:",omitempty"` // restrict param to these usage types, e.g. "battery" for home battery capacity
Type string // string representation of the value type, "string" is default
Type ParamType // string representation of the value type, "string" is default
ValidValues []string `json:",omitempty"` // list of valid values the user can provide
Choice []string `json:",omitempty"` // defines a set of choices, e.g. "grid", "pv", "battery", "charge" for "usage"
AllInOne *bool `json:"-"` // defines if the defined usages can all be present in a single device
@ -213,7 +201,7 @@ type Param struct {
// return a default value or example value depending on the renderMode
func (p *Param) DefaultValue(renderMode string) interface{} {
// return empty list to allow iterating over in template
if p.Type == ParamTypeStringList {
if p.Type == TypeStringList {
return []string{}
}