diff --git a/api/actions.go b/api/actions.go index b552f86..05fe2db 100644 --- a/api/actions.go +++ b/api/actions.go @@ -2,7 +2,6 @@ package api import ( "fmt" - "log" "net/http" "github.com/gin-gonic/gin" @@ -91,23 +90,4 @@ func declareActionsRoutes(cfg *config.Config, router *gin.RouterGroup) { c.JSON(http.StatusOK, nil) }) - - actionsRoutes.POST("/run", func(c *gin.Context) { - action := c.MustGet("action").(*reveil.Action) - - cmd, err := action.Launch() - if err != nil { - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to run the action: %s", err.Error())}) - return - } - - go func() { - err := cmd.Wait() - if err != nil { - log.Printf("%q: %s", action.Name, err.Error()) - } - }() - - c.JSON(http.StatusOK, true) - }) } diff --git a/api/alarm.go b/api/alarm.go index 23179d4..071073d 100644 --- a/api/alarm.go +++ b/api/alarm.go @@ -20,7 +20,7 @@ func declareAlarmRoutes(cfg *config.Config, router *gin.RouterGroup) { router.POST("/alarm/run", func(c *gin.Context) { if player.CommonPlayer == nil { - err := player.WakeUp(cfg, nil) + err := player.WakeUp(cfg) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) return diff --git a/api/alarms.go b/api/alarms.go index d3a0922..b5bad7a 100644 --- a/api/alarms.go +++ b/api/alarms.go @@ -13,7 +13,7 @@ import ( func declareAlarmsRoutes(cfg *config.Config, db *reveil.LevelDBStorage, resetTimer func(), router *gin.RouterGroup) { router.GET("/alarms/next", func(c *gin.Context) { - alarm, _, err := reveil.GetNextAlarm(cfg, db) + alarm, err := reveil.GetNextAlarm(cfg, db) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) return diff --git a/api/routines.go b/api/routines.go index 82c5b53..16d7c0a 100644 --- a/api/routines.go +++ b/api/routines.go @@ -78,12 +78,4 @@ func declareRoutinesRoutes(cfg *config.Config, router *gin.RouterGroup) { c.JSON(http.StatusOK, nil) }) - - routinesRoutes.POST("/run", func(c *gin.Context) { - routine := c.MustGet("routine").(*reveil.Routine) - - go routine.Launch(cfg) - - c.JSON(http.StatusOK, true) - }) } diff --git a/app.go b/app.go index f6a6b96..e2b5973 100644 --- a/app.go +++ b/app.go @@ -80,11 +80,11 @@ func (app *App) ResetTimer() { app.nextAlarm = nil } - if na, routines, err := reveil.GetNextAlarm(app.cfg, app.db); err == nil && na != nil { + if na, err := reveil.GetNextAlarm(app.cfg, app.db); err == nil && na != nil { app.nextAlarm = time.AfterFunc(time.Until(*na), func() { app.nextAlarm = nil reveil.RemoveOldAlarmsSingle(app.db) - err := player.WakeUp(app.cfg, routines) + err := player.WakeUp(app.cfg) if err != nil { log.Println(err.Error()) return diff --git a/model/action.go b/model/action.go index 7a0a744..9c1ce81 100644 --- a/model/action.go +++ b/model/action.go @@ -4,11 +4,9 @@ import ( "bufio" "crypto/sha512" "errors" - "fmt" "io/fs" "log" "os" - "os/exec" "path/filepath" "strings" @@ -21,10 +19,9 @@ type Action struct { Description string `json:"description,omitempty"` Path string `json:"path"` Enabled bool `json:"enabled"` - fullPath string } -func loadAction(path string) (string, string, error) { +func LoadAction(path string) (string, string, error) { fd, err := os.Open(path) if err != nil { return "", "", err @@ -67,45 +64,6 @@ func loadAction(path string) (string, string, error) { return name, description, nil } -func LoadAction(cfg *config.Config, path string) (*Action, error) { - actionsDir, err := filepath.Abs(cfg.ActionsDir) - if err != nil { - return nil, err - } - - path = filepath.Join(actionsDir, path) - - d, err := os.Stat(path) - if err != nil { - return nil, err - } - - if !d.Mode().IsRegular() { - return nil, fmt.Errorf("%q is not a file, it cannot be an action.", path) - } - - hash := sha512.Sum512([]byte(path)) - - // Parse content - name, description, err := loadAction(path) - if err != nil { - return nil, fmt.Errorf("Invalid action file (trying to parse %s): %s", path, err.Error()) - } - - if apath, err := filepath.Abs(path); err == nil { - path = apath - } - - return &Action{ - Id: hash[:], - Name: name, - Description: description, - Path: strings.TrimPrefix(path, actionsDir+"/"), - Enabled: d.Mode().Perm()&0111 != 0, - fullPath: path, - }, nil -} - func LoadActions(cfg *config.Config) (actions []*Action, err error) { actionsDir, err := filepath.Abs(cfg.ActionsDir) if err != nil { @@ -117,7 +75,7 @@ func LoadActions(cfg *config.Config) (actions []*Action, err error) { hash := sha512.Sum512([]byte(path)) // Parse content - name, description, err := loadAction(path) + name, description, err := LoadAction(path) if err != nil { log.Printf("Invalid action file (trying to parse %s): %s", path, err.Error()) // Ignore invalid files @@ -138,7 +96,6 @@ func LoadActions(cfg *config.Config) (actions []*Action, err error) { Description: description, Path: strings.TrimPrefix(path, actionsDir+"/"), Enabled: d.Mode().Perm()&0111 != 0, - fullPath: path, }) } @@ -173,9 +130,3 @@ func (a *Action) Disable() error { func (a *Action) Remove() error { return os.Remove(a.Path) } - -func (a *Action) Launch() (cmd *exec.Cmd, err error) { - cmd = exec.Command(a.fullPath) - err = cmd.Start() - return -} diff --git a/model/alarm.go b/model/alarm.go index 1453b9d..63e6e9f 100644 --- a/model/alarm.go +++ b/model/alarm.go @@ -40,57 +40,37 @@ func (h *Hour) UnmarshalJSON(src []byte) error { return nil } -func GetNextAlarm(cfg *config.Config, db *LevelDBStorage) (*time.Time, []Identifier, error) { +func GetNextAlarm(cfg *config.Config, db *LevelDBStorage) (*time.Time, error) { alarmsRepeated, err := GetAlarmsRepeated(db) if err != nil { - return nil, nil, err + return nil, err } var closestAlarm *time.Time - var closestAlarmRoutines []Identifier for _, alarm := range alarmsRepeated { next := alarm.GetNextOccurence(cfg, db) if next != nil && (closestAlarm == nil || closestAlarm.After(*next)) { closestAlarm = next - closestAlarmRoutines = alarm.FollowingRoutines } } alarmsSingle, err := GetAlarmsSingle(db) if err != nil { - return nil, nil, err + return nil, err } now := time.Now() for _, alarm := range alarmsSingle { if closestAlarm == nil || (closestAlarm.After(alarm.Time) && alarm.Time.After(now)) { closestAlarm = &alarm.Time - closestAlarmRoutines = alarm.FollowingRoutines } } - return closestAlarm, closestAlarmRoutines, nil -} - -func GetNextException(cfg *config.Config, db *LevelDBStorage) (*time.Time, error) { - alarmsExceptions, err := GetAlarmExceptions(db) - if err != nil { - return nil, err - } - - var closestException *time.Time - for _, except := range alarmsExceptions { - if except != nil && time.Time(*except.End).After(time.Now()) && (closestException == nil || closestException.After(time.Time(*except.Start))) { - tmp := time.Time(*except.Start) - closestException = &tmp - } - } - - return closestException, nil + return closestAlarm, nil } func DropNextAlarm(cfg *config.Config, db *LevelDBStorage) error { - timenext, _, err := GetNextAlarm(cfg, db) + timenext, err := GetNextAlarm(cfg, db) if err != nil { return err } diff --git a/model/routine.go b/model/routine.go index e1c6ba0..86b06a2 100644 --- a/model/routine.go +++ b/model/routine.go @@ -1,9 +1,7 @@ package reveil import ( - "bytes" "crypto/sha512" - "fmt" "io/fs" "io/ioutil" "log" @@ -11,7 +9,6 @@ import ( "path/filepath" "strconv" "strings" - "time" "git.nemunai.re/nemunaire/reveil/config" ) @@ -22,10 +19,6 @@ type RoutineStep struct { Args []string `json:"args,omitempty"` } -func (s *RoutineStep) GetAction(cfg *config.Config) (*Action, error) { - return LoadAction(cfg, s.Action) -} - type Routine struct { Id Identifier `json:"id"` Name string `json:"name"` @@ -79,21 +72,6 @@ func LoadRoutine(path string, cfg *config.Config) ([]RoutineStep, error) { return steps, nil } -func LoadRoutineFromId(id Identifier, cfg *config.Config) (*Routine, error) { - routines, err := LoadRoutines(cfg) - if err != nil { - return nil, err - } - - for _, routine := range routines { - if bytes.Equal(routine.Id, id) { - return routine, nil - } - } - - return nil, fmt.Errorf("Unable to find routine %x", id) -} - func LoadRoutines(cfg *config.Config) (routines []*Routine, err error) { err = filepath.Walk(cfg.RoutinesDir, func(path string, d fs.FileInfo, err error) error { if d.IsDir() && path != cfg.RoutinesDir { @@ -139,28 +117,3 @@ func (r *Routine) Rename(newName string) error { func (a *Routine) Remove() error { return os.Remove(a.Path) } - -func (a *Routine) Launch(cfg *config.Config) error { - for _, s := range a.Steps { - act, err := s.GetAction(cfg) - if err != nil { - log.Printf("Unable to get action: %s: %s", s.Action, err.Error()) - continue - } - - time.Sleep(time.Duration(s.Delay) * time.Second) - - cmd, err := act.Launch() - if err != nil { - log.Printf("Unable to launch the action %q: %s", s.Action, err.Error()) - continue - } - - err = cmd.Wait() - if err != nil { - log.Printf("Something goes wrong when waiting for the action %q's end: %s", s.Action, err.Error()) - } - } - - return nil -} diff --git a/player/player.go b/player/player.go index 5d49c29..d543c77 100644 --- a/player/player.go +++ b/player/player.go @@ -25,17 +25,11 @@ type Player struct { currentCmd *exec.Cmd currentCmdCh chan bool - weatherTime time.Duration - weatherAction *reveil.Action - claironTime time.Duration claironFile string - endRoutines []*reveil.Routine - ntick int64 hasClaironed bool - hasSpokeWeather bool launched time.Time volume uint16 dontUpdateVolume bool @@ -43,7 +37,7 @@ type Player struct { playedItem int } -func WakeUp(cfg *config.Config, routine []reveil.Identifier) (err error) { +func WakeUp(cfg *config.Config) (err error) { if CommonPlayer != nil { return fmt.Errorf("Unable to start the player: a player is already running") } @@ -52,48 +46,29 @@ func WakeUp(cfg *config.Config, routine []reveil.Identifier) (err error) { seed -= seed % 172800 rand.Seed(seed) - CommonPlayer, err = NewPlayer(cfg, routine) + CommonPlayer, err = NewPlayer(cfg) if err != nil { return err } - go CommonPlayer.WakeUp(cfg) + go CommonPlayer.WakeUp() return nil } -func NewPlayer(cfg *config.Config, routines []reveil.Identifier) (*Player, error) { +func NewPlayer(cfg *config.Config) (*Player, error) { // Load our settings settings, err := reveil.ReadSettings(cfg.SettingsFile) if err != nil { return nil, fmt.Errorf("Unable to read settings: %w", err) } - // Load weather action - wact, err := reveil.LoadAction(cfg, settings.WeatherAction) - if err != nil { - log.Println("Unable to load weather action:", err.Error()) - } - p := Player{ - Stopper: make(chan bool, 1), - currentCmdCh: make(chan bool, 1), - MaxRunTime: settings.MaxRunTime * time.Minute, - weatherTime: settings.WeatherDelay * time.Minute, - weatherAction: wact, - claironTime: settings.GongInterval * time.Minute, - claironFile: reveil.CurrentGongPath(cfg), - reverseOrder: int(time.Now().Unix()/86400)%2 == 0, - } - - // Load routines - for _, routine := range routines { - r, err := reveil.LoadRoutineFromId(routine, cfg) - if err != nil { - log.Printf("Unable to load routine %x: %s", routine, err.Error()) - continue - } - - p.endRoutines = append(p.endRoutines, r) + Stopper: make(chan bool, 1), + currentCmdCh: make(chan bool, 1), + MaxRunTime: settings.MaxRunTime * time.Minute, + claironTime: settings.GongInterval * time.Minute, + claironFile: reveil.CurrentGongPath(cfg), + reverseOrder: int(time.Now().Unix()/86400)%2 == 0, } // Load our track list @@ -123,16 +98,6 @@ func NewPlayer(cfg *config.Config, routines []reveil.Identifier) (*Player, error return &p, nil } -func (p *Player) launchAction(a *reveil.Action) (err error) { - p.currentCmd, err = a.Launch() - log.Println("Running action ", a.Name) - - err = p.currentCmd.Wait() - p.currentCmdCh <- true - - return -} - func (p *Player) playFile(filepath string) (err error) { p.currentCmd = exec.Command("paplay", filepath) if err = p.currentCmd.Start(); err != nil { @@ -149,7 +114,7 @@ func (p *Player) playFile(filepath string) (err error) { return } -func (p *Player) WakeUp(cfg *config.Config) { +func (p *Player) WakeUp() { log.Println("Playlist in use:", strings.Join(p.Playlist, " ; ")) // Prepare sound player @@ -176,11 +141,6 @@ loop: p.SetVolume(65535) p.dontUpdateVolume = true go p.playFile(p.claironFile) - } else if p.weatherAction != nil && !p.hasSpokeWeather && time.Since(p.launched) >= p.weatherTime { - log.Println("weather time!") - p.SetVolume(65535) - p.dontUpdateVolume = true - go p.launchAction(p.weatherAction) } else { p.dontUpdateVolume = false p.volume = 3500 + uint16(math.Log(1+float64(p.ntick)/8)*9500) @@ -254,11 +214,6 @@ loopcalm: CommonPlayer = nil } - - // TODO: Start Routine if any - for _, r := range p.endRoutines { - go r.Launch(cfg) - } } func (p *Player) NextTrack() { diff --git a/ui/nojs.go b/ui/nojs.go index 2d40706..51b0299 100644 --- a/ui/nojs.go +++ b/ui/nojs.go @@ -24,7 +24,7 @@ func DeclareNoJSRoutes(router *gin.Engine, cfg *config.Config, db *reveil.LevelD router.SetHTMLTemplate(templ) router.GET("/nojs.html", func(c *gin.Context) { - alarm, _, err := reveil.GetNextAlarm(cfg, db) + alarm, err := reveil.GetNextAlarm(cfg, db) if err != nil { c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) return @@ -109,7 +109,7 @@ func DeclareNoJSRoutes(router *gin.Engine, cfg *config.Config, db *reveil.LevelD case "start": if player.CommonPlayer == nil { - err := player.WakeUp(cfg, nil) + err := player.WakeUp(cfg) if err != nil { c.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{"errmsg": err.Error()}) return diff --git a/ui/src/lib/action.js b/ui/src/lib/action.js index e199028..5b0ad92 100644 --- a/ui/src/lib/action.js +++ b/ui/src/lib/action.js @@ -25,18 +25,6 @@ export class Action { } } - async launch() { - const res = await fetch(`api/actions/${this.id}/run`, { - method: 'POST', - headers: {'Accept': 'application/json'} - }); - if (res.status == 200) { - return true; - } else { - throw new Error((await res.json()).errmsg); - } - } - toggleEnable() { this.enabled = !this.enabled; this.save(); diff --git a/ui/src/lib/components/CardRoutine.svelte b/ui/src/lib/components/CardRoutine.svelte index 13223d6..cc63566 100644 --- a/ui/src/lib/components/CardRoutine.svelte +++ b/ui/src/lib/components/CardRoutine.svelte @@ -27,7 +27,6 @@ color="outline-danger" size="sm" class="float-end ms-1" - on:click={() => routine.delete()} > @@ -38,14 +37,6 @@ > - {routine.name} {#if routine.steps} diff --git a/ui/src/lib/routine.js b/ui/src/lib/routine.js index f08b2c2..95e6691 100644 --- a/ui/src/lib/routine.js +++ b/ui/src/lib/routine.js @@ -26,18 +26,6 @@ export class Routine { } } - async launch() { - const res = await fetch(`api/routines/${this.id}/run`, { - method: 'POST', - headers: {'Accept': 'application/json'} - }); - if (res.status == 200) { - return true; - } else { - throw new Error((await res.json()).errmsg); - } - } - async save() { const res = await fetch(this.id?`api/routines/${this.id}`:'api/routines', { method: this.id?'PUT':'POST', diff --git a/ui/src/routes/routines/actions/[aid]/+page.svelte b/ui/src/routes/routines/actions/[aid]/+page.svelte index dff78b2..f983a88 100644 --- a/ui/src/routes/routines/actions/[aid]/+page.svelte +++ b/ui/src/routes/routines/actions/[aid]/+page.svelte @@ -3,7 +3,6 @@ import { Container, - Icon, Input, ListGroup, ListGroupItem, @@ -11,14 +10,6 @@ } from 'sveltestrap'; import { getAction } from '$lib/action'; - import { actions } from '$lib/stores/actions'; - - function deleteThis(action) { - action.delete().then(() => { - actions.refresh(); - goto('routines/actions/'); - }) - } {#await getAction($page.params.aid)} @@ -43,26 +34,5 @@ action.toggleEnable()} checked={action.enabled} /> - - - action.launch()} - > - - Lancer cette action - - deleteThis(action)} - > - - Supprimer cette action - - {/await}