gobot.io/x/gobot@v1.16.0/drivers/gpio/pir_motion_driver.go (about)

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