Further implementation of config management

This commit is contained in:
KemoNine 2020-09-03 21:01:13 -04:00
parent 1b5d77e07a
commit fffd67f8c0
5 changed files with 117 additions and 62 deletions

View File

@ -9,7 +9,8 @@ The GUI will work off a config similar to the following. Use the ```generate con
```
[slideshow]
duration = "300s"
slideinterval = "300s"
restartinterval = "7d"
[hdmi]
# These are SYSTEMD.TIME formatted times

View File

@ -15,27 +15,6 @@ import (
"git.kemonine.info/PiFrame/ui"
)
const (
CLI_FLAG_CONFIG_ONLY = "config-ui-only"
)
const (
CONFIG_FILE_PATH = "/etc/default/pf.toml"
CONFIG_KEY_SLIDESHOW_DURATION = "slideshow.duration"
CONFIG_KEY_HDMI_OFF = "hdmi.off"
CONFIG_KEY_HDMI_ON = "hdmi.on"
CONFIG_KEY_ALBUMS_ROOT = "albums.root"
CONFIG_KEY_ALBUMS_SELECTED = "albums.selected"
)
const (
DEFAULT_SLIDESHOW_DURATION = "300s"
DEFAULT_HDMI_OFF = "*-*-* 00:00:00"
DEFAULT_HDMI_ON = "*-*-* 06:00:00"
DEFAULT_ALBUMS_ROOT = "/tank/pictures"
DEFAULT_ALBUM_SELECTED = "/"
)
func main() {
// Command line flag handler
f := flag.NewFlagSet("piframe", flag.ContinueOnError)
@ -44,8 +23,8 @@ func main() {
os.Exit(0)
}
// Command line flags
f.Bool(CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
cliFlag := f.Lookup(CLI_FLAG_CONFIG_ONLY)
f.Bool(ui.CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
cliFlag := f.Lookup(ui.CLI_FLAG_CONFIG_ONLY)
if cliFlag != nil {
cliFlag.NoOptDefVal = "true"
}
@ -57,23 +36,22 @@ func main() {
// Setup some defaults
pfConfig.Load(confmap.Provider(map[string]interface{}{
CONFIG_KEY_SLIDESHOW_DURATION: DEFAULT_SLIDESHOW_DURATION,
CONFIG_KEY_HDMI_OFF: DEFAULT_HDMI_OFF,
CONFIG_KEY_HDMI_ON: DEFAULT_HDMI_ON,
CONFIG_KEY_ALBUMS_ROOT: DEFAULT_ALBUMS_ROOT,
CONFIG_KEY_ALBUMS_SELECTED: []string{DEFAULT_ALBUM_SELECTED},
ui.CONFIG_KEY_SLIDESHOW_INTERVAL: ui.DEFAULT_SLIDESHOW_INTERVAL,
ui.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL: ui.DEFAULT_SLIDESHOW_RESTART_INTERVAL,
ui.CONFIG_KEY_HDMI_OFF: ui.DEFAULT_HDMI_OFF,
ui.CONFIG_KEY_HDMI_ON: ui.DEFAULT_HDMI_ON,
ui.CONFIG_KEY_ALBUMS_ROOT: ui.DEFAULT_ALBUMS_ROOT,
ui.CONFIG_KEY_ALBUMS_SELECTED: []string{ui.DEFAULT_ALBUM_SELECTED},
}, "."), nil)
// Bring in /etc/defaults/pf.toml if it exists
configFileProvider := file.Provider(CONFIG_FILE_PATH)
_, err := os.Stat(CONFIG_FILE_PATH)
if err != nil {
if os.IsNotExist(err) {
// log.Printf("%s does not exist, USING DEFAULTS", CONFIG_FILE_PATH)
} else {
if errConfigFile := pfConfig.Load(configFileProvider, toml.Parser()); errConfigFile != nil {
log.Fatalf("Error loading config : %s", err)
}
configFileProvider := file.Provider(ui.CONFIG_FILE_PATH)
_, err := os.Stat(ui.CONFIG_FILE_PATH)
if os.IsNotExist(err) {
//log.Printf("%s does not exist, USING DEFAULTS", ui.CONFIG_FILE_PATH)
} else {
if errConfigFile := pfConfig.Load(configFileProvider, toml.Parser()); errConfigFile != nil {
log.Fatalf("Error loading config : %s", err)
}
}
@ -92,9 +70,9 @@ func main() {
log.Fatalf("Error loading command line flags : %s", err)
}
if !pfConfig.Bool(CLI_FLAG_CONFIG_ONLY) {
ui.Slideshow()
if !pfConfig.Bool(ui.CLI_FLAG_CONFIG_ONLY) {
ui.Slideshow(pfConfig)
}
ui.ConfigGui()
ui.ConfigGui(pfConfig)
}

View File

@ -14,6 +14,7 @@ import (
"github.com/gdamore/tcell"
"github.com/guillermo/go.procmeminfo"
"github.com/knadh/koanf"
"github.com/rivo/tview"
"git.kemonine.info/PiFrame/wifi"
@ -24,7 +25,6 @@ const (
CMD_FINDMNT = "/usr/bin/findmnt"
CMD_VCGENCMD = "/opt/vc/bin/vcgencmd"
FILE_CPU_TEMP = "/sys/class/thermal/thermal_zone0/temp"
ALBUM_ROOT_DIR = "/tank/pictures/"
SYNCTHING_FOLDER_SKIP = ".stfolder"
)
@ -35,7 +35,7 @@ const (
PAGE_POWEROFF = "PAGE_POWEROFF"
)
func ConfigGui() {
func ConfigGui(config *koanf.Koanf) {
// Memory info for status panel
meminfo := &procmeminfo.MemInfo{}
err := meminfo.Update()
@ -80,7 +80,7 @@ func ConfigGui() {
// Get list of all folders that can be used as albums
var albums []string
err = filepath.Walk(ALBUM_ROOT_DIR, func(path string, fi os.FileInfo, err error) error {
err = filepath.Walk(config.String(CONFIG_KEY_ALBUMS_ROOT), func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
@ -88,7 +88,7 @@ func ConfigGui() {
if strings.Contains(path, SYNCTHING_FOLDER_SKIP) {
return nil
}
albumName := strings.TrimPrefix(path, ALBUM_ROOT_DIR)
albumName := strings.TrimPrefix(path, config.String(CONFIG_KEY_ALBUMS_ROOT))
if albumName == "" {
albumName = "Main Folder"
}
@ -154,7 +154,9 @@ func ConfigGui() {
SetTitle("Menu").
SetTitleColor(tcell.ColorAqua)
menu.AddItem("Select Albums", "", '1', nil)
menu.AddItem("Configure WiFi", "", '2', nil)
menu.AddItem("Intervals", "", '2', nil)
menu.AddItem("WiFi", "", '3', nil)
menu.AddItem("HDMI On/Off", "", '5', nil)
// Setup base var for main column so the menu setup is easier to manage
main := tview.NewFlex().
@ -165,6 +167,39 @@ func ConfigGui() {
SetBorder(true).
SetTitleColor(tcell.ColorAqua)
// Select Albums Form
selectAlbumsForm := tview.NewForm()
configSelectedAlbums := config.Strings(CONFIG_KEY_ALBUMS_SELECTED)
for _, album := range albums {
albumSelected := false
for _, configSelectedAlbum := range configSelectedAlbums {
if configSelectedAlbum == "/" {
configSelectedAlbum = "Main Folder"
}
if album == configSelectedAlbum {
albumSelected = true
}
}
selectAlbumsForm.AddCheckbox(album, albumSelected, nil)
}
selectAlbumsForm.AddButton("Apply", nil)
selectAlbumsForm.AddButton("Cancel", func() {
main.Clear()
app.SetFocus(menu)
})
// Slide Interval Form
intervalsForm := tview.NewForm()
configSlideInterval := config.String(CONFIG_KEY_SLIDESHOW_INTERVAL)
configRestartInterval := config.String(CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL)
intervalsForm.AddInputField("Slide", configSlideInterval, 0, nil, nil)
intervalsForm.AddInputField("Restart/Reshuffle", configRestartInterval, 0, nil, nil)
intervalsForm.AddButton("Apply", nil)
intervalsForm.AddButton("Cancel", func() {
main.Clear()
app.SetFocus(menu)
})
// WiFi Config Form
wifiConfigForm := tview.NewForm()
wifiConfigAccessPoint := ""
@ -185,13 +220,14 @@ func ConfigGui() {
app.SetFocus(menu)
})
// Select Albums Form
selectAlbumsForm := tview.NewForm()
for _, album := range albums {
selectAlbumsForm.AddCheckbox(album, true, nil)
}
selectAlbumsForm.AddButton("Apply", nil)
selectAlbumsForm.AddButton("Cancel", func() {
// HDMI On/Off Form
hdmiForm := tview.NewForm()
configHDMIOff := config.String(CONFIG_KEY_HDMI_OFF)
configHDMIOn := config.String(CONFIG_KEY_HDMI_ON)
hdmiForm.AddInputField("HDMI Off Schedule", configHDMIOff, 0, nil, nil)
hdmiForm.AddInputField("HDMI On Schedule", configHDMIOn, 0, nil, nil)
hdmiForm.AddButton("Apply", nil)
hdmiForm.AddButton("Cancel", func() {
main.Clear()
app.SetFocus(menu)
})
@ -204,12 +240,24 @@ func ConfigGui() {
main.AddItem(selectAlbumsForm, 0, 1, true)
app.SetFocus(selectAlbumsForm)
}
if title == "Configure WiFi" {
if title == "WiFi" {
main.SetTitle("Configure WiFi")
main.Clear()
main.AddItem(wifiConfigForm, 0, 1, true)
app.SetFocus(wifiConfigForm)
}
if title == "Intervals" {
main.SetTitle("Configure Intervals")
main.Clear()
main.AddItem(intervalsForm, 0, 1, true)
app.SetFocus(intervalsForm)
}
if title == "HDMI On/Off" {
main.SetTitle("Configure HDMI On/Off")
main.Clear()
main.AddItem(hdmiForm, 0, 1, true)
app.SetFocus(hdmiForm)
}
})
// Side bar fields
@ -364,9 +412,14 @@ func ConfigGui() {
// Override some of the default behavior so up/dn move between fields in forms
// Per API GetFocusedItemIndex on a form will be -1 if a form item isn't currently focused
// We use this as a bit of a cheat to figure out if we're inside of a form that needs better nav options for users (ie. tab doesn't exist on a remote)
wifiField, wifiButton := wifiConfigForm.GetFocusedItemIndex()
albumField, albumButton := selectAlbumsForm.GetFocusedItemIndex()
if wifiField != -1 || wifiButton != -1 || albumField != -1 || albumButton != -1 {
intervalField, intervalButton := intervalsForm.GetFocusedItemIndex()
wifiField, wifiButton := wifiConfigForm.GetFocusedItemIndex()
hdmiField, hdmiButton := hdmiForm.GetFocusedItemIndex()
if (wifiField != -1 || wifiButton != -1 ||
albumField != -1 || albumButton != -1 ||
intervalField != -1 || intervalButton != -1 ||
hdmiField != -1 || hdmiButton != -1) {
switch event.Key() {
case tcell.KeyUp:
return tcell.NewEventKey(tcell.KeyBacktab, 0, event.Modifiers())

24
ui/constants.go Normal file
View File

@ -0,0 +1,24 @@
package ui
const (
CLI_FLAG_CONFIG_ONLY = "config-ui-only"
)
const (
CONFIG_FILE_PATH = "/etc/default/pf.toml"
CONFIG_KEY_SLIDESHOW_INTERVAL = "slideshow.slideinterval"
CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL = "slideshow.restartinterval"
CONFIG_KEY_HDMI_OFF = "hdmi.off"
CONFIG_KEY_HDMI_ON = "hdmi.on"
CONFIG_KEY_ALBUMS_ROOT = "albums.root"
CONFIG_KEY_ALBUMS_SELECTED = "albums.selected"
)
const (
DEFAULT_SLIDESHOW_INTERVAL = "300s"
DEFAULT_SLIDESHOW_RESTART_INTERVAL = "7d"
DEFAULT_HDMI_OFF = "*-*-* 00:00:00"
DEFAULT_HDMI_ON = "*-*-* 06:00:00"
DEFAULT_ALBUMS_ROOT = "/tank/pictures"
DEFAULT_ALBUM_SELECTED = "/"
)

View File

@ -9,14 +9,14 @@ import (
"time"
"github.com/eiannone/keyboard"
"github.com/knadh/koanf"
)
const (
CMD_FIM = "/usr/local/bin/pf-fim.sh"
SLIDESHOW_INTERVAL = 300 * time.Second
CMD_FIM = "/usr/local/bin/pf-fim.sh"
)
func Slideshow() {
func Slideshow(config *koanf.Koanf) {
// fim placeholder so we can operate on it when a exit slideshow is received
var fim *exec.Cmd = nil
@ -32,7 +32,7 @@ func Slideshow() {
}
// Advance slideshow every interval as defined in const()
ticker := time.NewTicker(SLIDESHOW_INTERVAL)
ticker := time.NewTicker(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
stop_ticker := make(chan struct{})
go func() {
for {
@ -68,7 +68,6 @@ func Slideshow() {
if event.Err != nil {
log.Fatalf("Error listening to key events : %s", err)
}
log.Printf("You pressed: key %X\n", event.Key)
// Keys for fim event management (previous/next in particular)
fimKey := ""
@ -100,7 +99,7 @@ func Slideshow() {
if err != nil {
log.Fatalf("Error controlling fim : %s", err)
}
ticker.Reset(SLIDESHOW_INTERVAL)
ticker.Reset(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
}
}
}