diff --git a/main.go b/main.go index 88b1809..d1dcdca 100644 --- a/main.go +++ b/main.go @@ -6,12 +6,14 @@ import ( "os" "os/signal" "syscall" + "time" "github.com/mwuertinger/hal/pkg/config" "github.com/mwuertinger/hal/pkg/device" "github.com/mwuertinger/hal/pkg/frontend" "github.com/mwuertinger/hal/pkg/mqtt" "github.com/mwuertinger/hal/pkg/persistence" + "github.com/mwuertinger/hal/pkg/timer" ) func main() { @@ -35,6 +37,11 @@ func main() { log.Fatalf("persistence.Start: %v", err) } + timerSvc := timer.NewService() + if err := timerSvc.Start(); err != nil { + log.Fatalf("timerSvc.Start: %v", err) + } + mqttBroker := mqtt.New() if err := mqttBroker.Connect(c.Mqtt); err != nil { log.Fatalf("mqttBroker.Connect: %v", err) @@ -49,6 +56,17 @@ func main() { log.Fatalf("frontend.Start: %v", err) } + // TODO remove + var switches []device.Switch + for _, dev := range device.List() { + switches = append(switches, dev.(device.Switch)) + } + timerSvc.AddJob(timer.Job{ + Timestamp: time.Date(2018, 10, 26, 5, 0, 0, 0, time.UTC), + Status: true, + Switches: switches, + }) + log.Println("Server ready") // Wait for receiving a signal. diff --git a/pkg/timer/timer.go b/pkg/timer/timer.go new file mode 100644 index 0000000..e8b9789 --- /dev/null +++ b/pkg/timer/timer.go @@ -0,0 +1,73 @@ +package timer + +import ( + "errors" + "github.com/mwuertinger/hal/pkg/device" + "log" + "math/rand" + "sync" + "time" +) + +type Service interface { + Start() error + AddJob(job Job) (uint64, error) +} + +type Job struct { + ID uint64 + Timestamp time.Time // execution time + Switches []device.Switch // list of switches + Status bool // target status +} + +type service struct { + mu sync.Mutex // protects everything below + initialized bool + jobs map[uint64]Job +} + +func NewService() Service { + return &service{jobs: map[uint64]Job{}} +} + +func (s *service) Start() error { + s.mu.Lock() + defer s.mu.Unlock() + if s.initialized { + return errors.New("already initialized") + } + + go func() { + for now := range time.Tick(time.Minute) { + s.mu.Lock() + log.Print("Timer.jobs: ", s.jobs) + for id, job := range s.jobs { + if job.Timestamp.Before(now) { + log.Print("Timer: ", job) + for _, sw := range job.Switches { + sw.Switch(job.Status) + } + delete(s.jobs, id) + } + } + s.mu.Unlock() + } + }() + return nil +} + +func (s *service) AddJob(job Job) (uint64, error) { + job.ID = rand.Uint64() + + // defensive copying + switches := make([]device.Switch, len(job.Switches)) + copy(switches, job.Switches) + job.Switches = switches + + s.mu.Lock() + defer s.mu.Unlock() + s.jobs[job.ID] = job + + return job.ID, nil +}