From 2f1267016da2511edbbd92e2d22d39a854efbe07 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 15 Sep 2024 00:49:51 -0500 Subject: [PATCH 1/7] change modd.conf to not build extra binary --- modd.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modd.conf b/modd.conf index 1258eba..a6fee61 100644 --- a/modd.conf +++ b/modd.conf @@ -9,6 +9,5 @@ **/*.go .env { prep: go mod tidy prep: go test @dirmods - prep: go build - daemon +sigterm: ./hasshelper -c ../hasshelper.toml + daemon +sigterm: go run ./main.go -c ../hasshelper.toml } From d7ea0508cf776c5e1c22eaa548f53332670c50b3 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 15 Sep 2024 00:51:18 -0500 Subject: [PATCH 2/7] move web server to goroutine --- cmd/root.go | 47 ++++++++++++++++++++++++----------------------- web/server.go | 31 +++++++++++++++++++------------ 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 3fc47a1..6990600 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,13 +1,13 @@ package cmd import ( + "context" "fmt" "log" "log/slog" - "math/rand" "os" - "strings" - "time" + "os/signal" + "syscall" "git.bloy.org/mike/hasshelper/web" "github.com/spf13/cobra" @@ -22,30 +22,32 @@ var rootCmd = &cobra.Command{ Run: rootCmdRun, } -func logLevelVar(str string) slog.Level { - levelUpper := strings.ToUpper(str) - switch levelUpper { - case "DEBUG": - return slog.LevelDebug - case "INFO": - return slog.LevelInfo - case "WARN": - return slog.LevelWarn - case "ERROR": - return slog.LevelError - default: - return slog.LevelInfo - } -} - func rootCmdRun(cmd *cobra.Command, args []string) { - logLevel := logLevelVar(viper.GetString("loglevel")) + var logLevel slog.Level + logLevel.UnmarshalText([]byte(viper.GetString("loglevel"))) logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel})) logger.Info("HASSHelper startup", "version", viper.GetString("version")) exitchan := make(chan bool) - web.Run(logger, exitchan) - <-exitchan // run the main command until one of the goroutines is done + signalchan := make(chan os.Signal, 1) + done := make(chan bool) + signal.Notify(signalchan, syscall.SIGINT, syscall.SIGTERM) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + web.Run(logger, exitchan, ctx) + go func() { + select { + case <-signalchan: + logger.Warn("received interrupt. Exiting") + cancel() + done <- true + case <-exitchan: + logger.Error("unexpected exit of component") + cancel() + done <- true + } + }() + <-done } // Execute will kick off cobra's processing of the root command @@ -100,5 +102,4 @@ func initConfig() { os.Exit(1) } } - rand.Seed(time.Now().UnixNano()) } diff --git a/web/server.go b/web/server.go index 5197e14..bb8151a 100644 --- a/web/server.go +++ b/web/server.go @@ -3,10 +3,12 @@ package web import ( "fmt" "log/slog" + "net" "net/http" "time" "github.com/spf13/viper" + "golang.org/x/net/context" ) type configObj struct { @@ -19,7 +21,7 @@ var config = configObj{} // Run starts up the webserver part of hasshelper. It writes to exitch if // the webserver ends unexpectedly. Config values will be read from viper. -func Run(rootLogger *slog.Logger, exitch chan bool) { +func Run(rootLogger *slog.Logger, exitch chan bool, ctx context.Context) { rootLogger = rootLogger.With("component", "web") config.logger = rootLogger config.port = viper.GetInt("webserver_port") @@ -30,15 +32,21 @@ func Run(rootLogger *slog.Logger, exitch chan bool) { var logger = config.logger logger.Info("Webserver startup", "port", config.port, "imageDir", config.imageDir) - - addr := fmt.Sprintf(":%d", config.port) - - if err := http.ListenAndServe(addr, middleware(http.DefaultServeMux)); err != nil { - logger.Error("Webserver fatal error", "err", err) - } else { - logger.Info("Webserver shutting down") - } - exitch <- true + go func() { + server := http.Server{ + Addr: fmt.Sprintf(":%d", config.port), + Handler: middleware(http.DefaultServeMux), + BaseContext: func(net.Listener) context.Context { + return ctx + }, + } + if err := server.ListenAndServe(); err != nil { + logger.Error("Webserver fatal error", "err", err) + } else { + logger.Info("Webserver shutting down") + } + exitch <- true + }() } func middleware(next http.Handler) http.Handler { @@ -46,8 +54,7 @@ func middleware(next http.Handler) http.Handler { logger := config.logger. WithGroup("request"). With("method", r.Method, - "url", r.URL, - "remote", r.RemoteAddr) + "url", r.URL) logger.Info("Starting web request") start := time.Now() next.ServeHTTP(w, r) From d22da95cce996c8420c45a92f8f7dcd80797f93c Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 15 Sep 2024 00:51:34 -0500 Subject: [PATCH 3/7] start making kiosk mode --- kiosk/kiosk.go | 29 +++++++++++++++++++++++++++++ kiosk/mqtt.go | 27 +++++++++++++++++++++++++++ mqtt/mqtt.go | 7 ------- 3 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 kiosk/kiosk.go create mode 100644 kiosk/mqtt.go delete mode 100644 mqtt/mqtt.go diff --git a/kiosk/kiosk.go b/kiosk/kiosk.go new file mode 100644 index 0000000..e5ee8e0 --- /dev/null +++ b/kiosk/kiosk.go @@ -0,0 +1,29 @@ +package kiosk + +import ( + "log/slog" + + "github.com/spf13/viper" +) + +type handler func(area string, present bool) + +type configObj struct { + logger *slog.Logger + broker string + username string + password string + presenceTopic string +} + +var config = configObj{} + +func Run(rootLogger *slog.Logger, exitch chan bool) { + config.logger = rootLogger.With("component", "kiosk") + config.broker = viper.GetString("mqtt_broker_url") + config.username = viper.GetString("mqtt_broker_user") + config.password = viper.GetString("mqtt_broker_password") + config.presenceTopic = viper.GetString("mqtt_presence_topic") + brokerConsume() + exitch <- true +} diff --git a/kiosk/mqtt.go b/kiosk/mqtt.go new file mode 100644 index 0000000..88d6749 --- /dev/null +++ b/kiosk/mqtt.go @@ -0,0 +1,27 @@ +package kiosk + +import ( + "fmt" + "os" + + MQTT "github.com/eclipse/paho.mqtt.golang" +) + +func brokerConsume() { + opts := MQTT.NewClientOptions() + opts.AddBroker(config.broker) + hostname, err := os.Hostname() + if err != nil { + panic(err) + } + opts.SetClientID(fmt.Sprintf("hasskiosk-%s-%d", hostname, os.Getpid())) + opts.SetUsername(config.username) + opts.SetPassword(config.password) + opts.SetDefaultPublishHandler(func(client MQTT.Client, msg MQTT.Message) { + + }) +} + +func defaultMQTTHandler(client MQTT.Client, msg MQTT.Message) { + +} diff --git a/mqtt/mqtt.go b/mqtt/mqtt.go deleted file mode 100644 index 4d563b5..0000000 --- a/mqtt/mqtt.go +++ /dev/null @@ -1,7 +0,0 @@ -package mqtt - -import mqtt "github.com/eclipse/paho.mqtt.golang" - -func init() { - mqtt.NewClient() -} From f085312e13a7eefea38a33608415a93e910fdbe6 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 15 Sep 2024 12:25:06 -0500 Subject: [PATCH 4/7] mqtt reading from broker --- cmd/root.go | 33 +++++++++++++++++++++------------ go.mod | 2 ++ go.sum | 4 ++++ kiosk/kiosk.go | 6 ++++-- kiosk/mqtt.go | 36 +++++++++++++++++++++++++++++++----- modd.conf | 2 +- 6 files changed, 63 insertions(+), 20 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 6990600..ff73335 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,7 +9,10 @@ import ( "os/signal" "syscall" + "git.bloy.org/mike/hasshelper/kiosk" "git.bloy.org/mike/hasshelper/web" + _ "github.com/joho/godotenv/autoload" + "github.com/lmittmann/tint" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -25,16 +28,19 @@ var rootCmd = &cobra.Command{ func rootCmdRun(cmd *cobra.Command, args []string) { var logLevel slog.Level logLevel.UnmarshalText([]byte(viper.GetString("loglevel"))) - logger := slog.New(slog.NewTextHandler(os.Stdout, - &slog.HandlerOptions{Level: logLevel})) + logger := slog.New( + tint.NewHandler(os.Stdout, &tint.Options{ + Level: logLevel, + TimeFormat: "2006-01-02T15:04:05.999", + NoColor: viper.GetString("deployment") == "prod", + })) logger.Info("HASSHelper startup", "version", viper.GetString("version")) exitchan := make(chan bool) signalchan := make(chan os.Signal, 1) - done := make(chan bool) + done := make(chan bool, 2) signal.Notify(signalchan, syscall.SIGINT, syscall.SIGTERM) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - web.Run(logger, exitchan, ctx) go func() { select { case <-signalchan: @@ -47,6 +53,9 @@ func rootCmdRun(cmd *cobra.Command, args []string) { done <- true } }() + go web.Run(logger, exitchan, ctx) + go kiosk.Run(logger, exitchan, ctx) + logger.Debug("Waiting for exit") <-done } @@ -59,26 +68,26 @@ func Execute() { } func init() { - rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", - "config file (default is $HOME/.config/hasshelper/config.toml)") - cobra.OnInitialize(initConfig) - const dirName = "hasshelper" var userConfigDir, err = os.UserConfigDir() + const dirName = "hasshelper" + var defDir = fmt.Sprintf("%s%c%s", "/etc", os.PathSeparator, dirName) if err == nil { - viper.AddConfigPath( - fmt.Sprintf("%s%c%s", userConfigDir, os.PathSeparator, dirName)) + defDir = fmt.Sprintf("%s%c%s", userConfigDir, os.PathSeparator, dirName) + viper.AddConfigPath(defDir) } else { log.Println("could not locate user config dir:", err) } + rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", + fmt.Sprintf("config file (default is %s%c%s)", defDir, os.PathSeparator, "hasshelper.toml")) + cobra.OnInitialize(initConfig) viper.AddConfigPath(fmt.Sprintf("/etc%c%s", os.PathSeparator, dirName)) - viper.SetConfigName("config.toml") - viper.SetEnvPrefix("hasshelper") } func initConfig() { viper.Set("version", gitVersion) viper.SetDefault("deployment", "prod") viper.SetDefault("loglevel", "info") + viper.SetEnvPrefix("HASS") viper.AutomaticEnv() if cfgFile != "" { viper.SetConfigFile(cfgFile) diff --git a/go.mod b/go.mod index c26d792..0228c4b 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,8 @@ require ( github.com/cortesi/devd v0.0.0-20200427000907-c1a3bfba27d8 github.com/cortesi/modd v0.8.1 github.com/eclipse/paho.mqtt.golang v1.5.0 + github.com/joho/godotenv v1.5.1 + github.com/lmittmann/tint v1.0.5 github.com/mdomke/git-semver/v6 v6.9.0 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 diff --git a/go.sum b/go.sum index 1d98eae..7db1df9 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI= github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= @@ -120,6 +122,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw= +github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= diff --git a/kiosk/kiosk.go b/kiosk/kiosk.go index e5ee8e0..64a20cb 100644 --- a/kiosk/kiosk.go +++ b/kiosk/kiosk.go @@ -1,6 +1,7 @@ package kiosk import ( + "context" "log/slog" "github.com/spf13/viper" @@ -18,12 +19,13 @@ type configObj struct { var config = configObj{} -func Run(rootLogger *slog.Logger, exitch chan bool) { +func Run(rootLogger *slog.Logger, exitch chan bool, ctx context.Context) { config.logger = rootLogger.With("component", "kiosk") config.broker = viper.GetString("mqtt_broker_url") config.username = viper.GetString("mqtt_broker_user") config.password = viper.GetString("mqtt_broker_password") config.presenceTopic = viper.GetString("mqtt_presence_topic") - brokerConsume() + config.logger.Info("starting MQTT broker client") + brokerConsume(ctx) exitch <- true } diff --git a/kiosk/mqtt.go b/kiosk/mqtt.go index 88d6749..0eee1c5 100644 --- a/kiosk/mqtt.go +++ b/kiosk/mqtt.go @@ -1,27 +1,53 @@ package kiosk import ( + "context" "fmt" "os" MQTT "github.com/eclipse/paho.mqtt.golang" ) -func brokerConsume() { +func brokerConsume(ctx context.Context) { + logger := config.logger opts := MQTT.NewClientOptions() opts.AddBroker(config.broker) hostname, err := os.Hostname() if err != nil { panic(err) } + messages := make(chan [2]string) opts.SetClientID(fmt.Sprintf("hasskiosk-%s-%d", hostname, os.Getpid())) opts.SetUsername(config.username) opts.SetPassword(config.password) opts.SetDefaultPublishHandler(func(client MQTT.Client, msg MQTT.Message) { - + messages <- [2]string{msg.Topic(), string(msg.Payload())} }) -} - -func defaultMQTTHandler(client MQTT.Client, msg MQTT.Message) { + done := make(chan bool) + logger.Debug("creating client") + client := MQTT.NewClient(opts) + logger.Debug("starting client") + if token := client.Connect(); token.Wait() && token.Error() != nil { + logger.Error("MQTT client startup problem", "err", token.Error()) + return + } + defer client.Disconnect(250) + if token := client.Subscribe(config.presenceTopic, 1, nil); token.Wait() && token.Error() != nil { + logger.Error("MQTT subscribe error", "err", token.Error()) + return + } + go func() { + for true { + select { + case <-ctx.Done(): + logger.Info("Context shutdown. Exiting MQTT loop") + done <- true + return + case msg := <-messages: + logger.Info("MQTT message received", "topic", msg[0], "body", msg[1]) + } + } + }() + <-done } diff --git a/modd.conf b/modd.conf index a6fee61..11b959e 100644 --- a/modd.conf +++ b/modd.conf @@ -9,5 +9,5 @@ **/*.go .env { prep: go mod tidy prep: go test @dirmods - daemon +sigterm: go run ./main.go -c ../hasshelper.toml + daemon +sigterm: go run ./main.go } From 85abccf14a3ab68bae4567b3d439bd976bede42f Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 29 Sep 2024 12:10:36 -0500 Subject: [PATCH 5/7] config for kiosk handler --- cmd/root.go | 8 +++++++- cmd/root_test.go | 12 ++++++++++++ kiosk/kiosk.go | 14 +++++++++----- modd.conf | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index ff73335..7b748f1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -104,10 +104,16 @@ func initConfig() { "image_dir", "version", "webserver_port", + "mqtt_broker_url", + "mqtt_broker_user", + "mqtt_broker_password", + "mqtt_presence_topic", + "kiosk_cmd_screen_on", + "kiosk_cmd_screen_off", } for _, key := range expected_config { if !viper.IsSet(key) { - fmt.Fprintf(os.Stderr, "Missing configuration value: %s\n", key) + log.Fatalf("Missing configuration value: %s\n", key) os.Exit(1) } } diff --git a/cmd/root_test.go b/cmd/root_test.go index 0f512a0..434e216 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -14,6 +14,12 @@ func TestInitConfig(t *testing.T) { viper.Set("deployment", "testing") viper.Set("image_dir", "/tmp") viper.Set("webserver_port", "8080") + viper.Set("mqtt_broker_url", "mqtt://example.com:1883") + viper.Set("mqtt_broker_user", "testuser") + viper.Set("mqtt_broker_password", "testpass") + viper.Set("mqtt_presence_topic", "home/foo/test") + viper.Set("kiosk_cmd_screen_on", "echo screen on") + viper.Set("kiosk_cmd_screen_off", "echo screen off") initConfig() assert.Equal(t, gitVersion, viper.GetString("version"), "config version mismatch") @@ -25,6 +31,12 @@ func TestInitConfigMissingImageDir(t *testing.T) { viper.Set("deployment", "testing") viper.Set("version", "vTest") viper.Set("webserver_port", "8080") + viper.Set("mqtt_broker_url", "mqtt://example.com:1883") + viper.Set("mqtt_broker_user", "testuser") + viper.Set("mqtt_broker_password", "testpass") + viper.Set("mqtt_presence_topic", "home/foo/test") + viper.Set("kiosk_cmd_screen_on", "echo screen on") + viper.Set("kiosk_cmd_screen_off", "echo screen off") initConfig() return diff --git a/kiosk/kiosk.go b/kiosk/kiosk.go index 64a20cb..e32bf0f 100644 --- a/kiosk/kiosk.go +++ b/kiosk/kiosk.go @@ -10,11 +10,13 @@ import ( type handler func(area string, present bool) type configObj struct { - logger *slog.Logger - broker string - username string - password string - presenceTopic string + logger *slog.Logger + broker string + username string + password string + presenceTopic string + screen_on_cmd string + screen_off_cmd string } var config = configObj{} @@ -25,6 +27,8 @@ func Run(rootLogger *slog.Logger, exitch chan bool, ctx context.Context) { config.username = viper.GetString("mqtt_broker_user") config.password = viper.GetString("mqtt_broker_password") config.presenceTopic = viper.GetString("mqtt_presence_topic") + config.screen_on_cmd = viper.GetString("kiosk_cmd_screen_on") + config.screen_off_cmd = viper.GetString("kiosk_cmd_screen_off") config.logger.Info("starting MQTT broker client") brokerConsume(ctx) exitch <- true diff --git a/modd.conf b/modd.conf index 11b959e..47cfce8 100644 --- a/modd.conf +++ b/modd.conf @@ -9,5 +9,5 @@ **/*.go .env { prep: go mod tidy prep: go test @dirmods - daemon +sigterm: go run ./main.go + daemon +sigterm: go run ./main.go } From f22890bb66213a039b72afe597ff1e1bb2d78415 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 29 Sep 2024 13:07:24 -0500 Subject: [PATCH 6/7] add shell config --- cmd/root.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index 7b748f1..a779e31 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -87,6 +87,7 @@ func initConfig() { viper.Set("version", gitVersion) viper.SetDefault("deployment", "prod") viper.SetDefault("loglevel", "info") + viper.SetDefault("kiosk_cmd_shell", "bash") viper.SetEnvPrefix("HASS") viper.AutomaticEnv() if cfgFile != "" { @@ -108,6 +109,7 @@ func initConfig() { "mqtt_broker_user", "mqtt_broker_password", "mqtt_presence_topic", + "kiosk_cmd_shell", "kiosk_cmd_screen_on", "kiosk_cmd_screen_off", } From 19322dd35079c0b1771735a4c1c20b7ee4d0791d Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 29 Sep 2024 13:08:20 -0500 Subject: [PATCH 7/7] kiosk presence helper added --- .gitignore | 2 ++ kiosk/kiosk.go | 24 ++++++++++++++++++++++++ kiosk/mqtt.go | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f4fd54..346b10f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ go.work /cmd/git_version.go /dist .env +screen_off +screen_on diff --git a/kiosk/kiosk.go b/kiosk/kiosk.go index e32bf0f..05fa57b 100644 --- a/kiosk/kiosk.go +++ b/kiosk/kiosk.go @@ -3,6 +3,7 @@ package kiosk import ( "context" "log/slog" + "os/exec" "github.com/spf13/viper" ) @@ -15,6 +16,7 @@ type configObj struct { username string password string presenceTopic string + shell string screen_on_cmd string screen_off_cmd string } @@ -27,9 +29,31 @@ func Run(rootLogger *slog.Logger, exitch chan bool, ctx context.Context) { config.username = viper.GetString("mqtt_broker_user") config.password = viper.GetString("mqtt_broker_password") config.presenceTopic = viper.GetString("mqtt_presence_topic") + config.shell = viper.GetString("kiosk_cmd_shell") config.screen_on_cmd = viper.GetString("kiosk_cmd_screen_on") config.screen_off_cmd = viper.GetString("kiosk_cmd_screen_off") config.logger.Info("starting MQTT broker client") brokerConsume(ctx) exitch <- true } + +func handlePresenceMessage(msg [2]string) { + logger := config.logger + logger.Debug("received presence message", "msg", msg) + cmdStr := "" + switch msg[1] { + case "on": + cmdStr = config.screen_on_cmd + case "off": + cmdStr = config.screen_off_cmd + default: + logger.Warn("recieved unexpected presence message", "msg", msg) + return + } + logger.Info("Presence change event", "presence", msg[1], "command", cmdStr) + cmd := exec.Command(config.shell, "-c", cmdStr) + err := cmd.Run() + if err != nil { + logger.Error("error while executing command", "msg", msg, "command", cmdStr, "err", err) + } +} diff --git a/kiosk/mqtt.go b/kiosk/mqtt.go index 0eee1c5..cdc97ce 100644 --- a/kiosk/mqtt.go +++ b/kiosk/mqtt.go @@ -45,7 +45,7 @@ func brokerConsume(ctx context.Context) { done <- true return case msg := <-messages: - logger.Info("MQTT message received", "topic", msg[0], "body", msg[1]) + go handlePresenceMessage(msg) } } }()