Template improvements (#2019)
Fix #2018 - Update go-e firmware requirements - Change cfos devices not to use modbus config schema - Add support for `onIdentify` params of vehicles - Add support for `resetOnDisconnect` for loadpoints - Add support for defining device specific modbus port, baudrate and comset defaults - Handle fatal error when `evcc.yaml` exists and the process doesn't have write permissions - Some bug fixes
This commit is contained in:
parent
69c923a749
commit
96a0475390
41 changed files with 364 additions and 181 deletions
|
|
@ -16,14 +16,15 @@ type device struct {
|
|||
}
|
||||
|
||||
type loadpoint struct {
|
||||
Title string // TODO Perspektivisch können wir was aus core wiederverwenden, für später
|
||||
Charger string
|
||||
ChargeMeter string
|
||||
Vehicles []string
|
||||
Mode string
|
||||
MinCurrent int
|
||||
MaxCurrent int
|
||||
Phases int
|
||||
Title string // TODO Perspektivisch können wir was aus core wiederverwenden, für später
|
||||
Charger string
|
||||
ChargeMeter string
|
||||
Vehicles []string
|
||||
Mode string
|
||||
MinCurrent int
|
||||
MaxCurrent int
|
||||
Phases int
|
||||
ResetOnDisconnect string
|
||||
}
|
||||
|
||||
type config struct {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ loadpoints:
|
|||
phases: {{ .Phases }}
|
||||
mincurrent: {{ .MinCurrent }}
|
||||
maxcurrent: {{ .MaxCurrent }}
|
||||
resetOnDisconnect: {{ .ResetOnDisconnect }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
|
|
|||
|
|
@ -307,12 +307,21 @@ func (c *CmdConfigure) processModbusConfig(param templates.Param, deviceCategory
|
|||
|
||||
// baudrate and comset defaults can be overwritten, as they are device specific
|
||||
deviceDefaultBaudrate := templates.ModbusParamValueBaudrate
|
||||
deviceDefaultComset := templates.ModbusParamValueComset
|
||||
deviceDefaultPort := templates.ModbusParamValuePort
|
||||
deviceDefaultId := templates.ModbusParamValueId
|
||||
|
||||
if param.Baudrate != 0 {
|
||||
deviceDefaultBaudrate = param.Baudrate
|
||||
}
|
||||
deviceDefaultComset := templates.ModbusParamValueComset
|
||||
if param.Comset != "" {
|
||||
deviceDefaultBaudrate = param.Baudrate
|
||||
deviceDefaultComset = param.Comset
|
||||
}
|
||||
if param.Port != 0 {
|
||||
deviceDefaultPort = param.Port
|
||||
}
|
||||
if param.ID != 0 {
|
||||
deviceDefaultId = param.ID
|
||||
}
|
||||
|
||||
var choices []string
|
||||
|
|
@ -336,7 +345,7 @@ func (c *CmdConfigure) processModbusConfig(param templates.Param, deviceCategory
|
|||
id := c.askValue(question{
|
||||
label: "ID",
|
||||
help: "Modbus ID",
|
||||
defaultValue: 1,
|
||||
defaultValue: deviceDefaultId,
|
||||
valueType: templates.ParamValueTypeNumber,
|
||||
required: true})
|
||||
additionalConfig[templates.ModbusParamNameId] = id
|
||||
|
|
@ -383,7 +392,7 @@ func (c *CmdConfigure) processModbusConfig(param templates.Param, deviceCategory
|
|||
|
||||
port := c.askValue(question{
|
||||
label: c.localizedString("UserFriendly_Port_Name", nil),
|
||||
defaultValue: templates.ModbusParamValuePort,
|
||||
defaultValue: deviceDefaultPort,
|
||||
valueType: templates.ParamValueTypeNumber,
|
||||
required: true})
|
||||
additionalConfig[templates.ModbusParamNamePort] = port
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Error_EEBUS_Certificate_Create = "Konnte das EEBUS Zertifikat nicht erstellen"
|
|||
Error_EEBUS_Certificate_Use = "Konnte das EEBUS Zertifikat nicht verwenden"
|
||||
|
||||
File_Exists = "Die Datei {{ .FileName }} existiert bereits. Soll die Datei überschrieben werden?"
|
||||
File_Permissions = "Die Datei {{ .FileName }} existiert bereits und kann nicht überschrieben werden."
|
||||
File_NewFilename = "Bitte gib einen neuen Dateinamen an"
|
||||
File_Error_SaveFailed = "Die Konfiguration konnte nicht in der Datei {{ .FileName }} gespeichert werden"
|
||||
File_SaveSuccess = "Die Konfiguration wurde erfolgreich in der Datei {{ .FileName }} gespeichert"
|
||||
|
|
@ -45,6 +46,16 @@ UserFriendly_Password_Name = "Passwort"
|
|||
UserFriendly_Capacity_Name = "Akku-Kapazität in kWh"
|
||||
UserFriendly_Vin_Name = "Fahrzeugidentifikationsnummer"
|
||||
UserFriendly_Vin_Help = "Erforderlich, wenn mehrere Fahrzeuge des Herstellers vorhanden sind"
|
||||
UserFriendly_Cache_Name = "Cache"
|
||||
UserFriendly_Cache_Help = "Das zeitliche Interval, in welchem Daten vom Fahrzeug neu geladen werden soll"
|
||||
UserFriendly_MinSoC_Name = "Minimaler Ladestand (SoC) in %"
|
||||
UserFriendly_MinSoC_Help = "Lade sofort mit maximaler Geschwindigkeit bis zu dem angegeben Ladestand, wenn der Lademodus nicht auf 'Aus' steht"
|
||||
UserFriendly_TargetSoC_Name = "Ziel-Ladestand (SoC) in %"
|
||||
UserFriendly_TargetSoC_Help = "Bis zu welchem Ladestand (SoC) soll das Fahrzeug geladen werden"
|
||||
UserFriendly_MinCurrent_Name = "Minimale Stromstärke in Ampere (A)"
|
||||
UserFriendly_MinCurrent_Help = "Definiert die minimale Stromstärke pro angeschlossener Phase mit welcher das Fahrzeug geladen werden soll"
|
||||
UserFriendly_MaxCurrent_Name = "Maximale Stromstärke in Ampere (A)"
|
||||
UserFriendly_MaxCurrent_Help = "Definiert die maximale Stromstärke pro angeschlossener Phase mit welcher das Fahrzeug geladen werden soll"
|
||||
UserFriendly_Identifier_Name = "Identifikationsnummer"
|
||||
UserFriendly_Identifier_Help = "Kann meist erst später eingetragen werden, siehe: https://docs.evcc.io/docs/guides/vehicles/#erkennung-des-fahrzeugs-an-der-wallbox"
|
||||
UserFriendly_StandByPower_Name = "Standby-Leistung in W"
|
||||
|
|
@ -113,6 +124,8 @@ Loadpoint_Title = "Titel des Ladepunktes"
|
|||
Loadpoint_AddAnother = "Möchtest du einen weiteren Ladepunkt hinzufügen?"
|
||||
Loadpoint_DefaultTitle = "Garage"
|
||||
|
||||
Loadpoint_ResetOnDisconnect = "Soll beim Abstecken des Ladekables von einem Fahrzeug, die Lade-Standardeinstellungen wieder hergestellt werden?"
|
||||
|
||||
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_WallboxMaxAmperage = "Was ist die maximale Stromstärke, welche die Wallbox auf einer Phase zur Verfügung stellen kann?"
|
||||
|
|
@ -124,11 +137,12 @@ Loadpoint_WallboxPowerOther = "Andere Leistung"
|
|||
|
||||
Loadpoint_VehicleChargeHere = "Wird das Fahrzeug {{ .Vehicle }} hier laden?"
|
||||
|
||||
Loadpoint_DefaultChargeMode = "Was sollte der Standard-Lademodus sein, wenn ein Fahrzeug angeschlossen wird?"
|
||||
Loadpoint_ChargeModeOff = "Aus"
|
||||
Loadpoint_ChargeModeNow = "Sofort (mit größtmöglicher Leistung)"
|
||||
Loadpoint_ChargeModeMinPV = "Min+PV (mit der kleinstmöglichen Leistung, schneller wenn genügend PV Überschuss vorhanden ist)"
|
||||
Loadpoint_ChargeModePV = "PV (Nur mit PV Überschuss)"
|
||||
ChargeMode_Question = "Was sollte der Standard-Lademodus sein, wenn ein Fahrzeug angeschlossen wird?"
|
||||
ChargeModeOff = "Stop"
|
||||
ChargeModeNow = "Sofort (mit größtmöglicher Leistung)"
|
||||
ChargeModeMinPV = "Min+PV (mit der kleinstmöglichen Leistung, schneller wenn genügend PV Überschuss vorhanden ist)"
|
||||
ChargeModePV = "PV (Nur mit PV Überschuss)"
|
||||
ChargeModeNone = "Keinen (Benutzt den im Ladepunkt gesetzten Lademodus)"
|
||||
|
||||
Site_Setup = "- Standort einrichten"
|
||||
Site_Title = "Titel des Standortes"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Error_EEBUS_Certificate_Create = "Could not create the EEBUS certificate"
|
|||
Error_EEBUS_Certificate_Use = "Could not process teh generated EEBUS certificate"
|
||||
|
||||
File_Exists = "The file {{ .FileName }} already exists. Do you want to replace it?"
|
||||
File_Permissions = "The file {{ .FileName }} already exists and can not be overwritten."
|
||||
File_NewFilename = "Please provide a new filename"
|
||||
File_Error_SaveFailed = "The configuration could not be saved in the file {{ .FileName }}"
|
||||
File_SaveSuccess = "The configuration was successfully saved in the file {{ .FileName }}"
|
||||
|
|
@ -45,6 +46,16 @@ UserFriendly_Password_Name = "Password"
|
|||
UserFriendly_Capacity_Name = "Battery-Capacity in kWh"
|
||||
UserFriendly_Vin_Name = "Vehicle Identification Number"
|
||||
UserFriendly_Vin_Help = "Required if you own multiple vehicles of the same brand"
|
||||
UserFriendly_Cache_Name = "Cache"
|
||||
UserFriendly_Cache_Help = "Time interval with when data should be reloaded from the vehicle"
|
||||
UserFriendly_MinSoC_Name = "Minimum state of charge (SoC) in %"
|
||||
UserFriendly_MinSoC_Help = "Charge immediately with maximum power up to the defined state of charge, if the charge mode is not set to 'OFF'"
|
||||
UserFriendly_TargetSoC_Name = "Target state of charge (SoC) in %"
|
||||
UserFriendly_TargetSoC_Help = "Until which sate of charge (SoC) should the vehicle be charged"
|
||||
UserFriendly_MinCurrent_Name = "Minimum amperage (A)"
|
||||
UserFriendly_MinCurrent_Help = "The minimum amperage per connected phase with which the car should be charged"
|
||||
UserFriendly_MaxCurrent_Name = "Maximum amperage (A)"
|
||||
UserFriendly_MaxCurrent_Help = "The maximum amperage per connected phase with which the car shuold be charged"
|
||||
UserFriendly_Identifier_Name = "Identification"
|
||||
UserFriendly_Identifier_Help = "Mostly this can be added later, see: https://docs.evcc.io/docs/guides/vehicles/#erkennung-des-fahrzeugs-an-der-wallbox"
|
||||
UserFriendly_StandByPower_Name = "Standby power in W"
|
||||
|
|
@ -113,6 +124,8 @@ Loadpoint_Title = "Loadpoint title"
|
|||
Loadpoint_AddAnother = "Do you want to add another loadpoint?"
|
||||
Loadpoint_DefaultTitle = "Garage"
|
||||
|
||||
Loadpoint_ResetOnDisconnect = "Shall disconnecting the charging cable from the vehicle reset the charging settings to the defaults?"
|
||||
|
||||
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_WallboxMaxAmperage = "What is the maximum amperage your wallbox can provide on a single phase?"
|
||||
|
|
@ -124,11 +137,12 @@ Loadpoint_WallboxPowerOther = "Other option"
|
|||
|
||||
Loadpoint_VehicleChargeHere = "Will the vehicle {{ .Vehicle }} be charging here?"
|
||||
|
||||
Loadpoint_DefaultChargeMode = "Was sollte der Standard-Lademodus sein, wenn ein Fahrzeug angeschlossen wird?"
|
||||
Loadpoint_ChargeModeOff = "Off"
|
||||
Loadpoint_ChargeModeNow = "Now (charging with maximum power)"
|
||||
Loadpoint_ChargeModeMinPV = "Min+PV (charging with minimum power, faster if enough PV power surplus is available)"
|
||||
Loadpoint_ChargeModePV = "PV (Only with PV power surplus)"
|
||||
ChargeMode_Question = "What should be the default charging mode when a vehicle is connected?"
|
||||
ChargeModeOff = "Off"
|
||||
ChargeModeNow = "Now (charging with maximum power)"
|
||||
ChargeModeMinPV = "Min+PV (charging with minimum power, faster if enough PV power surplus is available)"
|
||||
ChargeModePV = "PV (Only with PV power surplus)"
|
||||
ChargeModeNone = "None (Use what is set at the loadpoint)"
|
||||
|
||||
Site_Setup = "- Setup site"
|
||||
Site_Title = "Site title"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/cloudfoundry/jibber_jabber"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/server"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/evcc-io/evcc/util/templates"
|
||||
|
|
@ -149,13 +148,18 @@ func (c *CmdConfigure) flowNewConfigFile() {
|
|||
filename := DefaultConfigFilename
|
||||
|
||||
for ok := true; ok; {
|
||||
_, err := os.Open(filename)
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY, 0666)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
break
|
||||
}
|
||||
|
||||
if c.askYesNo(c.localizedString("File_Exists", localizeMap{"FileName": filename})) {
|
||||
break
|
||||
file.Close()
|
||||
// in case of permission error, we can't write to the file anyway
|
||||
if os.IsPermission(err) {
|
||||
fmt.Println(c.localizedString("File_Permissions", localizeMap{"FileName": filename}))
|
||||
} else {
|
||||
if c.askYesNo(c.localizedString("File_Exists", localizeMap{"FileName": filename})) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
filename = c.askValue(question{
|
||||
|
|
@ -302,17 +306,14 @@ func (c *CmdConfigure) configureLoadpoints() {
|
|||
}
|
||||
}
|
||||
|
||||
chargingModes := []string{string(api.ModeOff), string(api.ModeNow), string(api.ModeMinPV), string(api.ModePV)}
|
||||
chargeModes := []string{
|
||||
c.localizedString("Loadpoint_ChargeModeOff", nil),
|
||||
c.localizedString("Loadpoint_ChargeModeNow", nil),
|
||||
c.localizedString("Loadpoint_ChargeModeMinPV", nil),
|
||||
c.localizedString("Loadpoint_ChargeModePV", nil),
|
||||
}
|
||||
fmt.Println()
|
||||
modeChoice, _ := c.askChoice(c.localizedString("Loadpoint_DefaultChargeMode", nil), chargeModes)
|
||||
loadpoint.Mode = chargingModes[modeChoice]
|
||||
loadpoint.Mode = c.askValue(question{valueType: templates.ParamValueTypeChargeModes, excludeNone: true})
|
||||
|
||||
fmt.Println()
|
||||
loadpoint.ResetOnDisconnect = c.askValue(question{
|
||||
label: c.localizedString("Loadpoint_ResetOnDisconnect", nil),
|
||||
valueType: templates.ParamValueTypeBool,
|
||||
})
|
||||
c.configuration.AddLoadpoint(loadpoint)
|
||||
|
||||
fmt.Println()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/AlecAivazis/survey/v2/terminal"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/util/templates"
|
||||
"github.com/thoas/go-funk"
|
||||
)
|
||||
|
|
@ -115,6 +116,7 @@ type question struct {
|
|||
invalidValues []string
|
||||
valueType string
|
||||
mask, required bool
|
||||
excludeNone bool
|
||||
}
|
||||
|
||||
// askBoolValue asks for a boolean value selection for a given question
|
||||
|
|
@ -137,6 +139,22 @@ func (c *CmdConfigure) askValue(q question) string {
|
|||
return c.askBoolValue(label)
|
||||
}
|
||||
|
||||
if q.valueType == templates.ParamValueTypeChargeModes {
|
||||
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),
|
||||
}
|
||||
if !q.excludeNone {
|
||||
chargingModes = append(chargingModes, "")
|
||||
chargeModes = append(chargeModes, c.localizedString("ChargeModeNone", nil))
|
||||
}
|
||||
modeChoice, _ := c.askChoice(c.localizedString("ChargeMode_Question", nil), chargeModes)
|
||||
return chargingModes[modeChoice]
|
||||
}
|
||||
|
||||
input := ""
|
||||
|
||||
var err error
|
||||
|
|
@ -174,7 +192,7 @@ func (c *CmdConfigure) askValue(q question) string {
|
|||
} else {
|
||||
help += " (" + c.localizedString("Value_Optional", nil) + ")"
|
||||
}
|
||||
if q.exampleValue != "" {
|
||||
if q.exampleValue != nil && q.exampleValue != "" {
|
||||
help += fmt.Sprintf(" ("+c.localizedString("Value_Sample", nil)+": %s)", q.exampleValue)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,49 +49,49 @@ func (c *CmdConfigure) userFriendlyTexts(param templates.Param) templates.Param
|
|||
result.ValueType = templates.ParamValueTypeString
|
||||
}
|
||||
|
||||
switch strings.ToLower(result.Name) {
|
||||
case "title":
|
||||
result.Name = c.localizedString("UserFriendly_Title_Name", nil)
|
||||
if result.Help.String(c.lang) == "" {
|
||||
result.Help.SetString(c.lang, c.localizedString("UserFriendly_Title_Help", nil))
|
||||
}
|
||||
case "device":
|
||||
result.Name = c.localizedString("UserFriendly_Device_Name", nil)
|
||||
case "baudrate":
|
||||
result.Name = c.localizedString("UserFriendly_Baudrate_Name", nil)
|
||||
case "comset":
|
||||
result.Name = c.localizedString("UserFriendly_ComSet_Name", nil)
|
||||
case "host":
|
||||
result.Name = c.localizedString("UserFriendly_Host_Name", nil)
|
||||
case "port":
|
||||
result.Name = c.localizedString("UserFriendly_Port_Name", nil)
|
||||
result.ValueType = templates.ParamValueTypeNumber
|
||||
case "user":
|
||||
result.Name = c.localizedString("UserFriendly_User_Name", nil)
|
||||
case "password":
|
||||
result.Name = c.localizedString("UserFriendly_Password_Name", nil)
|
||||
case "capacity":
|
||||
result.Name = c.localizedString("UserFriendly_Capacity_Name", nil)
|
||||
if result.Example == "" {
|
||||
result.Example = "41.5"
|
||||
}
|
||||
result.ValueType = templates.ParamValueTypeFloat
|
||||
case "vin":
|
||||
result.Name = c.localizedString("UserFriendly_Vin_Name", nil)
|
||||
if result.Help.String(c.lang) == "" {
|
||||
result.Help.SetString(c.lang, c.localizedString("UserFriendly_Vin_Help", nil))
|
||||
}
|
||||
case "identifiers":
|
||||
result.Name = c.localizedString("UserFriendly_Identifier_Name", nil)
|
||||
if result.Help.String(c.lang) == "" {
|
||||
result.Help.SetString(c.lang, c.localizedString("UserFriendly_Identifier_Help", nil))
|
||||
}
|
||||
case "standbypower":
|
||||
result.Name = c.localizedString("UserFriendly_StandByPower_Name", nil)
|
||||
if result.Help.String(c.lang) == "" {
|
||||
result.Help.SetString(c.lang, c.localizedString("UserFriendly_StandByPower_Help", nil))
|
||||
}
|
||||
result.ValueType = templates.ParamValueTypeNumber
|
||||
type replacements struct {
|
||||
Name string
|
||||
Help string
|
||||
Example string
|
||||
ValueType string
|
||||
}
|
||||
resultNameMap := map[string]replacements{
|
||||
"title": {Name: "UserFriendly_Title_Name", Help: "UserFriendly_Title_Help"},
|
||||
"device": {Name: "UserFriendly_Device_Name"},
|
||||
"baudrate": {Name: "UserFriendly_Baudrate_Name"},
|
||||
"comset": {Name: "UserFriendly_ComSet_Name"},
|
||||
"host": {Name: "UserFriendly_Host_Name"},
|
||||
"port": {Name: "UserFriendly_Port_Name", ValueType: templates.ParamValueTypeNumber},
|
||||
"user": {Name: "UserFriendly_User_Name"},
|
||||
"password": {Name: "UserFriendly_Password_Name"},
|
||||
"capacity": {Name: "UserFriendly_Capacity_Name", Example: "41.5", ValueType: templates.ParamValueTypeFloat},
|
||||
"vin": {Name: "UserFriendly_Vin_Name", Help: "UserFriendly_Vin_Help"},
|
||||
"cache": {Name: "UserFriendly_Cache_Name", Help: "UserFriendly_Cache_Help", Example: "5m"},
|
||||
"mode": {Name: "ChargeMode_Question", ValueType: templates.ParamValueTypeChargeModes},
|
||||
"minsoc": {Name: "UserFriendly_MinSoC_Name", Help: "UserFriendly_MinSoC_Help", Example: "25", ValueType: templates.ParamValueTypeNumber},
|
||||
"targetsoc": {Name: "UserFriendly_TargetSoC_Name", Help: "UserFriendly_TargetSoC_Help", Example: "80", ValueType: templates.ParamValueTypeNumber},
|
||||
"mincurrent": {Name: "UserFriendly_MinCurrent_Name", Help: "UserFriendly_MinCurrent_Help", Example: "6", ValueType: templates.ParamValueTypeNumber},
|
||||
"maxcurrent": {Name: "UserFriendly_MaxCurrent_Name", Help: "UserFriendly_MaxCurrent_Help", Example: "16", ValueType: templates.ParamValueTypeNumber},
|
||||
"identifiers": {Name: "UserFriendly_Identifier_Name", Help: "UserFriendly_Identifier_Help"},
|
||||
"standbypower": {Name: "UserFriendly_StandByPower_Name", Help: "UserFriendly_StandByPower_Help", ValueType: templates.ParamValueTypeNumber},
|
||||
}
|
||||
|
||||
if resultMapItem := resultNameMap[strings.ToLower(result.Name)]; resultMapItem != (replacements{}) {
|
||||
// always overwrite if defined
|
||||
if resultMapItem.Name != "" {
|
||||
result.Name = c.localizedString(resultMapItem.Name, nil)
|
||||
}
|
||||
if resultMapItem.ValueType != "" {
|
||||
result.ValueType = resultMapItem.ValueType
|
||||
}
|
||||
// only set if empty
|
||||
if result.Help.String(c.lang) == "" && resultMapItem.Help != "" {
|
||||
result.Help.SetString(c.lang, c.localizedString(resultMapItem.Help, nil))
|
||||
}
|
||||
if result.Example == "" && resultMapItem.Example != "" {
|
||||
result.Example = resultMapItem.Example
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package configure
|
||||
|
||||
import "github.com/evcc-io/evcc/util/templates"
|
||||
|
||||
const (
|
||||
DefaultConfigFilename string = "evcc.yaml"
|
||||
)
|
||||
|
|
@ -12,8 +10,6 @@ func (u UsageChoice) String() string {
|
|||
return string(u)
|
||||
}
|
||||
|
||||
var ValidModbusChoices = []string{templates.ModbusChoiceRS485, templates.ModbusChoiceTCPIP}
|
||||
|
||||
type DeviceClass string
|
||||
|
||||
func (c DeviceClass) String() string {
|
||||
|
|
@ -42,8 +38,6 @@ const (
|
|||
DeviceCategoryGuidedSetup DeviceCategory = "guided"
|
||||
)
|
||||
|
||||
var ValidUsageChoices = []DeviceCategory{DeviceCategoryGridMeter, DeviceCategoryPVMeter, DeviceCategoryBatteryMeter, DeviceCategoryChargeMeter}
|
||||
|
||||
const (
|
||||
defaultNameCharger = "wallbox"
|
||||
defaultNameGridMeter = "grid"
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ Example Use Case: With SMA Home Manager, there can be a SMA Energy Meter used fo
|
|||
- `number`: for int values
|
||||
- `float`: for float values
|
||||
- `stringlist`: for a list of strings, e.g.used for defining a list of `identifiers` for `vehicles`
|
||||
- `chargemodes`: for a selection of charge modes (including `None` which results in the param not being set)
|
||||
|
||||
### `advanced`
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ requirements:
|
|||
params:
|
||||
- name: modbus
|
||||
choice: ["rs485"]
|
||||
baudrate: 38400
|
||||
comset: "8E1"
|
||||
render: |
|
||||
type: abl
|
||||
{{include "modbus" .}}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ description: cFos PowerBrain
|
|||
requirements:
|
||||
sponsorship: true
|
||||
params:
|
||||
- name: modbus
|
||||
choice: ["tcpip"]
|
||||
- name: host
|
||||
required: true
|
||||
example: 192.0.2.2
|
||||
render: |
|
||||
type: cfos
|
||||
{{include "modbus" .}}
|
||||
uri: {{ .host }}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ template: go-e
|
|||
description: go-eCharger Home/Pro/V3
|
||||
requirements:
|
||||
description:
|
||||
en: Models Home and Pro required firmware 040.0 or later.
|
||||
de: Bei den Modellen Home und Pro ist mindestens Firmware 040.0 oder höher erforderlich.
|
||||
en: Home und PRO require firmware 040.0 or later, V3 requires firmware 052.1 or later.
|
||||
de: Home und PRO benötigen mindestens Firmware 040.0 oder neuer, V3 benötigt mindestens Firmware 052.1 oder neuer.
|
||||
uri: https://docs.evcc.io/docs/devices/chargers#go-echarger-homeprov3
|
||||
params:
|
||||
- name: host
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ requirements:
|
|||
params:
|
||||
- name: modbus
|
||||
choice: ["rs485"]
|
||||
baudrate: 19200
|
||||
comset: "8E1"
|
||||
render: |
|
||||
type: heidelberg
|
||||
{{include "modbus" .}}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
template: cfos-meter
|
||||
description: cFos PowerBrain
|
||||
description: cFos PowerBrain Meter
|
||||
requirements:
|
||||
sponsorship: true
|
||||
params:
|
||||
- name: usage
|
||||
choice: [ "charger" ]
|
||||
choice: [ "charge" ]
|
||||
- name: modbus
|
||||
choice: ["tcpip"]
|
||||
choice: [ "tcpip" ]
|
||||
port: 4702
|
||||
id: 2
|
||||
render: |
|
||||
type: cfos
|
||||
{{include "modbus" .}}
|
||||
{{ include "modbus" . }}
|
||||
|
|
|
|||
28
templates/definition/meter/fritzdect.yaml
Normal file
28
templates/definition/meter/fritzdect.yaml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
template: fritzdect
|
||||
description: FritzDECT
|
||||
params:
|
||||
- name: usage
|
||||
choice: ["pv", "charge"]
|
||||
- name: uri
|
||||
default: https://fritz.box
|
||||
- name: user
|
||||
required: true
|
||||
- name: password
|
||||
required: true
|
||||
mask: true
|
||||
- name: ain
|
||||
required: true
|
||||
mask: true
|
||||
example: '007788992233'
|
||||
help:
|
||||
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.
|
||||
- name: standbypower
|
||||
default: 15
|
||||
render: |
|
||||
type: fritzdect
|
||||
uri: {{ .uri }}
|
||||
user: {{ .user }}
|
||||
password: {{ .password }}
|
||||
ain: {{ .ain }} # switch actor identification number without blanks (see AIN number on switch sticker)
|
||||
standbypower: {{ .standbypower }} # treat as charging above this power
|
||||
|
|
@ -5,6 +5,7 @@ params:
|
|||
choice: [ "pv" ]
|
||||
- name: modbus
|
||||
choice: ["rs485"]
|
||||
baudrate: 19200
|
||||
render: |
|
||||
type: custom
|
||||
power:
|
||||
|
|
|
|||
|
|
@ -3,17 +3,15 @@ description: Kostal Piko (BA) Energy Meter
|
|||
params:
|
||||
- name: usage
|
||||
choice: [ "grid" ]
|
||||
- name: host
|
||||
example: 192.0.2.2
|
||||
required: true
|
||||
- name: port
|
||||
default: 1502
|
||||
- name: modbus
|
||||
choice: [ "tcpip" ]
|
||||
port: 1502
|
||||
id: 71
|
||||
render: |
|
||||
type: custom
|
||||
power:
|
||||
source: modbus # use ModBus plugin
|
||||
uri: {{ .host }}:{{ .port }} # inverter port
|
||||
id: 71
|
||||
{{ include "modbus" . | indent 2 }}
|
||||
register: # manual non-sunspec register configuration
|
||||
address: 252 # (see ba_kostal_interface_modbus-tcp_sunspec.pdf)
|
||||
type: holding
|
||||
|
|
|
|||
|
|
@ -8,16 +8,14 @@ guidedsetup:
|
|||
params:
|
||||
- name: usage
|
||||
choice: [ "pv", "battery" ]
|
||||
- name: host
|
||||
example: 192.0.2.2
|
||||
required: true
|
||||
- name: port
|
||||
default: 1502
|
||||
- name: modbus
|
||||
choice: [ "tcpip" ]
|
||||
id: 71
|
||||
port: 1502
|
||||
render: |
|
||||
type: modbus
|
||||
model: sunspec
|
||||
uri: {{ .host }}:{{ .port }}
|
||||
id: 71 # kostal default sunspec modbus id
|
||||
{{ include "modbus" . }}
|
||||
{{- if eq .usage "battery" }}
|
||||
power: 802:W # sunspec model 802 battery
|
||||
soc: 802:SoC # sunspec model 802 battery
|
||||
|
|
|
|||
|
|
@ -3,13 +3,10 @@ description: Kostal Smart Energy Meter
|
|||
params:
|
||||
- name: usage
|
||||
choice: [ "grid" ]
|
||||
- name: host
|
||||
example: 192.0.2.2
|
||||
required: true
|
||||
- name: port
|
||||
default: 502
|
||||
- name: modbus
|
||||
choice: [ "tcpip" ]
|
||||
id: 71
|
||||
render: |
|
||||
type: modbus
|
||||
model: sunspec
|
||||
uri: {{ .host }}:{{ .port }}
|
||||
id: 71 # kostal default sunspec modbus id
|
||||
{{ include "modbus" . }}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,8 @@ guidedsetup:
|
|||
params:
|
||||
- name: usage
|
||||
choice: [ "grid", "pv" ]
|
||||
- name: host
|
||||
required: true
|
||||
example: 192.0.2.2
|
||||
- name: port
|
||||
default: 502
|
||||
- name: modbus
|
||||
choice: [ "tcpip" ]
|
||||
render: |
|
||||
type: custom
|
||||
power:
|
||||
|
|
@ -17,15 +14,13 @@ render: |
|
|||
source: calc #calculate current overall consumption + (current pv effort * (-1) )
|
||||
add:
|
||||
- source: modbus
|
||||
uri: {{ .host }}:{{ .port }} #ip-adress and port (default-port: 502)
|
||||
id: 1
|
||||
{{ include "modbus" . | indent 4 }}
|
||||
register:
|
||||
address: 40026 #register for overall consumption
|
||||
type: holding
|
||||
decode: int32
|
||||
- source: modbus
|
||||
uri: {{ .host }}:{{ .port }} #ip-adress and port (default-port: 502)
|
||||
id: 1
|
||||
{{ include "modbus" . | indent 4 }}
|
||||
register:
|
||||
address: 40002 #register for pv effort
|
||||
type: holding
|
||||
|
|
@ -34,8 +29,7 @@ render: |
|
|||
{{- end }}
|
||||
{{- if eq .usage "pv" }}
|
||||
type: modbus
|
||||
uri: {{ .host }}:{{ .port }} #ip-adress and port (default-port: 502)
|
||||
id: 1
|
||||
{{ include "modbus" . | indent 2 }}
|
||||
register:
|
||||
address: 40002 #register for pv effort
|
||||
type: holding
|
||||
|
|
|
|||
|
|
@ -4,17 +4,12 @@ generic: true
|
|||
params:
|
||||
- name: usage
|
||||
choice: [ "grid", "pv", "battery" ]
|
||||
- name: host
|
||||
example: 192.0.2.2
|
||||
required: true
|
||||
- name: id
|
||||
default: 1
|
||||
valuetype: number
|
||||
- name: modbus
|
||||
choice: [ "tcpip" ]
|
||||
render: |
|
||||
type: modbus
|
||||
model: sunspec
|
||||
uri: {{ .host }}
|
||||
id: {{ .id }}
|
||||
{{ include "modbus" .}}
|
||||
{{- if eq .usage "grid" }}
|
||||
power: 203:W # sunspec 3-phase meter power reading
|
||||
{{- end -}}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,18 @@ vehicle:
|
|||
example: W...
|
||||
- name: capacity
|
||||
default: '50'
|
||||
valueType: float
|
||||
- name: cache
|
||||
advanced: true
|
||||
- name: mode
|
||||
advanced: true
|
||||
- name: minSoC
|
||||
advanced: true
|
||||
- name: targetSoC
|
||||
advanced: true
|
||||
- name: minCurrent
|
||||
advanced: true
|
||||
- name: maxCurrent
|
||||
advanced: true
|
||||
- name: identifiers
|
||||
advanced: true
|
||||
valueType: stringlist
|
||||
|
|
@ -27,6 +38,27 @@ vehicle:
|
|||
{{- if ne .vin "" }}
|
||||
vin: {{ .vin }}
|
||||
{{- end }}
|
||||
{{- if ne .cache "" }}
|
||||
cache: {{ .cache }}
|
||||
{{- end }}
|
||||
{{- if or (ne .mode "") (ne .minSoC "") (ne .targetSoC "") (ne .minCurrent "") (ne .maxCurrent "") }}
|
||||
onIdentify:
|
||||
{{- if (ne .mode "") }}
|
||||
mode: {{ .mode }}
|
||||
{{- end }}
|
||||
{{- if (ne .minSoC "") }}
|
||||
minSoC: {{ .minSoC }}
|
||||
{{- end }}
|
||||
{{- if (ne .targetSoC "") }}
|
||||
targetSoC: {{ .targetSoC }}
|
||||
{{- end }}
|
||||
{{- if (ne .minCurrent "") }}
|
||||
minCurrent: {{ .minCurrent }}
|
||||
{{- end }}
|
||||
{{- if (ne .maxCurrent "") }}
|
||||
maxCurrent: {{ .maxCurrent }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if ne (len .identifiers) 0 }}
|
||||
identifiers:
|
||||
{{- range .identifiers }}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
type: template
|
||||
template: cfos_charger
|
||||
description: cFos PowerBrain
|
||||
description: cFos PowerBrain
|
||||
host: 192.0.2.2
|
||||
4
templates/docs/meter/cfos-meter-charge.yaml
Normal file
4
templates/docs/meter/cfos-meter-charge.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
type: template
|
||||
template: cfos-meter
|
||||
description: cFos PowerBrain Meter
|
||||
usage: charge
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
type: template
|
||||
template: cfos-meter
|
||||
description: cFos PowerBrain
|
||||
usage: charger
|
||||
9
templates/docs/meter/fritzdect-charge.yaml
Normal file
9
templates/docs/meter/fritzdect-charge.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
type: template
|
||||
template: fritzdect
|
||||
description: FritzDECT
|
||||
usage: charge
|
||||
uri: https://fritz.box
|
||||
user:
|
||||
password:
|
||||
ain: 007788992233 # Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt.
|
||||
standbypower: 15
|
||||
9
templates/docs/meter/fritzdect-pv.yaml
Normal file
9
templates/docs/meter/fritzdect-pv.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
type: template
|
||||
template: fritzdect
|
||||
description: FritzDECT
|
||||
usage: pv
|
||||
uri: https://fritz.box
|
||||
user:
|
||||
password:
|
||||
ain: 007788992233 # Die AIN ist auf dem Typenschild auf der Geräterückseite aufgedruckt.
|
||||
standbypower: 15
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: kostal-piko-energy-meter
|
||||
description: Kostal Piko (BA) Energy Meter
|
||||
usage: grid
|
||||
host: 192.0.2.2
|
||||
port: 1502
|
||||
usage: grid
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: kostal-plenticore
|
||||
description: Kostal Plenticore Hybrid
|
||||
usage: battery
|
||||
host: 192.0.2.2
|
||||
port: 1502
|
||||
usage: battery
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: kostal-plenticore
|
||||
description: Kostal Plenticore Hybrid
|
||||
usage: pv
|
||||
host: 192.0.2.2
|
||||
port: 1502
|
||||
usage: pv
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: kostal-smart-energy-meter
|
||||
description: Kostal Smart Energy Meter
|
||||
usage: grid
|
||||
host: 192.0.2.2
|
||||
port: 502
|
||||
usage: grid
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: powerdog
|
||||
description: Powerdog
|
||||
usage: grid
|
||||
host: 192.0.2.2
|
||||
port: 502
|
||||
usage: grid
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: powerdog
|
||||
description: Powerdog
|
||||
usage: pv
|
||||
host: 192.0.2.2
|
||||
port: 502
|
||||
usage: pv
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: sunspec
|
||||
description: Inverter / Wechselrichter (SunSpec)
|
||||
usage: battery
|
||||
host: 192.0.2.2
|
||||
id: 1
|
||||
usage: battery
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: sunspec
|
||||
description: Inverter / Wechselrichter (SunSpec)
|
||||
usage: grid
|
||||
host: 192.0.2.2
|
||||
id: 1
|
||||
usage: grid
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
type: template
|
||||
template: sunspec
|
||||
description: Inverter / Wechselrichter (SunSpec)
|
||||
usage: pv
|
||||
host: 192.0.2.2
|
||||
id: 1
|
||||
usage: pv
|
||||
|
|
@ -34,6 +34,9 @@ func main() {
|
|||
|
||||
func generateClass(class string) error {
|
||||
for _, tmpl := range templates.ByClass(class) {
|
||||
if err := tmpl.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
usages := tmpl.Usages()
|
||||
|
||||
fmt.Println(tmpl.Template)
|
||||
|
|
|
|||
|
|
@ -39,9 +39,12 @@ func loadTemplates(class string) {
|
|||
|
||||
var tmpl Template
|
||||
if err = yaml.Unmarshal(b, &tmpl); err != nil {
|
||||
panic(fmt.Errorf("reading template '%s' failed: %w", filepath, err))
|
||||
return fmt.Errorf("reading template '%s' failed: %w", filepath, err)
|
||||
}
|
||||
tmpl.ResolveParamBase()
|
||||
if err = tmpl.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := path.Dir(filepath)
|
||||
templates[path] = append(templates[path], tmpl)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/evcc-io/evcc/templates/definition"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
"github.com/thoas/go-funk"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
|
@ -17,6 +18,11 @@ const (
|
|||
ParamUsage = "usage"
|
||||
ParamModbus = "modbus"
|
||||
|
||||
UsageChoiceGrid = "grid"
|
||||
UsageChoicePV = "pv"
|
||||
UsageChoiceBattery = "battery"
|
||||
UsageChoiceCharge = "charge"
|
||||
|
||||
HemsTypeSMA = "sma"
|
||||
|
||||
ModbusChoiceRS485 = "rs485"
|
||||
|
|
@ -48,14 +54,18 @@ const (
|
|||
var HemsValueTypes = []string{HemsTypeSMA}
|
||||
|
||||
const (
|
||||
ParamValueTypeString = "string"
|
||||
ParamValueTypeNumber = "number"
|
||||
ParamValueTypeFloat = "float"
|
||||
ParamValueTypeBool = "bool"
|
||||
ParamValueTypeStringList = "stringlist"
|
||||
ParamValueTypeString = "string"
|
||||
ParamValueTypeNumber = "number"
|
||||
ParamValueTypeFloat = "float"
|
||||
ParamValueTypeBool = "bool"
|
||||
ParamValueTypeStringList = "stringlist"
|
||||
ParamValueTypeChargeModes = "chargemodes"
|
||||
)
|
||||
|
||||
var ParamValueTypes = []string{ParamValueTypeString, ParamValueTypeNumber, ParamValueTypeBool}
|
||||
var ParamValueTypes = []string{ParamValueTypeString, ParamValueTypeNumber, ParamValueTypeFloat, ParamValueTypeBool, ParamValueTypeStringList, ParamValueTypeChargeModes}
|
||||
|
||||
var ValidModbusChoices = []string{ModbusChoiceRS485, ModbusChoiceTCPIP}
|
||||
var ValidUsageChoices = []string{UsageChoiceGrid, UsageChoicePV, UsageChoiceBattery, UsageChoiceCharge}
|
||||
|
||||
// language specific texts
|
||||
type TextLanguage struct {
|
||||
|
|
@ -123,6 +133,8 @@ type Param struct {
|
|||
Usages []string
|
||||
Baudrate int // device specific default for modbus RS485 baudrate
|
||||
Comset string // device specific default for modbus RS485 comset
|
||||
Port int // device specific default for modbus TCPIP port
|
||||
ID int // device specific default for modbus ID
|
||||
}
|
||||
|
||||
type ParamBase struct {
|
||||
|
|
@ -144,6 +156,27 @@ type Template struct {
|
|||
Render string // rendering template
|
||||
}
|
||||
|
||||
func (t *Template) Validate() error {
|
||||
for _, p := range t.Params {
|
||||
switch p.Name {
|
||||
case ParamUsage:
|
||||
for _, c := range p.Choice {
|
||||
if !funk.ContainsString(ValidUsageChoices, c) {
|
||||
return fmt.Errorf("invalid usage choice '%s' in template %s", c, t.Template)
|
||||
}
|
||||
}
|
||||
case ParamModbus:
|
||||
for _, c := range p.Choice {
|
||||
if !funk.ContainsString(ValidModbusChoices, c) {
|
||||
return fmt.Errorf("invalid modbus choice '%s' in template %s", c, t.Template)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// add the referenced base Params and overwrite existing ones
|
||||
func (t *Template) ResolveParamBase() {
|
||||
if t.ParamsBase == "" {
|
||||
|
|
@ -190,6 +223,8 @@ func (t *Template) Defaults(docsOrTests bool) map[string]interface{} {
|
|||
switch p.ValueType {
|
||||
case ParamValueTypeStringList:
|
||||
values[p.Name] = []string{}
|
||||
case ParamValueTypeChargeModes:
|
||||
values[p.Name] = ""
|
||||
default:
|
||||
if p.Test != "" {
|
||||
values[p.Name] = p.Test
|
||||
|
|
@ -234,17 +269,15 @@ func (t *Template) ModbusChoices() []string {
|
|||
//go:embed proxy.tpl
|
||||
var proxyTmpl string
|
||||
|
||||
// RenderProxy renders the proxy template for inclusion in documentation
|
||||
func (t *Template) RenderProxy() ([]byte, error) {
|
||||
return t.RenderProxyWithValues(nil, false)
|
||||
}
|
||||
|
||||
// RenderProxy renders the proxy template
|
||||
func (t *Template) RenderProxyWithValues(values map[string]interface{}, includeDescription bool) ([]byte, error) {
|
||||
tmpl, err := template.New("yaml").Funcs(template.FuncMap(sprig.FuncMap())).Parse(proxyTmpl)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
t.ModbusParams(values)
|
||||
|
||||
for index, p := range t.Params {
|
||||
for k, v := range values {
|
||||
if p.Name != k {
|
||||
|
|
@ -257,7 +290,12 @@ func (t *Template) RenderProxyWithValues(values map[string]interface{}, includeD
|
|||
t.Params[index].Values = append(p.Values, yamlQuote(e))
|
||||
}
|
||||
default:
|
||||
t.Params[index].Value = yamlQuote(v.(string))
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
t.Params[index].Value = yamlQuote(v)
|
||||
case int:
|
||||
t.Params[index].Value = fmt.Sprintf("%d", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,41 @@ import (
|
|||
//go:embed modbus.tpl
|
||||
var modbusTmpl string
|
||||
|
||||
// add the modbus params to the template
|
||||
func (t *Template) ModbusParams(values map[string]interface{}) {
|
||||
if len(t.ModbusChoices()) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if values[ParamModbus] == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for k := range values {
|
||||
if k == ModbusParamNameId {
|
||||
t.Params = append(t.Params, Param{Name: ModbusParamNameId, ValueType: ParamValueTypeNumber})
|
||||
continue
|
||||
}
|
||||
|
||||
type modbusData struct {
|
||||
modbusKeys []string
|
||||
valueType string
|
||||
}
|
||||
paramMap := map[string]modbusData{
|
||||
ModbusParamNameId: {modbusKeys: []string{ModbusKeyTCPIP, ModbusKeyRS485TCPIP, ModbusKeyRS485Serial}, valueType: ParamValueTypeNumber},
|
||||
ModbusParamNameHost: {modbusKeys: []string{ModbusKeyTCPIP, ModbusKeyRS485TCPIP}, valueType: ParamValueTypeString},
|
||||
ModbusParamNamePort: {modbusKeys: []string{ModbusKeyTCPIP, ModbusKeyRS485TCPIP}, valueType: ParamValueTypeNumber},
|
||||
ModbusParamNameDevice: {modbusKeys: []string{ModbusKeyRS485Serial}, valueType: ParamValueTypeString},
|
||||
ModbusParamNameBaudrate: {modbusKeys: []string{ModbusKeyRS485Serial}, valueType: ParamValueTypeNumber},
|
||||
ModbusParamNameComset: {modbusKeys: []string{ModbusKeyRS485Serial}, valueType: ParamValueTypeString},
|
||||
}
|
||||
|
||||
if funk.ContainsString(paramMap[k].modbusKeys, values[ParamModbus].(string)) {
|
||||
t.Params = append(t.Params, Param{Name: k, ValueType: paramMap[k].valueType})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the modbus values required from modbus.tpl and and the template to the render
|
||||
func (t *Template) ModbusValues(values map[string]interface{}) {
|
||||
if len(t.ModbusChoices()) == 0 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue