Templates: add capabilities on product level (#31588)
This commit is contained in:
parent
4f71e9675c
commit
023a48dd24
6 changed files with 95 additions and 10 deletions
|
|
@ -50,14 +50,40 @@ Note: The official website of the manufacturer or service provider is the refere
|
|||
|
||||
## `capabilities`
|
||||
|
||||
`capabilities` provides an option to define special capabilities of the device as a list of strings
|
||||
`capabilities` provides an option to define special capabilities of the device as a list of strings.
|
||||
|
||||
**Possible Values**:
|
||||
**Possible values**:
|
||||
|
||||
- `iso151182`: If the charger supports communicating via ISO15118-2
|
||||
- `rfid`: If the charger supports RFID
|
||||
- `1p3p`: If the charger supports 1P/3P-phase switching
|
||||
- `smahems`: If the device can be used as an SMA HEMS device, only used for the SMA Home Manager 2.0 right now
|
||||
- `iso151182`: The device supports communicating via ISO 15118-2.
|
||||
- `mA`: The device supports granular (milliamp) current control.
|
||||
- `rfid`: The device supports RFID.
|
||||
- `1p3p`: The device supports 1P/3P phase switching.
|
||||
- `battery-control`: The device supports battery control.
|
||||
- `meter`: The device has a built-in energy meter.
|
||||
- `dim`: The device supports EnWG §14a dimming.
|
||||
- `curtail`: The device supports EEG §9 curtailment.
|
||||
|
||||
`capabilities` can be set at two levels:
|
||||
|
||||
- **Template level** (next to `template`): applies to every product.
|
||||
- **Product level** (under a `products` entry): applies to that product only.
|
||||
|
||||
Both levels are merged, not overwritten: template-level capabilities are appended to each product's own list. A product cannot remove an inherited capability, and duplicates are rejected, so do not repeat a template-level capability on a product.
|
||||
|
||||
**Example** (all products get `1p3p`; only the second product additionally gets `meter`):
|
||||
|
||||
```yaml
|
||||
template: demo-charger
|
||||
capabilities: ["1p3p"]
|
||||
products:
|
||||
- brand: Demo
|
||||
description:
|
||||
generic: Basic
|
||||
- brand: Demo
|
||||
description:
|
||||
generic: Plus
|
||||
capabilities: ["meter"] # effective: ["meter", "1p3p"]
|
||||
```
|
||||
|
||||
## `requirements`
|
||||
|
||||
|
|
|
|||
45
util/templates/capability_test.go
Normal file
45
util/templates/capability_test.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCapabilityPushdown(t *testing.T) {
|
||||
tmpl, err := fromBytes([]byte(`
|
||||
template: caps-demo
|
||||
capabilities: ["1p3p"]
|
||||
products:
|
||||
- brand: Plain
|
||||
- brand: Extra
|
||||
capabilities: ["meter"]
|
||||
params:
|
||||
- name: host
|
||||
required: true
|
||||
render: |
|
||||
type: demo
|
||||
`))
|
||||
require.NoError(t, err)
|
||||
|
||||
// template caps appended to product caps (product first)
|
||||
require.Equal(t, []Capability{Capability1p3p}, tmpl.Products[0].Capabilities)
|
||||
require.Equal(t, []Capability{CapabilityMeter, Capability1p3p}, tmpl.Products[1].Capabilities)
|
||||
}
|
||||
|
||||
func TestCapabilityDuplicate(t *testing.T) {
|
||||
// product repeats a template-level capability
|
||||
_, err := fromBytes([]byte(`
|
||||
template: caps-dup
|
||||
capabilities: ["1p3p"]
|
||||
products:
|
||||
- brand: Dup
|
||||
capabilities: ["1p3p"]
|
||||
params:
|
||||
- name: host
|
||||
required: true
|
||||
render: |
|
||||
type: demo
|
||||
`))
|
||||
require.ErrorContains(t, err, "duplicate capability '1p3p'")
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ func (t *Template) RenderDocumentation(product Product, lang string) ([]byte, er
|
|||
"ProductBrand": product.Brand,
|
||||
"ProductDescription": product.Description.String(lang),
|
||||
"ProductGroup": t.GroupTitle(lang),
|
||||
"Capabilities": t.Capabilities,
|
||||
"Capabilities": product.Capabilities,
|
||||
"Countries": t.Countries,
|
||||
"Requirements": t.Requirements.EVCC,
|
||||
"RequirementDescription": t.Requirements.Description.String(lang),
|
||||
|
|
|
|||
|
|
@ -79,6 +79,19 @@ func fromBytes(b []byte) (Template, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// push down capabilities to products
|
||||
for i := range tmpl.Products {
|
||||
tmpl.Products[i].Capabilities = append(tmpl.Products[i].Capabilities, tmpl.Capabilities...)
|
||||
|
||||
seen := make(map[Capability]struct{}, len(tmpl.Products[i].Capabilities))
|
||||
for _, c := range tmpl.Products[i].Capabilities {
|
||||
if _, ok := seen[c]; ok {
|
||||
return Template{}, fmt.Errorf("template '%s': duplicate capability '%s' for product '%s'", tmpl.Template, c, tmpl.Products[i].Identifier())
|
||||
}
|
||||
seen[c] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return tmpl, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ type Template struct {
|
|||
Group string `json:",omitempty"` // the group this template belongs to, references groupList entries
|
||||
Covers []string `json:",omitempty"` // list of covered outdated template names
|
||||
Products []Product `json:",omitempty"` // list of products this template is compatible with
|
||||
Capabilities []Capability `json:",omitempty"`
|
||||
Capabilities []Capability `json:"-"`
|
||||
Countries []CountryCode `json:",omitempty"` // list of countries supported by this template
|
||||
Requirements Requirements `json:",omitempty"`
|
||||
Caveats []Caveat `json:",omitempty"` // known device limitations
|
||||
|
|
|
|||
|
|
@ -321,8 +321,9 @@ func (p Param) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// Product contains naming information about a product a template supports
|
||||
type Product struct {
|
||||
Brand string // product brand
|
||||
Description TextLanguage `json:",omitempty"` // product name
|
||||
Brand string // product brand
|
||||
Description TextLanguage `json:",omitempty"` // product name
|
||||
Capabilities []Capability `json:",omitempty"` // appended to template-level capabilities
|
||||
}
|
||||
|
||||
// Title returns the product title in the given language
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue