244 lines
5.5 KiB
Go
244 lines
5.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/evcc-io/evcc/util/templates"
|
|
"github.com/gosimple/slug"
|
|
)
|
|
|
|
const (
|
|
docsPath = "../../../templates/docs"
|
|
websitePath = "../../../templates/evcc.io"
|
|
iconsPath = "../../../templates/icons"
|
|
)
|
|
|
|
//go:generate go run main.go
|
|
|
|
func main() {
|
|
slug.CustomSub = map[string]string{"+": "plus"}
|
|
|
|
for _, lang := range []string{"de", "en"} {
|
|
if err := generateDocs(lang); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
if err := generateBrandJSON(); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if err := generateProductJSON(); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func generateDocs(lang string) error {
|
|
for _, class := range templates.ClassValues() {
|
|
path := fmt.Sprintf("%s/%s/%s", docsPath, lang, strings.ToLower(class.String()))
|
|
_, err := os.Stat(path)
|
|
if os.IsNotExist(err) {
|
|
if err := os.MkdirAll(path, 0o755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := clearDir(path); err != nil {
|
|
fmt.Printf("Could not clear directory for %s: %s\n", class, err)
|
|
}
|
|
|
|
if err := generateClass(class, lang); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func generateClass(class templates.Class, lang string) error {
|
|
for _, tmpl := range templates.ByClass(class) {
|
|
if err := tmpl.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, product := range tmpl.Products {
|
|
fmt.Println(tmpl.Template + ": " + product.Title(lang))
|
|
|
|
b, err := tmpl.RenderDocumentation(product, lang)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
filename := fmt.Sprintf("%s/%s/%s/%s.yaml", docsPath, lang, strings.ToLower(class.String()), product.Identifier())
|
|
|
|
if _, err := os.Stat(filename); err == nil {
|
|
return fmt.Errorf("file already exists: %s - product titles must be unique", filename)
|
|
}
|
|
|
|
if err := os.WriteFile(filename, b, 0o644); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func clearDir(dir string) error {
|
|
names, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, entry := range names {
|
|
if err := os.RemoveAll(path.Join([]string{dir, entry.Name()}...)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func sorted(keys []string) []string {
|
|
slices.SortFunc(keys, func(i, j string) int {
|
|
return strings.Compare(strings.ToLower(i), strings.ToLower(j))
|
|
})
|
|
return slices.Compact(keys)
|
|
}
|
|
|
|
func generateBrandJSON() error {
|
|
var chargers, smartswitches, heating []string
|
|
for _, tmpl := range templates.ByClass(templates.Charger) {
|
|
for _, product := range tmpl.Products {
|
|
if product.Brand == "" {
|
|
continue
|
|
}
|
|
|
|
if tmpl.Group == "switchsockets" {
|
|
smartswitches = append(smartswitches, product.Brand)
|
|
} else if tmpl.Group == "heating" {
|
|
heating = append(heating, product.Brand)
|
|
} else {
|
|
chargers = append(chargers, product.Brand)
|
|
}
|
|
}
|
|
}
|
|
|
|
var vehicles []string
|
|
for _, tmpl := range templates.ByClass(templates.Vehicle) {
|
|
for _, product := range tmpl.Products {
|
|
if product.Brand != "" {
|
|
vehicles = append(vehicles, product.Brand)
|
|
}
|
|
}
|
|
}
|
|
|
|
var meters, pvBattery []string
|
|
for _, tmpl := range templates.ByClass(templates.Meter) {
|
|
for i := range tmpl.Params {
|
|
if tmpl.Params[i].Name != templates.ParamUsage {
|
|
continue
|
|
}
|
|
|
|
for j := range tmpl.Params[i].Choice {
|
|
usage, _ := templates.UsageString(tmpl.Params[i].Choice[j])
|
|
for _, product := range tmpl.Products {
|
|
if product.Brand == "" {
|
|
continue
|
|
}
|
|
|
|
switch usage {
|
|
case templates.UsageGrid, templates.UsageCharge, templates.UsageAux:
|
|
meters = append(meters, product.Brand)
|
|
case templates.UsagePV, templates.UsageBattery:
|
|
pvBattery = append(pvBattery, product.Brand)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
brands := struct {
|
|
Chargers, SmartSwitches, Heating, Meters, PVBattery, Vehicles []string
|
|
}{
|
|
Chargers: sorted(chargers),
|
|
SmartSwitches: sorted(smartswitches),
|
|
Heating: sorted(heating),
|
|
Meters: sorted(meters),
|
|
PVBattery: sorted(pvBattery),
|
|
Vehicles: sorted(vehicles),
|
|
}
|
|
|
|
file, err := json.MarshalIndent(brands, "", " ")
|
|
if err == nil {
|
|
err = os.WriteFile(websitePath+"/brands.json", file, 0o644)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func generateProductJSON() error {
|
|
type Category string
|
|
|
|
const (
|
|
charger Category = "charger"
|
|
smartswitch Category = "smartswitch"
|
|
heating Category = "heating"
|
|
meter Category = "meter"
|
|
vehicle Category = "vehicle"
|
|
)
|
|
|
|
type ProductInfo struct {
|
|
Brand string `json:"brand"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
products := make(map[string]map[string]ProductInfo)
|
|
for _, key := range []Category{charger, smartswitch, heating, meter, vehicle} {
|
|
products[string(key)] = make(map[string]ProductInfo)
|
|
}
|
|
|
|
for _, class := range []templates.Class{templates.Charger, templates.Meter, templates.Vehicle} {
|
|
for _, tmpl := range templates.ByClass(class) {
|
|
for _, product := range tmpl.Products {
|
|
var category Category
|
|
switch class {
|
|
case templates.Charger:
|
|
if tmpl.Group == "switchsockets" {
|
|
category = smartswitch
|
|
} else if tmpl.Group == "heating" {
|
|
category = heating
|
|
} else {
|
|
category = charger
|
|
}
|
|
case templates.Meter:
|
|
category = meter
|
|
case templates.Vehicle:
|
|
category = vehicle
|
|
}
|
|
|
|
products[string(category)][product.Identifier()] = ProductInfo{
|
|
Brand: product.Brand,
|
|
Description: product.Description.String("en"),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if _, err := os.Stat(iconsPath); os.IsNotExist(err) {
|
|
if err := os.MkdirAll(iconsPath, 0o755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
file, err := json.MarshalIndent(products, "", " ")
|
|
if err == nil {
|
|
err = os.WriteFile(iconsPath+"/products.json", file, 0o644)
|
|
}
|
|
|
|
return err
|
|
}
|