2022-09-24 16:29:26 -07:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import "context"
|
2022-09-24 21:19:57 -07:00
|
|
|
import "encoding/json"
|
2022-09-24 17:20:10 -07:00
|
|
|
import "flag"
|
2022-09-24 21:19:57 -07:00
|
|
|
import "log"
|
2022-09-24 17:20:10 -07:00
|
|
|
import "math"
|
|
|
|
|
import "os"
|
|
|
|
|
import "time"
|
2022-09-24 16:29:26 -07:00
|
|
|
|
2022-09-24 16:35:03 -07:00
|
|
|
import "github.com/firestuff/hh/hhio"
|
2022-09-24 17:20:10 -07:00
|
|
|
import "gopkg.in/yaml.v3"
|
|
|
|
|
|
|
|
|
|
var conf = flag.String("conf", "", "path to config file")
|
|
|
|
|
|
|
|
|
|
type Config struct {
|
|
|
|
|
Relay
|
|
|
|
|
Ultrasonics []Ultrasonic
|
|
|
|
|
|
|
|
|
|
MedianBuffer int
|
|
|
|
|
|
|
|
|
|
OnCM float64
|
|
|
|
|
OffCM float64
|
|
|
|
|
|
2022-09-24 21:19:57 -07:00
|
|
|
OnSeconds float64
|
|
|
|
|
OffSeconds float64
|
2022-09-24 17:20:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Relay struct {
|
|
|
|
|
Control int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Ultrasonic struct {
|
|
|
|
|
Trigger int
|
|
|
|
|
Echo int
|
|
|
|
|
}
|
2022-09-24 16:29:26 -07:00
|
|
|
|
|
|
|
|
func main() {
|
2022-09-24 17:20:10 -07:00
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
|
|
cf, err := readConf()
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = hhio.Open()
|
2022-09-24 16:29:26 -07:00
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
2022-09-24 16:35:03 -07:00
|
|
|
defer hhio.Close()
|
2022-09-24 16:29:26 -07:00
|
|
|
|
2022-09-24 17:20:10 -07:00
|
|
|
uss := []chan float64{}
|
2022-09-24 16:39:06 -07:00
|
|
|
|
2022-09-24 17:20:10 -07:00
|
|
|
for _, uscf := range cf.Ultrasonics {
|
|
|
|
|
us := hhio.NewUltrasonic(context.Background(), uscf.Trigger, uscf.Echo)
|
|
|
|
|
mf := hhio.NewMedianFilter(us.C, cf.MedianBuffer)
|
|
|
|
|
uss = append(uss, mf)
|
|
|
|
|
}
|
2022-09-24 16:29:26 -07:00
|
|
|
|
2022-09-24 17:20:10 -07:00
|
|
|
r := hhio.NewRelay(cf.Relay.Control)
|
2022-09-24 16:39:06 -07:00
|
|
|
|
2022-09-24 17:20:10 -07:00
|
|
|
last := make([]float64, len(uss))
|
|
|
|
|
for i := range uss {
|
|
|
|
|
last[i] = math.MaxFloat64
|
2022-09-24 16:29:26 -07:00
|
|
|
}
|
2022-09-24 17:20:10 -07:00
|
|
|
|
|
|
|
|
onUntil := time.Time{}
|
2022-09-24 21:19:57 -07:00
|
|
|
offUntil := time.Time{}
|
2022-09-24 17:20:10 -07:00
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
// Fetch new values
|
|
|
|
|
for i, us := range uss {
|
|
|
|
|
select {
|
|
|
|
|
case dist := <-us:
|
|
|
|
|
last[i] = dist
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Count votes
|
|
|
|
|
var on, off int
|
|
|
|
|
for _, v := range last {
|
|
|
|
|
if v < cf.OnCM {
|
|
|
|
|
on++
|
|
|
|
|
} else if v > cf.OffCM {
|
|
|
|
|
off++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-24 21:19:57 -07:00
|
|
|
if !r.IsOn() && on > 0 && onUntil.IsZero() && offUntil.IsZero() {
|
|
|
|
|
// Not on, no timers, something detected
|
|
|
|
|
r.On()
|
|
|
|
|
onUntil = time.Now().Add(time.Duration(cf.OnSeconds * float64(time.Second)))
|
|
|
|
|
log.Printf("on %s", fmtDists(last))
|
2022-09-24 17:20:10 -07:00
|
|
|
}
|
|
|
|
|
|
2022-09-24 21:19:57 -07:00
|
|
|
if r.IsOn() && onUntil.Before(time.Now()) {
|
|
|
|
|
// On timer expired, turn off
|
2022-09-24 17:20:10 -07:00
|
|
|
r.Off()
|
2022-09-24 21:19:57 -07:00
|
|
|
offUntil = time.Now().Add(time.Duration(cf.OffSeconds * float64(time.Second)))
|
|
|
|
|
log.Printf("off %s", fmtDists(last))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !r.IsOn() && on == 0 && off == len(uss) && !offUntil.IsZero() && offUntil.Before(time.Now()) {
|
|
|
|
|
// All quiet and timers expired, reset state
|
|
|
|
|
onUntil = time.Time{}
|
|
|
|
|
offUntil = time.Time{}
|
|
|
|
|
log.Printf("reset %s", fmtDists(last))
|
2022-09-24 17:20:10 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func readConf() (*Config, error) {
|
|
|
|
|
fh, err := os.Open(*conf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer fh.Close()
|
|
|
|
|
|
|
|
|
|
dec := yaml.NewDecoder(fh)
|
|
|
|
|
dec.KnownFields(true)
|
|
|
|
|
|
|
|
|
|
c := &Config{}
|
|
|
|
|
|
|
|
|
|
err = dec.Decode(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c, nil
|
2022-09-24 16:29:26 -07:00
|
|
|
}
|
2022-09-24 21:19:57 -07:00
|
|
|
|
|
|
|
|
func fmtDists(dists []float64) string {
|
|
|
|
|
ints := make([]int, len(dists))
|
|
|
|
|
|
|
|
|
|
for i, d := range dists {
|
|
|
|
|
ints[i] = int(d)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b, err := json.Marshal(ints)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string(b)
|
|
|
|
|
}
|