detector.go 1.7 KB

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