Skip to content

Commit

Permalink
Merge pull request #1 from rmanocha/golang
Browse files Browse the repository at this point in the history
adding golang version for this stuff
  • Loading branch information
rmanocha committed Aug 13, 2016
2 parents d418fe6 + 3f76ed8 commit 84ea0c8
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -89,3 +89,6 @@ ENV/
.ropeproject

settings.py
motion
*.db
tmp.py
4 changes: 4 additions & 0 deletions create_table.sh
@@ -0,0 +1,4 @@
#!/bin/bash
#echo "create table last_motion (rid integer primary key, start_time datetime, end_time datetime); insert into last_motion SELECT 1, datetime('now', '-5 seconds');" | sqlite3 last_motion.db
echo "create table last_motion (rid integer primary key, start_time datetime, end_time datetime);" | sqlite3 last_motion.db

183 changes: 183 additions & 0 deletions motion.go
@@ -0,0 +1,183 @@
package main

import (
"github.com/stianeikeland/go-rpio"
"os"
"time"
"database/sql"
_ "github.com/mattn/go-sqlite3"
"log"
"flag"
"strconv"
)

const (
InsertInitialSQL = "insert into last_motion(start_time) values (?)"
InsertFinalSQL = "update last_motion set end_time=? where rid=?"
SelectLastRidSQL = "select rid from last_motion order by rid desc limit 1"
)

var (
motion_pin rpio.Pin
//light_pin rpio.Pin
light_timeout int // this should be in seconds
//light_pin = rpio.Pin(11)

// set the default to be something greater than the timeout we have
//last_motion_ts = time.Now().UTC().Add((light_timeout + -2) * time.Second)
last_motion_ts time.Time
)

type MotionTracker struct {
db *sql.DB

last_motion_ts time.Time
last_no_motion_ts time.Time

rid int

timeout int
}

func LogInfo(message string) {
log.Println("INFO:", message)
}

func LogError(message string) {
log.Println("ERROR:", message)
}

func LogFatal(err error) {
log.Fatalln("FATAL:", err)
}

func MoreThanTimeout(from, to time.Time, timeout int) bool {
return to.Sub(from).Seconds() > float64(timeout)
}

func (mt *MotionTracker) GetSetDBRID() {
var rid int
mt.db.QueryRow(SelectLastRidSQL).Scan(&rid)

mt.rid = rid
}

func (mt *MotionTracker) StartMotionRow() {
stmt, err := mt.db.Prepare(InsertInitialSQL)
if err != nil {
LogFatal(err)
} else {
stmt.Exec(mt.last_motion_ts)
mt.GetSetDBRID()
LogInfo("New RID: " + strconv.Itoa(mt.rid))
}
}

func (mt *MotionTracker) EndMotionRow() {
stmt, err := mt.db.Prepare(InsertFinalSQL)
if err != nil {
LogFatal(err)
} else {
stmt.Exec(mt.last_no_motion_ts, mt.rid)
mt.rid = 0
}
}

func (mt *MotionTracker) TrackMotion() {
mt.last_motion_ts = time.Now().UTC()
if mt.rid == 0 {
LogInfo("Starting logging to DB")
mt.StartMotionRow()
}
}

func (mt *MotionTracker) TrackNoMotion() {
mt.last_no_motion_ts = time.Now().UTC()
if MoreThanTimeout(mt.last_motion_ts, mt.last_no_motion_ts, mt.timeout) && mt.rid != 0 {
LogInfo("Ending logging to DB")
mt.EndMotionRow()
}
}

func NewMotionTracker(timeout int) *MotionTracker {
db, err := sql.Open("sqlite3", "last_motion.db")
if err != nil {
LogFatal(err)
}

return &MotionTracker{db: db, timeout: timeout}
}

func TurnLightOn() {
if light_pin.Read() != rpio.Low {
LogInfo("Turning light on")
light_pin.Low()
}
}

func TurhLightOff() {
if light_pin.Read() != rpio.High {
LogInfo("Turning light off")
light_pin.High()
}
}

func main() {
var mpin, lpin int
var logfile_location string

flag.IntVar(&mpin, "motion_pin", 7, "Pin for the motion detector (BCM mode). Defaults to 7")
flag.IntVar(&lpin, "light_pin", 11, "Pin for the light (BCM mode). Defaults to 11")
flag.IntVar(&light_timeout, "timeout", 180, "Timeout before turning off the light. Value should be in seconds. Defaults to 180")
flag.StringVar(&logfile_location, "logfile", "/var/log/motion.log", "Location for the logfile. Defaults to /var/log/motion.log")

flag.Parse()

f, err := os.OpenFile(logfile_location, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
LogFatal(err)
}
defer f.Close()

log.SetOutput(f)

LogInfo("Using motion pin: " + strconv.Itoa(mpin))
LogInfo("Using light pin: " + strconv.Itoa(lpin))
LogInfo("Using timeout: " + strconv.Itoa(light_timeout))
LogInfo("Using logfile: " + logfile_location)

motion_pin = rpio.Pin(mpin)
light_pin = rpio.Pin(lpin)

if err := rpio.Open(); err != nil {
LogFatal(err)
}

mt := NewMotionTracker(light_timeout)

defer rpio.Close()

motion_pin.Input()
light_pin.Output()

for true {
switch motion_pin.Read() {
case rpio.High: // this is the one which means motion was detected
last_motion_ts = time.Now().UTC()
mt.TrackMotion()
case rpio.Low:
mt.TrackNoMotion()
}

if !MoreThanTimeout(last_motion_ts, time.Now().UTC(), light_timeout) {
//light_pin.Low()
TurnLightOn()
} else {
//light_pin.High()
TurnLightOff()
}

// sleep for 100 ms
time.Sleep(time.Millisecond * 100)
}
}

0 comments on commit 84ea0c8

Please sign in to comment.