gobot.io/x/gobot/v2@v2.1.0/drivers/gpio/pir_motion_driver.go (about)

     1  package gpio
     2  
     3  import (
     4  	"time"
     5  
     6  	"gobot.io/x/gobot/v2"
     7  )
     8  
     9  // PIRMotionDriver represents a digital Proximity Infra Red (PIR) motion detecter
    10  type PIRMotionDriver struct {
    11  	Active     bool
    12  	pin        string
    13  	name       string
    14  	halt       chan bool
    15  	interval   time.Duration
    16  	connection DigitalReader
    17  	gobot.Eventer
    18  }
    19  
    20  // NewPIRMotionDriver returns a new PIRMotionDriver with a polling interval of
    21  // 10 Milliseconds given a DigitalReader and pin.
    22  //
    23  // Optionally accepts:
    24  //
    25  //	time.Duration: Interval at which the PIRMotionDriver is polled for new information
    26  func NewPIRMotionDriver(a DigitalReader, pin string, v ...time.Duration) *PIRMotionDriver {
    27  	b := &PIRMotionDriver{
    28  		name:       gobot.DefaultName("PIRMotion"),
    29  		connection: a,
    30  		pin:        pin,
    31  		Active:     false,
    32  		Eventer:    gobot.NewEventer(),
    33  		interval:   10 * time.Millisecond,
    34  		halt:       make(chan bool),
    35  	}
    36  
    37  	if len(v) > 0 {
    38  		b.interval = v[0]
    39  	}
    40  
    41  	b.AddEvent(MotionDetected)
    42  	b.AddEvent(MotionStopped)
    43  	b.AddEvent(Error)
    44  
    45  	return b
    46  }
    47  
    48  // Start starts the PIRMotionDriver and polls the state of the sensor at the given interval.
    49  //
    50  // Emits the Events:
    51  //
    52  //	MotionDetected - On motion detected
    53  //	MotionStopped int - On motion stopped
    54  //	Error error - On button error
    55  //
    56  // The PIRMotionDriver will send the MotionDetected event over and over,
    57  // just as long as motion is still being detected.
    58  // It will only send the MotionStopped event once, however, until
    59  // motion starts being detected again
    60  func (p *PIRMotionDriver) Start() (err error) {
    61  	go func() {
    62  		for {
    63  			newValue, err := p.connection.DigitalRead(p.Pin())
    64  			if err != nil {
    65  				p.Publish(Error, err)
    66  			}
    67  			switch newValue {
    68  			case 1:
    69  				if !p.Active {
    70  					p.Active = true
    71  					p.Publish(MotionDetected, newValue)
    72  				}
    73  			case 0:
    74  				if p.Active {
    75  					p.Active = false
    76  					p.Publish(MotionStopped, newValue)
    77  				}
    78  			}
    79  
    80  			select {
    81  			case <-time.After(p.interval):
    82  			case <-p.halt:
    83  				return
    84  			}
    85  		}
    86  	}()
    87  	return
    88  }
    89  
    90  // Halt stops polling the button for new information
    91  func (p *PIRMotionDriver) Halt() (err error) {
    92  	p.halt <- true
    93  	return
    94  }
    95  
    96  // Name returns the PIRMotionDriver name
    97  func (p *PIRMotionDriver) Name() string { return p.name }
    98  
    99  // SetName sets the PIRMotionDriver name
   100  func (p *PIRMotionDriver) SetName(n string) { p.name = n }
   101  
   102  // Pin returns the PIRMotionDriver pin
   103  func (p *PIRMotionDriver) Pin() string { return p.pin }
   104  
   105  // Connection returns the PIRMotionDriver Connection
   106  func (p *PIRMotionDriver) Connection() gobot.Connection { return p.connection.(gobot.Connection) }