detector.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package presence
  2. import (
  3. "context"
  4. "goa.design/clue/log"
  5. "douglasthrift.net/presence/ifttt"
  6. "douglasthrift.net/presence/neighbors"
  7. )
  8. type (
  9. Detector interface {
  10. Detect(ctx context.Context) error
  11. Config(config *Config)
  12. Client(client ifttt.Client)
  13. }
  14. detector struct {
  15. config *Config
  16. arp neighbors.ARP
  17. interfaces neighbors.Interfaces
  18. state neighbors.State
  19. states neighbors.HardwareAddrStates
  20. client ifttt.Client
  21. }
  22. )
  23. func NewDetector(config *Config, arp neighbors.ARP, client ifttt.Client) Detector {
  24. d := &detector{
  25. arp: arp,
  26. state: neighbors.NewState(),
  27. states: make(neighbors.HardwareAddrStates, len(config.MACAddresses)),
  28. client: client,
  29. }
  30. d.Config(config)
  31. return d
  32. }
  33. func (d *detector) Detect(ctx context.Context) error {
  34. log.Print(ctx, log.KV{K: "msg", V: "detecting presence"}, log.KV{K: "present", V: d.state.Present()})
  35. err := d.arp.Present(ctx, d.interfaces, d.state, d.states)
  36. if err != nil {
  37. return err
  38. }
  39. for _, a := range d.config.MACAddresses {
  40. state := d.states[a]
  41. log.Print(ctx, log.KV{K: "msg", V: a}, log.KV{K: "present", V: state.Present()}, log.KV{K: "changed", V: state.Changed()})
  42. }
  43. log.Print(ctx, log.KV{K: "msg", V: "detected presence"}, log.KV{K: "present", V: d.state.Present()}, log.KV{K: "changed", V: d.state.Changed()})
  44. if d.state.Changed() {
  45. event, err := d.client.Trigger(ctx, d.state.Present())
  46. if err != nil {
  47. d.state.Reset()
  48. return err
  49. }
  50. log.Print(ctx, log.KV{K: "msg", V: "triggered IFTTT"}, log.KV{K: "event", V: event})
  51. }
  52. return nil
  53. }
  54. func (d *detector) Config(config *Config) {
  55. d.config = config
  56. d.interfaces = make(neighbors.Interfaces, len(config.Interfaces))
  57. for _, i := range config.Interfaces {
  58. d.interfaces[i] = true
  59. }
  60. states := make(map[string]bool, len(d.states))
  61. for a := range d.states {
  62. states[a] = true
  63. }
  64. for _, a := range config.MACAddresses {
  65. if states[a] {
  66. states[a] = false
  67. } else {
  68. d.states[a] = neighbors.NewState()
  69. }
  70. }
  71. for a, ok := range states {
  72. if ok {
  73. delete(d.states, a)
  74. }
  75. }
  76. }
  77. func (d *detector) Client(client ifttt.Client) {
  78. d.client = client
  79. }