Add products api (#6205)

This commit is contained in:
andig 2023-02-11 21:05:35 +01:00 • committed by GitHub
parent cc85ed8efd
commit e6f8939ee7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 0 deletions

View file

@ -98,6 +98,7 @@ func (s *HTTPd) RegisterSiteHandlers(site site.API, cache *util.Cache) {
"health": {[]string{"GET"}, "/health", healthHandler(site)},
"state": {[]string{"GET"}, "/state", stateHandler(cache)},
"config": {[]string{"GET"}, "/config/templates/{class:[a-z]+}", templatesHandler},
"products": {[]string{"GET"}, "/config/products/{class:[a-z]+}", productsHandler},
"test": {[]string{"POST"}, "/config/test/{class:[a-z]+}", testHandler},
"buffersoc": {[]string{"POST", "OPTIONS"}, "/buffersoc/{value:[0-9.]+}", floatHandler(site.SetBufferSoc, site.GetBufferSoc)},
"prioritysoc": {[]string{"POST", "OPTIONS"}, "/prioritysoc/{value:[0-9.]+}", floatHandler(site.SetPrioritySoc, site.GetPrioritySoc)},

View file

@ -2,7 +2,9 @@ package server
import (
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/charger"
@ -10,6 +12,7 @@ import (
"github.com/evcc-io/evcc/util/templates"
"github.com/evcc-io/evcc/vehicle"
"github.com/gorilla/mux"
"golang.org/x/exp/slices"
)
// templatesHandler returns the list of templates by class
@ -23,6 +26,93 @@ func templatesHandler(w http.ResponseWriter, r *http.Request) {
}
res := templates.ByClass(class)
lang := r.URL.Query().Get("lang")
templates.EncoderLanguage(lang)
if name := r.URL.Query().Get("name"); name != "" {
for _, t := range res {
if t.TemplateDefinition.Template == name {
jsonResult(w, t)
return
}
}
jsonError(w, http.StatusBadRequest, errors.New("template not found"))
return
}
jsonResult(w, res)
}
type product struct {
Name string `json:"name"`
Template string `json:"template"`
}
type products []product
func (p products) MarshalJSON() (out []byte, err error) {
if p == nil {
return []byte(`null`), nil
}
if len(p) == 0 {
return []byte(`{}`), nil
}
out = append(out, '{')
for _, e := range p {
key, err := json.Marshal(e.Name)
if err != nil {
return nil, err
}
val, err := json.Marshal(e.Template)
if err != nil {
return nil, err
}
out = append(out, key...)
out = append(out, ':')
out = append(out, val...)
out = append(out, ',')
}
// replace last ',' with '}'
if len(out) > 1 {
out[len(out)-1] = '}'
} else {
out = append(out, '}')
}
return out, nil
}
// productsHandler returns the list of products by class
func productsHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
class, err := templates.ClassString(vars["class"])
if err != nil {
jsonError(w, http.StatusBadRequest, err)
return
}
tmpl := templates.ByClass(class)
lang := r.URL.Query().Get("lang")
res := make(products, 0)
for _, t := range tmpl {
for _, p := range t.Products {
res = append(res, product{
Name: p.Title(lang),
Template: t.TemplateDefinition.Template,
})
}
}
slices.SortFunc(res, func(a, b product) bool {
return strings.ToLower(a.Name) < strings.ToLower(b.Name)
})
jsonResult(w, res)
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"io/fs"
"path"
"sync"
"github.com/evcc-io/evcc/templates/definition"
"golang.org/x/exp/slices"
@ -14,6 +15,9 @@ import (
var (
templates = make(map[Class][]Template)
configDefaults = ConfigDefaults{}
mu sync.Mutex
encoderLanguage string
)
func init() {
@ -98,6 +102,13 @@ func loadTemplates(class Class) {
}
}
// EncoderLanguage sets the template language for encoding json
func EncoderLanguage(lang string) {
mu.Lock()
defer mu.Unlock()
encoderLanguage = lang
}
func ByClass(class Class) []Template {
return templates[class]
}

View file

@ -2,6 +2,7 @@ package templates
import (
"bufio"
"encoding/json"
"fmt"
"strings"
@ -145,6 +146,14 @@ func (t *TextLanguage) Update(new TextLanguage, always bool) {
}
}
// MarshalJSON implements the json.Marshaler interface
func (t *TextLanguage) MarshalJSON() (out []byte, err error) {
mu.Lock()
s := t.String(encoderLanguage)
mu.Unlock()
return json.Marshal(s)
}
// Requirements
type Requirements struct {
EVCC []string // EVCC requirements, e.g. sponsorship