backup
This commit is contained in:
parent
b250a6b3c8
commit
081626b434
5 changed files with 137 additions and 14 deletions
|
@ -60,21 +60,29 @@ type jsonConf struct {
|
||||||
McastGroup string `json:"multicast_group"`
|
McastGroup string `json:"multicast_group"`
|
||||||
SrcAddr string `json:"src_addr"`
|
SrcAddr string `json:"src_addr"`
|
||||||
} `json:"boot_provider"`
|
} `json:"boot_provider"`
|
||||||
|
HomeAssistant struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
APIToken string `json:"token"`
|
||||||
|
} `json:"home_assistant"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
LogLevel logrus.Level
|
LogLevel logrus.Level
|
||||||
ServerMode ListeningMode
|
ServerMode ListeningMode
|
||||||
DataFilepath string
|
DataFilepath string
|
||||||
StaticDir string
|
StaticDir string
|
||||||
Host string
|
Host string
|
||||||
PublicHost string
|
PublicHost string
|
||||||
Port int
|
Port int
|
||||||
SockPath string
|
SockPath string
|
||||||
UPDMcastGroup string
|
UPDMcastGroup string
|
||||||
UDPPort int
|
UDPPort int
|
||||||
UDPIface string
|
UDPIface string
|
||||||
UDPSrcAddr string
|
UDPSrcAddr string
|
||||||
|
HomeAssistantEnabled bool
|
||||||
|
HomeAssistantHost string
|
||||||
|
HomeAssistantToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLevel(lvlStr string) logrus.Level {
|
func parseLevel(lvlStr string) logrus.Level {
|
||||||
|
@ -108,6 +116,9 @@ func (ac *AppConfig) UnmarshalJSON(data []byte) error {
|
||||||
ac.UDPSrcAddr = jsonConf.BootProvider.SrcAddr
|
ac.UDPSrcAddr = jsonConf.BootProvider.SrcAddr
|
||||||
ac.DataFilepath = jsonConf.Storage.Path
|
ac.DataFilepath = jsonConf.Storage.Path
|
||||||
ac.StaticDir = jsonConf.Storage.StaticDir
|
ac.StaticDir = jsonConf.Storage.StaticDir
|
||||||
|
ac.HomeAssistantEnabled = jsonConf.HomeAssistant.Enabled
|
||||||
|
ac.HomeAssistantHost = jsonConf.HomeAssistant.Host
|
||||||
|
ac.HomeAssistantToken = jsonConf.HomeAssistant.APIToken
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"git.faercol.me/faercol/http-boot-server/bootserver/config"
|
||||||
"git.faercol.me/faercol/http-boot-server/bootserver/helpers"
|
"git.faercol.me/faercol/http-boot-server/bootserver/helpers"
|
||||||
|
"git.faercol.me/faercol/http-boot-server/bootserver/homeassistant"
|
||||||
"git.faercol.me/faercol/http-boot-server/bootserver/services"
|
"git.faercol.me/faercol/http-boot-server/bootserver/services"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -22,13 +24,15 @@ type setBootOptionPayload struct {
|
||||||
|
|
||||||
type BootController struct {
|
type BootController struct {
|
||||||
clientService *services.ClientHandlerService
|
clientService *services.ClientHandlerService
|
||||||
|
appConf *config.AppConfig
|
||||||
l *logrus.Logger
|
l *logrus.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBootController(logger *logrus.Logger, service *services.ClientHandlerService) *BootController {
|
func NewBootController(logger *logrus.Logger, service *services.ClientHandlerService, conf *config.AppConfig) *BootController {
|
||||||
return &BootController{
|
return &BootController{
|
||||||
clientService: service,
|
clientService: service,
|
||||||
l: logger,
|
l: logger,
|
||||||
|
appConf: conf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +65,18 @@ func (bc *BootController) setBootOption(w http.ResponseWriter, r *http.Request)
|
||||||
return http.StatusInternalServerError, nil, fmt.Errorf("failed to set boot option for client: %w", err)
|
return http.StatusInternalServerError, nil, fmt.Errorf("failed to set boot option for client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bc.appConf.HomeAssistantEnabled {
|
||||||
|
bc.l.Debug("Notifying HomeAssistant of change")
|
||||||
|
newConf, err := bc.clientService.GetClientConfig(clientID)
|
||||||
|
if err != nil {
|
||||||
|
bc.l.Errorf("Failed to get new config to send to HA: %s", err.Error())
|
||||||
|
} else {
|
||||||
|
if err := homeassistant.New(bc.appConf).SendBootOption(r.Context(), newConf.Name, newConf.Options[newConf.SelectedOption].Name); err != nil {
|
||||||
|
bc.l.Errorf("Failed to notify HA: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return http.StatusAccepted, nil, nil
|
return http.StatusAccepted, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
80
bootserver/homeassistant/sender..go
Normal file
80
bootserver/homeassistant/sender..go
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package homeassistant
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.faercol.me/faercol/http-boot-server/bootserver/config"
|
||||||
|
"git.faercol.me/faercol/http-boot-server/bootserver/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Entity struct {
|
||||||
|
State string `json:"state"`
|
||||||
|
ID string `json:"-"`
|
||||||
|
Attributes map[string]string `json:"attributes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBootOptionEntity(device, option string) Entity {
|
||||||
|
return Entity{
|
||||||
|
State: option,
|
||||||
|
ID: "httpboot." + device,
|
||||||
|
Attributes: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HomeAssistantExporter struct {
|
||||||
|
clt *http.Client
|
||||||
|
baseURL string
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(conf *config.AppConfig) *HomeAssistantExporter {
|
||||||
|
clt := http.Client{}
|
||||||
|
return &HomeAssistantExporter{
|
||||||
|
clt: &clt,
|
||||||
|
baseURL: conf.HomeAssistantHost,
|
||||||
|
token: conf.HomeAssistantToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *HomeAssistantExporter) SendBootOption(ctx context.Context, device string, option string) error {
|
||||||
|
subCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
entity := newBootOptionEntity(device, option)
|
||||||
|
|
||||||
|
dat, err := json.Marshal(entity)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(subCtx, http.MethodPost, e.baseURL+"/api/states/"+entity.ID, bytes.NewBuffer(dat))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", "Bearer "+e.token)
|
||||||
|
|
||||||
|
resp, err := e.clt.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusOK:
|
||||||
|
logger.L.Debugf("Updated boot info for device %s to %s", device, option)
|
||||||
|
case http.StatusCreated:
|
||||||
|
logger.L.Debugf("Created boot info for device %s with value %s", device, option)
|
||||||
|
default:
|
||||||
|
respBod, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unexpected returncode %d (%s)", resp.StatusCode, string(respBod))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.faercol.me/faercol/http-boot-server/bootserver/config"
|
"git.faercol.me/faercol/http-boot-server/bootserver/config"
|
||||||
|
"git.faercol.me/faercol/http-boot-server/bootserver/homeassistant"
|
||||||
"git.faercol.me/faercol/http-boot-server/bootserver/logger"
|
"git.faercol.me/faercol/http-boot-server/bootserver/logger"
|
||||||
"git.faercol.me/faercol/http-boot-server/bootserver/server"
|
"git.faercol.me/faercol/http-boot-server/bootserver/server"
|
||||||
"git.faercol.me/faercol/http-boot-server/bootserver/services"
|
"git.faercol.me/faercol/http-boot-server/bootserver/services"
|
||||||
|
@ -61,6 +62,21 @@ func main() {
|
||||||
logger.L.Fatalf("Failed to start UDP listener: %s", err.Error())
|
logger.L.Fatalf("Failed to start UDP listener: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.HomeAssistantEnabled {
|
||||||
|
logger.L.Info("Home assistant integration enabled, sending current configuration to the host")
|
||||||
|
haClt := homeassistant.New(conf)
|
||||||
|
cltSrv := services.NewClientHandlerService(conf.DataFilepath, logger.L)
|
||||||
|
clts, err := cltSrv.GetAllClientConfig()
|
||||||
|
if err != nil {
|
||||||
|
logger.L.Fatalf("Failed to get current clients from the storage: %s", err.Error())
|
||||||
|
}
|
||||||
|
for _, c := range clts {
|
||||||
|
if err := haClt.SendBootOption(context.Background(), c.Name, c.Options[c.SelectedOption].Name); err != nil {
|
||||||
|
logger.L.Errorf("Failed to send config to homeassistant: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
go s.Run(mainCtx)
|
go s.Run(mainCtx)
|
||||||
go listener.Run(mainCtx)
|
go listener.Run(mainCtx)
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ func New(appConf *config.AppConfig, logger *logrus.Logger) (*Server, error) {
|
||||||
controllers := map[string]http.Handler{
|
controllers := map[string]http.Handler{
|
||||||
client.EnrollRoute: middlewares.WithLogger(client.NewEnrollController(logger, service, appConf.UDPPort, appConf.UPDMcastGroup), logger),
|
client.EnrollRoute: middlewares.WithLogger(client.NewEnrollController(logger, service, appConf.UDPPort, appConf.UPDMcastGroup), logger),
|
||||||
client.ConfigRoute: middlewares.WithLogger(client.NewGetConfigController(logger, service, appConf), logger),
|
client.ConfigRoute: middlewares.WithLogger(client.NewGetConfigController(logger, service, appConf), logger),
|
||||||
client.SetBootRoute: middlewares.WithLogger(client.NewBootController(logger, service), logger),
|
client.SetBootRoute: middlewares.WithLogger(client.NewBootController(logger, service, appConf), logger),
|
||||||
ui.StaticRoute: middlewares.WithLogger(ui.NewStaticController(appConf.StaticDir), logger),
|
ui.StaticRoute: middlewares.WithLogger(ui.NewStaticController(appConf.StaticDir), logger),
|
||||||
ui.UIRoute: middlewares.WithLogger(ui.NewUIController(logger, service, appConf.StaticDir), logger),
|
ui.UIRoute: middlewares.WithLogger(ui.NewUIController(logger, service, appConf.StaticDir), logger),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue