Wire up more of the config ; apply hdmi on/off schedules on save

This commit is contained in:
KemoNine 2020-09-04 23:28:01 -04:00
parent 769029b9c2
commit 15dfaa31f9
9 changed files with 148 additions and 40 deletions

View file

@ -12,6 +12,7 @@ import (
"github.com/knadh/koanf/providers/posflag"
flag "github.com/spf13/pflag"
pfconfig "git.kemonine.info/PiFrame/config"
"git.kemonine.info/PiFrame/ui"
)
@ -23,8 +24,8 @@ func main() {
os.Exit(0)
}
// Command line flags
f.Bool(ui.CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
cliFlag := f.Lookup(ui.CLI_FLAG_CONFIG_ONLY)
f.Bool(pfconfig.CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
cliFlag := f.Lookup(pfconfig.CLI_FLAG_CONFIG_ONLY)
if cliFlag != nil {
cliFlag.NoOptDefVal = "true"
}
@ -36,17 +37,17 @@ func main() {
// Setup some defaults
pfConfig.Load(confmap.Provider(map[string]interface{}{
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},
pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL: pfconfig.DEFAULT_SLIDESHOW_INTERVAL,
pfconfig.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL: pfconfig.DEFAULT_SLIDESHOW_RESTART_INTERVAL,
pfconfig.CONFIG_KEY_HDMI_OFF: pfconfig.DEFAULT_HDMI_OFF,
pfconfig.CONFIG_KEY_HDMI_ON: pfconfig.DEFAULT_HDMI_ON,
pfconfig.CONFIG_KEY_ALBUMS_ROOT: pfconfig.DEFAULT_ALBUMS_ROOT,
pfconfig.CONFIG_KEY_ALBUMS_SELECTED: []string{pfconfig.DEFAULT_ALBUM_SELECTED},
}, "."), nil)
// Bring in /etc/defaults/pf.toml if it exists
configFileProvider := file.Provider(ui.CONFIG_FILE_PATH)
_, err := os.Stat(ui.CONFIG_FILE_PATH)
configFileProvider := file.Provider(pfconfig.CONFIG_FILE_PATH)
_, err := os.Stat(pfconfig.CONFIG_FILE_PATH)
if os.IsNotExist(err) {
//log.Printf("%s does not exist, USING DEFAULTS", ui.CONFIG_FILE_PATH)
} else {
@ -70,13 +71,13 @@ func main() {
log.Fatalf("Error loading command line flags : %s", err)
}
if !pfConfig.Bool(ui.CLI_FLAG_CONFIG_ONLY) {
if !pfConfig.Bool(pfconfig.CLI_FLAG_CONFIG_ONLY) {
ui.Slideshow(pfConfig)
}
// Reset the CLI flag so it's never writted to the config as 'true'
pfConfig.Load(confmap.Provider(map[string]interface{}{
ui.CLI_FLAG_CONFIG_ONLY: false,
pfconfig.CLI_FLAG_CONFIG_ONLY: false,
}, "."), nil)
ui.ConfigGui(pfConfig)

3
config/README.md Normal file
View file

@ -0,0 +1,3 @@
# config
Mini module for working with PiFrame configuration file.

View file

@ -1,4 +1,4 @@
package ui
package config
const (
CLI_FLAG_CONFIG_ONLY = "config-ui-only"

View file

@ -1,22 +1,25 @@
package ui
import (
"bytes"
"fmt"
"log"
"math"
"net"
"os"
"os/exec"
"io/ioutil"
"path/filepath"
"strings"
"text/template"
"github.com/gdamore/tcell"
"github.com/guillermo/go.procmeminfo"
"github.com/knadh/koanf"
"github.com/knadh/koanf/parsers/toml"
"github.com/knadh/koanf/providers/confmap"
"github.com/rivo/tview"
"git.kemonine.info/PiFrame/config"
"git.kemonine.info/PiFrame/utils"
"git.kemonine.info/PiFrame/wifi"
)
@ -35,7 +38,7 @@ const (
PAGE_POWEROFF = "PAGE_POWEROFF"
)
func ConfigGui(config *koanf.Koanf) {
func ConfigGui(pfconfig *koanf.Koanf) {
// Memory info for status panel
meminfo := &procmeminfo.MemInfo{}
err := meminfo.Update()
@ -67,7 +70,7 @@ func ConfigGui(config *koanf.Koanf) {
// Get list of all folders that can be used as albums
var albums []string
err = filepath.Walk(config.String(CONFIG_KEY_ALBUMS_ROOT), func(path string, fi os.FileInfo, err error) error {
err = filepath.Walk(pfconfig.String(config.CONFIG_KEY_ALBUMS_ROOT), func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
@ -75,7 +78,7 @@ func ConfigGui(config *koanf.Koanf) {
if strings.Contains(path, SYNCTHING_FOLDER_SKIP) {
return nil
}
albumName := strings.TrimPrefix(path, config.String(CONFIG_KEY_ALBUMS_ROOT))
albumName := strings.TrimPrefix(path, pfconfig.String(config.CONFIG_KEY_ALBUMS_ROOT))
if albumName == "" {
albumName = "Main Folder"
}
@ -166,7 +169,7 @@ func ConfigGui(config *koanf.Koanf) {
// Select Albums Form
selectAlbumsForm := tview.NewForm()
configSelectedAlbums := config.Strings(CONFIG_KEY_ALBUMS_SELECTED)
configSelectedAlbums := pfconfig.Strings(config.CONFIG_KEY_ALBUMS_SELECTED)
for _, album := range albums {
albumSelected := false
for _, configSelectedAlbum := range configSelectedAlbums {
@ -187,8 +190,8 @@ func ConfigGui(config *koanf.Koanf) {
// Slide Interval Form
intervalsForm := tview.NewForm()
configSlideInterval := config.String(CONFIG_KEY_SLIDESHOW_INTERVAL)
configRestartInterval := config.String(CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL)
configSlideInterval := pfconfig.String(config.CONFIG_KEY_SLIDESHOW_INTERVAL)
configRestartInterval := pfconfig.String(config.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL)
intervalsForm.AddInputField("Slide", configSlideInterval, 0, nil, func(value string) {
configSlideInterval = value
})
@ -223,8 +226,8 @@ func ConfigGui(config *koanf.Koanf) {
// HDMI On/Off Form
hdmiForm := tview.NewForm()
configHDMIOff := config.String(CONFIG_KEY_HDMI_OFF)
configHDMIOn := config.String(CONFIG_KEY_HDMI_ON)
configHDMIOff := pfconfig.String(config.CONFIG_KEY_HDMI_OFF)
configHDMIOn := pfconfig.String(config.CONFIG_KEY_HDMI_ON)
hdmiForm.AddInputField("HDMI Off Schedule", configHDMIOff, 0, nil, func(value string) {
configHDMIOff = value
})
@ -377,21 +380,49 @@ func ConfigGui(config *koanf.Koanf) {
AddButtons([]string{"Yes", "Cancel"}).
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
if buttonLabel == "Yes" {
// Housekeeping var for data to be written to disk
var hdmiForDisk bytes.Buffer
// Apply HDMI configuration (on/off)
valueForTemplate := utils.SystemdTimer{OnCalendar: configHDMIOn}
screenOn, err := template.New("screenon.systemd.timer").Parse(utils.SCREEN_ON_DOT_TIMER)
if err != nil {
log.Fatalf("Error setting up screen on systemd timer : %s", err)
}
err = screenOn.Execute(&hdmiForDisk, valueForTemplate)
if err != nil {
log.Fatalf("Error setting up screen on systemd timer : %s", err)
}
utils.WriteFile(utils.SCREEN_ON_TIMER_PATH, utils.SCREEN_ON_TIMER_PATH+".tmp", hdmiForDisk.Bytes())
valueForTemplate.OnCalendar = configHDMIOff
hdmiForDisk.Truncate(0)
screenOff, err := template.New("screenoff.systemd.timer").Parse(utils.SCREEN_OFF_DOT_TIMER)
if err != nil {
log.Fatalf("Error setting up screen off systemd timer : %s", err)
}
err = screenOff.Execute(&hdmiForDisk, valueForTemplate)
if err != nil {
log.Fatalf("Error setting up screen off systemd timer : %s", err)
}
utils.WriteFile(utils.SCREEN_OFF_TIMER_PATH, utils.SCREEN_OFF_TIMER_PATH+".tmp", hdmiForDisk.Bytes())
// Reload systemd units after applying HDMI config
utils.SystemdDaemonReload()
// Apply configuration updates to main config manager prior to saving
pfconfig.Load(confmap.Provider(map[string]interface{}{
config.DEFAULT_HDMI_ON: configHDMIOn,
config.DEFAULT_HDMI_OFF: configHDMIOff,
}, "."), nil)
// Save configuration
parser := toml.Parser()
dataForDisk, err := config.Marshal(parser)
configForDisk, err := pfconfig.Marshal(parser)
if err != nil {
log.Fatalf("Error preparing config for disk write : %s", err)
}
existingStat, err := os.Lstat(CONFIG_FILE_PATH)
if err != nil {
log.Fatalf("Error checking if config exists : %s", err)
}
if err := ioutil.WriteFile(CONFIG_FILE_PATH_TMP, dataForDisk, existingStat.Mode()); err != nil {
log.Fatalf("Error writing temp config file : %s", err)
}
if err := os.Rename(CONFIG_FILE_PATH_TMP, CONFIG_FILE_PATH); err != nil {
log.Fatalf("Error moving new config in place : %s", err)
}
utils.WriteFile(config.CONFIG_FILE_PATH, config.CONFIG_FILE_PATH_TMP, configForDisk)
app.Stop()
os.Exit(0)
}

View file

@ -10,6 +10,8 @@ import (
"github.com/eiannone/keyboard"
"github.com/knadh/koanf"
pfconfig "git.kemonine.info/PiFrame/config"
)
const (
@ -32,7 +34,7 @@ func Slideshow(config *koanf.Koanf) {
}
// Advance slideshow every interval as defined in const()
ticker := time.NewTicker(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
ticker := time.NewTicker(config.Duration(pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL))
stop_ticker := make(chan struct{})
go func() {
for {
@ -99,7 +101,7 @@ func Slideshow(config *koanf.Koanf) {
if err != nil {
log.Fatalf("Error controlling fim : %s", err)
}
ticker.Reset(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
ticker.Reset(config.Duration(pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL))
}
}
}

20
utils/files.go Normal file
View file

@ -0,0 +1,20 @@
package utils
import (
"io/ioutil"
"log"
"os"
)
func WriteFile(destinationPath string, tempPath string, dataForDisk []byte) {
existingStat, err := os.Lstat(destinationPath)
if err != nil {
log.Fatalf("Error checking if file exists : %s", err)
}
if err := ioutil.WriteFile(tempPath, dataForDisk, existingStat.Mode()); err != nil {
log.Fatalf("Error writing temp file : %s", err)
}
if err := os.Rename(tempPath, destinationPath); err != nil {
log.Fatalf("Error moving new in place : %s", err)
}
}

28
utils/hdmi.go Normal file
View file

@ -0,0 +1,28 @@
package utils
type SystemdTimer struct {
OnCalendar string
}
const SCREEN_ON_DOT_TIMER = `
[Unit]
Description=Turn on display
[Timer]
OnCalendar={{.OnCalendar}}
Persistent=true
[Install]
WantedBy=timers.target
`
const SCREEN_OFF_DOT_TIMER = `
[Unit]
Description=Turn off display
[Timer]
OnCalendar={{.OnCalendar}}
Persistent=true
[Install]
WantedBy=timers.target
`

23
utils/systemd.go Normal file
View file

@ -0,0 +1,23 @@
package utils
import (
"log"
"os/exec"
)
const (
CMD_SYSTEMCTL = "/usr/bin/systemctl"
)
const (
SCREEN_ON_TIMER_PATH = "/etc/systemd/system/screen-on.timer"
SCREEN_OFF_TIMER_PATH = "/etc/systemd/system/screen-off.timer"
)
func SystemdDaemonReload() {
// Reload systemd units
err := exec.Command(CMD_SYSTEMCTL, "daemon-reload").Run()
if err != nil {
log.Fatalf("Error running %s : %s", CMD_SYSTEMCTL, err)
}
}