detect.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "os/signal"
  6. "syscall"
  7. "time"
  8. "goa.design/clue/log"
  9. "douglasthrift.net/presence"
  10. "douglasthrift.net/presence/ifttt"
  11. "douglasthrift.net/presence/neighbors"
  12. )
  13. type (
  14. Detect struct {
  15. Iterations uint `help:"Only detect for N iterations." placeholder:"N" short:"i"`
  16. }
  17. )
  18. func (d *Detect) Run(cli *CLI) error {
  19. ctx := cli.Context()
  20. config, err := presence.ParseConfigWithContext(ctx, cli.Config, wNet)
  21. if err != nil {
  22. log.Fatal(ctx, err, log.KV{K: "msg", V: "error parsing config"}, log.KV{K: "config", V: cli.Config})
  23. }
  24. arp, err := neighbors.NewARP(config.PingCount)
  25. if err != nil {
  26. log.Fatal(ctx, err, log.KV{K: "msg", V: "error finding dependencies"})
  27. }
  28. client, err := ifttt.NewClient(http.DefaultClient, config.IFTTT.BaseURL, config.IFTTT.Key, config.IFTTT.Events.Present, config.IFTTT.Events.Absent, cli.Debug)
  29. if err != nil {
  30. log.Fatal(ctx, err, log.KV{K: "msg", V: "error creating IFTTT client"})
  31. }
  32. var (
  33. detector = presence.NewDetector(config, arp, client)
  34. ticker = time.NewTicker(config.Interval)
  35. stop = make(chan os.Signal, 1)
  36. reload = make(chan os.Signal, 1)
  37. i uint
  38. )
  39. err = detector.Detect(ctx)
  40. if err != nil {
  41. log.Error(ctx, err, log.KV{K: "msg", V: "error detecting presence"})
  42. }
  43. if d.Iterations != 0 {
  44. i++
  45. if i >= d.Iterations {
  46. ticker.Stop()
  47. return nil
  48. }
  49. }
  50. signal.Ignore(syscall.SIGHUP)
  51. signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
  52. signal.Notify(reload, syscall.SIGUSR1)
  53. for {
  54. select {
  55. case <-ticker.C:
  56. err = detector.Detect(ctx)
  57. if err != nil {
  58. log.Error(ctx, err, log.KV{K: "msg", V: "error detecting presence"})
  59. }
  60. if d.Iterations != 0 {
  61. i++
  62. if i >= d.Iterations {
  63. ticker.Stop()
  64. return nil
  65. }
  66. }
  67. case s := <-stop:
  68. log.Print(ctx, log.Fields{"msg": "received stop signal"}, log.Fields{"signal": s})
  69. ticker.Stop()
  70. return nil
  71. case s := <-reload:
  72. log.Print(ctx, log.Fields{"msg": "received reload signal"}, log.Fields{"signal": s})
  73. config, err = presence.ParseConfigWithContext(ctx, cli.Config, wNet)
  74. if err != nil {
  75. log.Error(ctx, err, log.KV{K: "msg", V: "error parsing config"}, log.KV{K: "config", V: cli.Config})
  76. } else if client, err = ifttt.NewClient(http.DefaultClient, config.IFTTT.BaseURL, config.IFTTT.Key, config.IFTTT.Events.Present, config.IFTTT.Events.Absent, cli.Debug); err != nil {
  77. log.Error(ctx, err, log.KV{K: "msg", V: "error creating IFTTT client"})
  78. } else {
  79. arp.Count(config.PingCount)
  80. detector.Config(config)
  81. detector.Client(client)
  82. err = detector.Detect(ctx)
  83. if err != nil {
  84. log.Error(ctx, err, log.KV{K: "msg", V: "error detecting presence"})
  85. }
  86. ticker.Reset(config.Interval)
  87. }
  88. }
  89. }
  90. }