250 lines
5.8 KiB
Go
250 lines
5.8 KiB
Go
package globalconfig
|
|
|
|
import (
|
|
"encoding/json"
|
|
"iter"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/evcc-io/evcc/api"
|
|
"github.com/evcc-io/evcc/charger/ocpp"
|
|
"github.com/evcc-io/evcc/hems/shm"
|
|
"github.com/evcc-io/evcc/plugin/mqtt"
|
|
"github.com/evcc-io/evcc/server/eebus"
|
|
"github.com/evcc-io/evcc/util"
|
|
"github.com/evcc-io/evcc/util/config"
|
|
"github.com/evcc-io/evcc/util/modbus"
|
|
)
|
|
|
|
// ConfigStatus for publishing config, status and source to UI and external systems
|
|
type ConfigStatus struct {
|
|
Config any `json:"config,omitempty"`
|
|
Status any `json:"status,omitempty"`
|
|
YamlSource YamlSource `json:"yamlSource,omitempty"`
|
|
}
|
|
|
|
type YamlSource string
|
|
|
|
const (
|
|
YamlSourceFile YamlSource = "file"
|
|
YamlSourceDb YamlSource = "db"
|
|
YamlSourceNone YamlSource = ""
|
|
)
|
|
|
|
type All struct {
|
|
Network Network
|
|
Ocpp ocpp.Config
|
|
Log string
|
|
SponsorToken string
|
|
Plant string // telemetry plant id
|
|
Telemetry bool
|
|
Mcp bool // TODO deprecated
|
|
Metrics bool
|
|
Profile bool
|
|
Levels map[string]string
|
|
Interval time.Duration
|
|
Database DB
|
|
Mqtt Mqtt
|
|
ModbusProxy []ModbusProxy
|
|
Javascript []Javascript
|
|
Go []Go
|
|
Influx Influx
|
|
EEBus eebus.Config
|
|
HEMS Hems
|
|
SHM shm.Config
|
|
Messaging Messaging
|
|
MessagingEvents MessagingEvents
|
|
Meters []config.Named
|
|
Chargers []config.Named
|
|
Vehicles []config.Named
|
|
Tariffs Tariffs
|
|
Site map[string]any
|
|
Loadpoints []config.Named
|
|
Circuits []config.Named
|
|
Curtailers []config.Named
|
|
}
|
|
|
|
type Javascript struct {
|
|
VM string
|
|
Script string
|
|
}
|
|
|
|
type Go struct {
|
|
VM string
|
|
Script string
|
|
}
|
|
|
|
type ModbusProxy struct {
|
|
Port int `json:"port"`
|
|
ReadOnly string `yaml:",omitempty" json:"readonly,omitempty"`
|
|
modbus.Settings `mapstructure:",squash" yaml:",inline,omitempty" json:"settings"`
|
|
}
|
|
|
|
var _ api.Redactor = (*Hems)(nil)
|
|
|
|
type Hems config.Typed
|
|
|
|
func (c Hems) Redacted() any {
|
|
return struct {
|
|
Type string `json:"type,omitempty"`
|
|
}{
|
|
Type: c.Type,
|
|
}
|
|
}
|
|
|
|
var _ api.Redactor = (*Mqtt)(nil)
|
|
|
|
type Mqtt struct {
|
|
mqtt.Config `mapstructure:",squash"`
|
|
Topic string `json:"topic"`
|
|
}
|
|
|
|
// Redacted implements the redactor interface used by the tee publisher
|
|
func (m Mqtt) Redacted() any {
|
|
return Mqtt{
|
|
Config: mqtt.Config{
|
|
Broker: m.Broker,
|
|
User: m.User,
|
|
Password: util.Masked(m.Password),
|
|
ClientID: m.ClientID,
|
|
Insecure: m.Insecure,
|
|
CaCert: util.Masked(m.CaCert),
|
|
ClientCert: util.Masked(m.ClientCert),
|
|
ClientKey: util.Masked(m.ClientKey),
|
|
},
|
|
Topic: m.Topic,
|
|
}
|
|
}
|
|
|
|
// Influx is the influx db configuration
|
|
type Influx struct {
|
|
URL string `json:"url"`
|
|
Database string `json:"database"`
|
|
Token string `json:"token"`
|
|
Org string `json:"org"`
|
|
User string `json:"user"`
|
|
Password string `json:"password"`
|
|
Insecure bool `json:"insecure"`
|
|
}
|
|
|
|
// Redacted implements the redactor interface used by the tee publisher
|
|
func (c Influx) Redacted() any {
|
|
return Influx{
|
|
URL: c.URL,
|
|
Database: c.Database,
|
|
Token: util.Masked(c.Token),
|
|
Org: c.Org,
|
|
User: c.User,
|
|
Password: util.Masked(c.Password),
|
|
Insecure: c.Insecure,
|
|
}
|
|
}
|
|
|
|
type DB struct {
|
|
Type string
|
|
Dsn string
|
|
}
|
|
|
|
type Messaging struct {
|
|
Events MessagingEvents
|
|
Services []config.Typed
|
|
}
|
|
|
|
type MessagingEvents = map[string]MessagingEventTemplate
|
|
|
|
// MessagingEventTemplate is the push message configuration for an event
|
|
type MessagingEventTemplate struct {
|
|
Title string `json:"title"`
|
|
Msg string `json:"msg"`
|
|
Disabled bool `json:"disabled"`
|
|
}
|
|
|
|
func (c Messaging) IsConfigured() bool {
|
|
return len(c.Services) > 0 || len(c.Events) > 0
|
|
}
|
|
|
|
type Tariffs struct {
|
|
Currency string
|
|
Grid config.Typed
|
|
FeedIn config.Typed
|
|
Co2 config.Typed
|
|
Planner config.Typed
|
|
Solar []config.Typed
|
|
Temperature config.Typed
|
|
}
|
|
|
|
func (c Tariffs) IsConfigured() bool {
|
|
return c.Currency != "" || c.Grid.Type != "" || c.FeedIn.Type != "" || c.Co2.Type != "" || c.Planner.Type != "" || len(c.Solar) > 0 || c.Temperature.Type != ""
|
|
}
|
|
|
|
type TariffRefs struct {
|
|
Grid string `json:"grid"`
|
|
FeedIn string `json:"feedIn"`
|
|
Co2 string `json:"co2"`
|
|
Planner string `json:"planner"`
|
|
Solar []string `json:"solar"`
|
|
Temperature string `json:"temperature"`
|
|
}
|
|
|
|
func (refs TariffRefs) IsConfigured() bool {
|
|
return refs.Grid != "" || refs.FeedIn != "" || refs.Co2 != "" || refs.Planner != "" || len(refs.Solar) > 0 || refs.Temperature != ""
|
|
}
|
|
|
|
func (refs TariffRefs) Used() iter.Seq[string] {
|
|
return func(yield func(string) bool) {
|
|
for _, ref := range append([]string{refs.Grid, refs.FeedIn, refs.Co2, refs.Planner, refs.Temperature}, refs.Solar...) {
|
|
if ref != "" {
|
|
if !yield(ref) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type Network struct {
|
|
Schema_ string `json:"schema,omitempty" mapstructure:"schema"` // TODO deprecated
|
|
ExternalUrl string `json:"externalUrl"`
|
|
Host string `json:"host"`
|
|
Port int `json:"port"`
|
|
}
|
|
|
|
func (c Network) HostPort() string {
|
|
host := "localhost"
|
|
if h, err := os.Hostname(); err == nil {
|
|
host = h
|
|
}
|
|
if ips := util.LocalIPs(); len(ips) > 0 {
|
|
host = ips[0].IP.String()
|
|
}
|
|
if c.Port == 80 {
|
|
return host
|
|
}
|
|
return net.JoinHostPort(host, strconv.Itoa(c.Port))
|
|
}
|
|
|
|
func (c Network) InternalURL() string {
|
|
return "http://" + c.HostPort()
|
|
}
|
|
|
|
func (c Network) ExternalURL() string {
|
|
if c.ExternalUrl != "" {
|
|
return strings.TrimRight(c.ExternalUrl, "/")
|
|
}
|
|
return c.InternalURL()
|
|
}
|
|
|
|
// MarshalJSON includes the computed InternalUrl field in JSON output
|
|
func (c Network) MarshalJSON() ([]byte, error) {
|
|
type networkAlias Network
|
|
return json.Marshal(struct {
|
|
networkAlias
|
|
InternalUrl string `json:"internalUrl"`
|
|
}{
|
|
networkAlias: networkAlias(c),
|
|
InternalUrl: c.InternalURL(),
|
|
})
|
|
}
|