Files
hh/ultrasonic2relay/main.go

159 lines
2.4 KiB
Go
Raw Normal View History

2022-09-24 16:29:26 -07:00
package main
import "context"
import "encoding/json"
import "flag"
import "log"
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"
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
OnSeconds float64
OffSeconds float64
}
type Relay struct {
Control int
}
type Ultrasonic struct {
Trigger int
Echo int
}
2022-09-24 16:29:26 -07:00
2022-09-24 21:33:06 -07:00
type state int
const (
onTimer state = iota
offTimer
watching
)
2022-09-24 16:29:26 -07:00
func main() {
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
uss := []chan float64{}
2022-09-24 16:39:06 -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
r := hhio.NewRelay(cf.Relay.Control)
2022-09-24 16:39:06 -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 21:33:06 -07:00
var st state = watching
var onUntil, offUntil time.Time
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:33:06 -07:00
switch st {
case watching:
if on > 0 {
log.Printf("on %s", fmtDists(last))
r.On()
onUntil = time.Now().Add(time.Duration(cf.OnSeconds * float64(time.Second)))
st = onTimer
}
2022-09-24 21:33:06 -07:00
case onTimer:
if time.Now().After(onUntil) {
log.Printf("off %s", fmtDists(last))
r.Off()
offUntil = time.Now().Add(time.Duration(cf.OffSeconds * float64(time.Second)))
st = offTimer
}
2022-09-24 21:33:06 -07:00
case offTimer:
if time.Now().After(offUntil) && on == 0 && off == len(uss) {
log.Printf("reset %s", fmtDists(last))
st = watching
}
}
}
}
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
}
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)
}