diff --git a/charger/template_test.go b/charger/template_test.go index 9ef5e90d8..0fe9f053a 100644 --- a/charger/template_test.go +++ b/charger/template_test.go @@ -49,7 +49,7 @@ func TestTemplates(t *testing.T) { } else { values[templates.ModbusKeyRS485TCPIP] = true } - values = tmpl.ModbusValues(templates.TemplateRenderModeInstance, true, values) + tmpl.ModbusValues(templates.TemplateRenderModeInstance, values) } templates.RenderTest(t, tmpl, values, func(values map[string]interface{}) { diff --git a/cmd/configure/helper.go b/cmd/configure/helper.go index f809e7c24..e77155ebd 100644 --- a/cmd/configure/helper.go +++ b/cmd/configure/helper.go @@ -1,7 +1,6 @@ package configure import ( - "bufio" "fmt" "sort" "strings" @@ -15,7 +14,8 @@ import ( "gopkg.in/yaml.v3" ) -// processDeviceSelection processes the the user selected device, check if it is an actual device and make sure the requirements are set +// processDeviceSelection processes the user-selected device, checks +// if it's an actual device and makes sure the requirements are set func (c *CmdConfigure) processDeviceSelection(deviceCategory DeviceCategory) (templates.Template, error) { templateItem := c.selectItem(deviceCategory) @@ -30,7 +30,8 @@ func (c *CmdConfigure) processDeviceSelection(deviceCategory DeviceCategory) (te return templateItem, nil } -// processDeviceValues processes the user provided values, create a device configuration and check if it is a valid device +// processDeviceValues processes the user provided values, creates +// a device configuration and check if it is a valid device func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templateItem templates.Template, device device, deviceCategory DeviceCategory) (device, error) { c.addedDeviceIndex++ @@ -45,12 +46,14 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa } } - categoryWithUsage := deviceCategory == DeviceCategoryPVMeter || deviceCategory == DeviceCategoryBatteryMeter || deviceCategory == DeviceCategoryGridMeter + var categoryWithUsage bool fmt.Println() - if categoryWithUsage { + switch deviceCategory { + case DeviceCategoryPVMeter, DeviceCategoryBatteryMeter, DeviceCategoryGridMeter: + categoryWithUsage = true fmt.Println(c.localizedString("TestingDevice_TitleUsage", localizeMap{"Device": templateItem.Title(), "Usage": deviceCategory.String()})) - } else { + default: fmt.Println(c.localizedString("TestingDevice_Title", localizeMap{"Device": templateItem.Title()})) } @@ -81,24 +84,8 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa templateItem.Params = append(templateItem.Params, templates.Param{Name: "name", Value: device.Name}) if !c.expandedMode { - for index, param := range templateItem.Params { - // reduce help texts to one line and add ... - help := param.Help.String(c.lang) - if help != "" { - scanner := bufio.NewScanner(strings.NewReader(help)) - line := 0 - for scanner.Scan() { - if line == 0 { - help = scanner.Text() - } else { - help += "..." - break - } - } - if help != param.Help.String(c.lang) { - templateItem.Params[index].Help.SetString(c.lang, help) - } - } + for _, param := range templateItem.Params { + param.Help.Shorten(c.lang) } b, err := templateItem.RenderProxyWithValues(values, c.lang) @@ -115,6 +102,7 @@ func (c *CmdConfigure) processDeviceValues(values map[string]interface{}, templa templateItem.Render = fmt.Sprintf("name: {{ .name }}\n%s", templateItem.Render) } } + b, _, err := templateItem.RenderResult(templates.TemplateRenderModeInstance, values) if err != nil { c.addedDeviceIndex-- @@ -470,11 +458,7 @@ func (c *CmdConfigure) processParams(templateItem *templates.Template, deviceCat } default: - if !c.advancedMode && param.Advanced { - continue - } - - if param.Deprecated { + if param.Advanced && !c.advancedMode || param.Deprecated { continue } @@ -493,7 +477,9 @@ func (c *CmdConfigure) processParams(templateItem *templates.Template, deviceCat } } additionalConfig[param.Name] = nonEmptyValues + default: + // TODO make processInputConfig aware of default values added by template if value := c.processInputConfig(param); value != "" { additionalConfig[param.Name] = value } @@ -593,8 +579,10 @@ func (c *CmdConfigure) processModbusConfig(templateItem *templates.Template, dev values := make(map[string]interface{}) templateItem.Params[modbusIndex].Value = choiceTypes[index] + // add the interface type specific modbus params templateItem.ModbusParams(choiceTypes[index], values) - // Update the modbus default values - _ = templateItem.ModbusValues(templates.TemplateRenderModeInstance, true, values) + + // update the modbus default values + templateItem.ModbusValues(templates.TemplateRenderModeInstance, values) } diff --git a/cmd/configure/types.go b/cmd/configure/types.go index 6173e7474..d56e7bf49 100644 --- a/cmd/configure/types.go +++ b/cmd/configure/types.go @@ -57,28 +57,35 @@ type DeviceCategoryData struct { var DeviceCategories = map[DeviceCategory]DeviceCategoryData{ DeviceCategoryCharger: { class: DeviceClassCharger, - defaultName: defaultNameCharger}, + defaultName: defaultNameCharger, + }, DeviceCategoryGuidedSetup: { - class: DeviceClassMeter}, + class: DeviceClassMeter, + }, DeviceCategoryGridMeter: { class: DeviceClassMeter, categoryFilter: DeviceCategoryGridMeter, - defaultName: defaultNameGridMeter}, + defaultName: defaultNameGridMeter, + }, DeviceCategoryPVMeter: { class: DeviceClassMeter, categoryFilter: DeviceCategoryPVMeter, - defaultName: defaultNamePVMeter}, + defaultName: defaultNamePVMeter, + }, DeviceCategoryBatteryMeter: { class: DeviceClassMeter, categoryFilter: DeviceCategoryBatteryMeter, - defaultName: defaultNameBatteryMeter}, + defaultName: defaultNameBatteryMeter, + }, DeviceCategoryVehicle: { class: DeviceClassVehicle, - defaultName: defaultNameVehicle}, + defaultName: defaultNameVehicle, + }, DeviceCategoryChargeMeter: { class: DeviceClassMeter, categoryFilter: DeviceCategoryChargeMeter, - defaultName: defaultNameChargeMeter}, + defaultName: defaultNameChargeMeter, + }, } type localizeMap map[string]interface{} diff --git a/meter/template_test.go b/meter/template_test.go index 38a8d3123..1ed90dbc3 100644 --- a/meter/template_test.go +++ b/meter/template_test.go @@ -48,7 +48,7 @@ func TestTemplates(t *testing.T) { } else { values[templates.ModbusKeyRS485TCPIP] = true } - values = tmpl.ModbusValues(templates.TemplateRenderModeInstance, true, values) + tmpl.ModbusValues(templates.TemplateRenderModeInstance, values) } templates.RenderTest(t, tmpl, values, func(values map[string]interface{}) { diff --git a/util/templates/template.go b/util/templates/template.go index 35e6f4098..bafa62324 100644 --- a/util/templates/template.go +++ b/util/templates/template.go @@ -181,18 +181,6 @@ func (t *Template) Defaults(renderMode string) map[string]interface{} { return values } -// Update the default value of a param -// -// Used for modbus params, which are dynamically added after selecting the interface -func (t *Template) SetParamDefault(name string, value string) { - for i, p := range t.Params { - if p.Name == name { - t.Params[i].Default = value - return - } - } -} - // return the param with the given name func (t *Template) ParamByName(name string) (int, Param) { for i, p := range t.Params { @@ -292,7 +280,7 @@ func (t *Template) RenderResult(renderMode string, other map[string]interface{}) return nil, values, err } - values = t.ModbusValues(renderMode, false, values) + t.ModbusValues(renderMode, values) // add the common templates for _, v := range t.ConfigDefaults.Presets { diff --git a/util/templates/template_documentation.go b/util/templates/template_documentation.go index d0089ad8d..5f66f7f6a 100644 --- a/util/templates/template_documentation.go +++ b/util/templates/template_documentation.go @@ -1,12 +1,10 @@ package templates import ( - "bufio" "bytes" _ "embed" "fmt" "regexp" - "strings" "text/template" "github.com/Masterminds/sprig/v3" @@ -53,7 +51,7 @@ func (t *Template) RenderDocumentation(product Product, values map[string]interf } modbusData := map[string]interface{}{} - modbusData = t.ModbusValues(TemplateRenderModeDocs, true, modbusData) + t.ModbusValues(TemplateRenderModeDocs, modbusData) modbusOut := new(bytes.Buffer) @@ -70,31 +68,16 @@ func (t *Template) RenderDocumentation(product Product, values map[string]interf var hasAdvancedParam bool var newParams []Param for _, param := range t.Params { - // reduce help texts to one line and add ... - help := param.Help.String(lang) - if help != "" { - scanner := bufio.NewScanner(strings.NewReader(help)) - line := 0 - for scanner.Scan() { - line++ - if line == 1 { - help = scanner.Text() - } else { - help += "..." - break - } - } - if help != param.Help.String(lang) { - param.Help.SetString(lang, help) - } - } + param.Help.Shorten(lang) if param.Deprecated || param.Name == ParamUsage { continue } + if param.Advanced { hasAdvancedParam = true } + newParams = append(newParams, param) } t.Params = newParams diff --git a/util/templates/template_modbus.go b/util/templates/template_modbus.go index 6ffb64859..7f66bd7c5 100644 --- a/util/templates/template_modbus.go +++ b/util/templates/template_modbus.go @@ -34,11 +34,11 @@ func (t *Template) ModbusParams(modbusType string, values map[string]interface{} t.Params = append(modbusParams, t.Params...) } -// set the modbus values required from modbus.tpl and and the template to the render -func (t *Template) ModbusValues(renderMode string, setDefaults bool, values map[string]interface{}) map[string]interface{} { +// ModbusValues adds the values required for modbus.tpl to the value map +func (t *Template) ModbusValues(renderMode string, values map[string]interface{}) { choices := t.ModbusChoices() if len(choices) == 0 { - return values + return } // only add the template once, when testing multiple usages, it might already be present @@ -46,10 +46,6 @@ func (t *Template) ModbusValues(renderMode string, setDefaults bool, values map[ t.Render = fmt.Sprintf("%s\n%s", t.Render, modbusTmpl) } - if !setDefaults { - return values - } - modbusConfig := t.ConfigDefaults.Modbus _, modbusParam := t.ParamByName(ParamModbus) @@ -58,9 +54,20 @@ func (t *Template) ModbusValues(renderMode string, setDefaults bool, values map[ modbusInterfaces = append(modbusInterfaces, modbusConfig.Interfaces[choice]...) } + // set default interface type + if len(modbusInterfaces) == 1 { + values[ParamModbus] = modbusInterfaces[0] + } + for _, iface := range modbusInterfaces { typeParams := modbusConfig.Types[iface].Params + for _, p := range typeParams { + // don't overwrite custom values + if values[p.Name] != nil { + continue + } + values[p.Name] = p.DefaultValue(renderMode) var defaultValue string @@ -84,21 +91,13 @@ func (t *Template) ModbusValues(renderMode string, setDefaults bool, values map[ } } - if defaultValue == "" { - continue - } - - if renderMode == TemplateRenderModeInstance { - t.SetParamDefault(p.Name, defaultValue) - } else { + if defaultValue != "" { values[p.Name] = defaultValue } - } + if renderMode == TemplateRenderModeDocs { values[iface] = true } } - - return values } diff --git a/util/templates/template_types.go b/util/templates/template_types.go index be7f47ff5..f5e3cc772 100644 --- a/util/templates/template_types.go +++ b/util/templates/template_types.go @@ -1,6 +1,10 @@ package templates -import "reflect" +import ( + "bufio" + "reflect" + "strings" +) const ( ParamUsage = "usage" @@ -79,7 +83,7 @@ var predefinedTemplateProperties = []string{"type", "template", "name", ModbusKeyTCPIP, ModbusKeyRS485Serial, ModbusKeyRS485TCPIP, } -// language specific texts +// TextLanguage contains language-specific texts type TextLanguage struct { Generic string // language independent DE string // german text @@ -99,7 +103,7 @@ func (t *TextLanguage) String(lang string) string { return t.DE } -func (t *TextLanguage) SetString(lang, value string) { +func (t *TextLanguage) set(lang, value string) { switch lang { case "de": t.DE = value @@ -110,6 +114,33 @@ func (t *TextLanguage) SetString(lang, value string) { } } +// Shorten reduces help texts to one line and adds ... +func (t *TextLanguage) Shorten(lang string) { + help := t.String(lang) + if help == "" { + return + } + + scanner := bufio.NewScanner(strings.NewReader(help)) + + var line int + var short string + + for scanner.Scan() { + line++ + if line == 1 { + short = scanner.Text() + } else { + short += "..." + break + } + } + + if help != short { + t.set(lang, short) + } +} + // Update the language specific texts // // always true to always update if the new value is not empty @@ -261,7 +292,7 @@ type Product struct { // TemplateDefinition contains properties of a device template type TemplateDefinition struct { Template string - Covers []string // list of covered outdated tempate names + Covers []string // list of covered outdated template names Products []Product // list of products this template is compatible with Capabilities []string Requirements Requirements