2023-07-23 08:49:57 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/fs"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ListeningMode int64
|
|
|
|
|
|
|
|
func (lm ListeningMode) String() string {
|
|
|
|
mapping := map[ListeningMode]string{
|
|
|
|
ModeNet: "net",
|
|
|
|
ModeUnix: "unix",
|
|
|
|
}
|
|
|
|
val := mapping[lm]
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
|
|
|
|
func listeningModeFromString(rawVal string) (ListeningMode, error) {
|
|
|
|
mapping := map[string]ListeningMode{
|
|
|
|
"unix": ModeUnix,
|
|
|
|
"net": ModeNet,
|
|
|
|
}
|
|
|
|
if typedVal, ok := mapping[rawVal]; !ok {
|
|
|
|
return ModeNet, fmt.Errorf("invalid listening mode %s", rawVal)
|
|
|
|
} else {
|
|
|
|
return typedVal, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
ModeUnix ListeningMode = iota
|
|
|
|
ModeNet
|
|
|
|
)
|
|
|
|
|
|
|
|
type jsonConf struct {
|
|
|
|
Log struct {
|
|
|
|
Level string `json:"level"`
|
|
|
|
} `json:"log"`
|
2023-07-30 09:20:45 +00:00
|
|
|
Storage struct {
|
2024-03-24 12:37:40 +00:00
|
|
|
Path string `json:"path"`
|
|
|
|
TemplateDir string `json:"templatePath"`
|
|
|
|
StaticDir string `json:"staticPath"`
|
2023-07-30 09:20:45 +00:00
|
|
|
} `json:"storage"`
|
2023-07-23 08:49:57 +00:00
|
|
|
Server struct {
|
2024-03-27 21:07:09 +00:00
|
|
|
Host string `json:"host"`
|
|
|
|
Port int `json:"port"`
|
|
|
|
Mode string `json:"mode"`
|
|
|
|
SockPath string `json:"sock"`
|
|
|
|
PublicHost string `json:"public_host"`
|
2023-07-23 08:49:57 +00:00
|
|
|
} `json:"server"`
|
2023-07-29 19:23:36 +00:00
|
|
|
BootProvider struct {
|
|
|
|
Iface string `json:"interface"`
|
|
|
|
Port int `json:"port"`
|
|
|
|
McastGroup string `json:"multicast_group"`
|
2023-09-16 11:52:05 +00:00
|
|
|
SrcAddr string `json:"src_addr"`
|
2023-07-29 19:23:36 +00:00
|
|
|
} `json:"boot_provider"`
|
2024-04-30 16:43:01 +00:00
|
|
|
HomeAssistant struct {
|
|
|
|
Enabled bool `json:"enabled"`
|
|
|
|
Host string `json:"host"`
|
|
|
|
APIToken string `json:"token"`
|
|
|
|
} `json:"home_assistant"`
|
2023-07-23 08:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type AppConfig struct {
|
2024-04-30 16:43:01 +00:00
|
|
|
LogLevel logrus.Level
|
|
|
|
ServerMode ListeningMode
|
|
|
|
DataFilepath string
|
|
|
|
StaticDir string
|
|
|
|
Host string
|
|
|
|
PublicHost string
|
|
|
|
Port int
|
|
|
|
SockPath string
|
|
|
|
UPDMcastGroup string
|
|
|
|
UDPPort int
|
|
|
|
UDPIface string
|
|
|
|
UDPSrcAddr string
|
|
|
|
HomeAssistantEnabled bool
|
|
|
|
HomeAssistantHost string
|
|
|
|
HomeAssistantToken string
|
2023-07-23 08:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseLevel(lvlStr string) logrus.Level {
|
|
|
|
for _, lvl := range logrus.AllLevels {
|
|
|
|
if lvl.String() == lvlStr {
|
|
|
|
return lvl
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return logrus.InfoLevel
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ac *AppConfig) UnmarshalJSON(data []byte) error {
|
|
|
|
var jsonConf jsonConf
|
|
|
|
if err := json.Unmarshal(data, &jsonConf); err != nil {
|
|
|
|
return fmt.Errorf("failed to read JSON: %w", err)
|
|
|
|
}
|
|
|
|
ac.LogLevel = parseLevel(jsonConf.Log.Level)
|
|
|
|
|
|
|
|
lm, err := listeningModeFromString(jsonConf.Server.Mode)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to parse server listening mode: %w", err)
|
|
|
|
}
|
|
|
|
ac.ServerMode = lm
|
|
|
|
ac.SockPath = jsonConf.Server.SockPath
|
|
|
|
ac.Host = jsonConf.Server.Host
|
2024-03-27 21:07:09 +00:00
|
|
|
ac.PublicHost = jsonConf.Server.PublicHost
|
2023-07-23 08:49:57 +00:00
|
|
|
ac.Port = jsonConf.Server.Port
|
2023-07-29 19:23:36 +00:00
|
|
|
ac.UPDMcastGroup = jsonConf.BootProvider.McastGroup
|
|
|
|
ac.UDPIface = jsonConf.BootProvider.Iface
|
|
|
|
ac.UDPPort = jsonConf.BootProvider.Port
|
2023-09-16 11:52:05 +00:00
|
|
|
ac.UDPSrcAddr = jsonConf.BootProvider.SrcAddr
|
2023-07-30 09:20:45 +00:00
|
|
|
ac.DataFilepath = jsonConf.Storage.Path
|
2024-03-24 12:37:40 +00:00
|
|
|
ac.StaticDir = jsonConf.Storage.StaticDir
|
2024-04-30 16:43:01 +00:00
|
|
|
ac.HomeAssistantEnabled = jsonConf.HomeAssistant.Enabled
|
|
|
|
ac.HomeAssistantHost = jsonConf.HomeAssistant.Host
|
|
|
|
ac.HomeAssistantToken = jsonConf.HomeAssistant.APIToken
|
2023-07-23 08:49:57 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var defaultConfig AppConfig = AppConfig{
|
2023-07-29 19:23:36 +00:00
|
|
|
LogLevel: logrus.InfoLevel,
|
|
|
|
ServerMode: ModeNet,
|
2023-07-30 09:20:45 +00:00
|
|
|
DataFilepath: "boot_options.json",
|
2023-07-29 19:23:36 +00:00
|
|
|
Host: "0.0.0.0",
|
2024-03-27 21:07:09 +00:00
|
|
|
PublicHost: "http://127.0.0.1:5000",
|
2023-07-29 19:23:36 +00:00
|
|
|
Port: 5000,
|
|
|
|
UPDMcastGroup: "ff02::abcd:1234",
|
|
|
|
UDPPort: 42,
|
|
|
|
UDPIface: "eth0",
|
2024-03-24 12:37:40 +00:00
|
|
|
StaticDir: "./static",
|
2023-07-23 08:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func New(filepath string) (*AppConfig, error) {
|
|
|
|
content, err := os.ReadFile(filepath)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, fs.ErrNotExist) {
|
|
|
|
conf := defaultConfig
|
|
|
|
return &conf, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("failed to read config file %q: %w", filepath, err)
|
|
|
|
}
|
|
|
|
var conf AppConfig
|
|
|
|
if err := json.Unmarshal(content, &conf); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
|
|
|
}
|
|
|
|
return &conf, nil
|
|
|
|
}
|