This commit is contained in:
Thomas Vogl 2022-12-30 18:42:48 +01:00
parent 5b25457224
commit 005b167f5e
6 changed files with 155 additions and 42 deletions

2
go.mod
View File

@ -5,12 +5,12 @@ go 1.17
require ( require (
github.com/eclipse/paho.mqtt.golang v1.3.5 github.com/eclipse/paho.mqtt.golang v1.3.5
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1
github.com/stianeikeland/go-rpio v4.2.0+incompatible
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
) )
require ( require (
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect
github.com/stianeikeland/go-rpio v4.2.0+incompatible // indirect
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 // indirect golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
) )

View File

@ -0,0 +1,30 @@
//go:build !arm && !arm64
package PinControlService
type PinEmu struct {
}
func (*PinEmu) Toggle() {}
func (*PinEmu) High() {}
func (*PinEmu) Low() {}
func (*PinEmu) Input() {}
func (*PinEmu) Output() {}
func (*PinEmu) Detect(Edge) {}
func (*PinEmu) PullUp() {}
func (*PinEmu) PullDown() {}
func (*PinEmu) PullOff() {}
func (*PinEmu) Read() State { return LowState }
func (*PinEmu) EdgeDetected() bool { return false }
type HardwarePin struct {
Pin PinEmu
}
func NewHardwarePin(n int) HardwarePinInterface {
return &PinEmu{}
}
func HardwarePinOpen() error {
return nil
}

View File

@ -0,0 +1,39 @@
package PinControlService
type Mode uint8
type State uint8
type Pull uint8
type Edge uint8
type HardwarePinInterface interface {
Toggle()
High()
Low()
Input()
Output()
Detect(Edge)
PullUp()
PullDown()
PullOff()
Read() State
EdgeDetected() bool
}
const (
ModeInput Mode = iota
ModeOutput
ModeClock
ModePwm
)
const (
LowState State = iota
HighState
)
const (
NoEdge Edge = iota
RiseEdge
FallEdge
AnyEdge = RiseEdge | FallEdge
)

View File

@ -0,0 +1,55 @@
//go:build (arm || arm64) && linux
package PinControlService
import "github.com/stianeikeland/go-rpio"
type PinRpi struct {
pin rpio.Pin
}
func (p *PinRpi) Toggle() {
p.pin.Toggle()
}
func (p *PinRpi) High() {
p.pin.High()
}
func (p *PinRpi) Low() {
p.pin.Low()
}
func (p *PinRpi) Input() {
p.pin.Input()
}
func (p *PinRpi) Output() {
p.pin.Output()
}
func (p *PinRpi) Detect(e Edge) {
p.pin.Detect(rpio.Edge(e))
}
func (p *PinRpi) PullUp() {
p.pin.PullUp()
}
func (p *PinRpi) PullDown() {
p.pin.PullDown()
}
func (p *PinRpi) PullOff() {
p.pin.PullOff()
}
func (p *PinRpi) Read() State {
return State(p.pin.Read())
}
func (p *PinRpi) EdgeDetected() bool {
return p.pin.EdgeDetected()
}
func NewHardwarePin(n int) HardwarePinInterface {
return &PinRpi{
pin: rpio.Pin(n),
}
}
func HardwarePinOpen() error {
return rpio.Open()
}

View File

@ -3,28 +3,26 @@ package PinControlService
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/stianeikeland/go-rpio"
) )
type Pin struct { type Pin struct {
Id int Id int
Name string Name string
Direction PinDirection Direction PinDirection
PullConfig PinPull PullConfig PinPull
InitialState PinCommand InitialState PinCommand
PinHandle rpio.Pin PinHandle HardwarePinInterface
SendPollingEvents bool SendPollingEvents bool
SendChangeEvents bool SendChangeEvents bool
} }
func NewPin(config PinConfig) Pin { func NewPin(config PinConfig) Pin {
p := Pin{ p := Pin{
Direction: config.Direction, Direction: config.Direction,
PullConfig: config.PullConfig, PullConfig: config.PullConfig,
Name: config.Name, Name: config.Name,
Id: config.PinNumber, Id: config.PinNumber,
PinHandle: rpio.Pin(config.PinNumber), PinHandle: NewHardwarePin(config.PinNumber),
} }
if config.SendPollingEvents != nil { if config.SendPollingEvents != nil {
@ -49,14 +47,14 @@ func NewPin(config PinConfig) Pin {
} }
func (p *Pin) State() PinState { func (p *Pin) State() PinState {
if state := p.PinHandle.Read(); state == rpio.High { if state := p.PinHandle.Read(); State(state) == HighState {
return StateOn return StateOn
} else { } else {
return StateOff return StateOff
} }
} }
func (p *Pin) Command(cmd PinCommand) error{ func (p *Pin) Command(cmd PinCommand) error {
log.Debugf("try to send command %s for pin %s (pin no: %d)", cmd, p.Name, p.Id) log.Debugf("try to send command %s for pin %s (pin no: %d)", cmd, p.Name, p.Id)
if p.Direction != Output { if p.Direction != Output {
return errors.New("pin is not an output") return errors.New("pin is not an output")
@ -83,7 +81,7 @@ func (p *Pin) Configure() {
_ = p.Command(p.InitialState) _ = p.Command(p.InitialState)
} }
p.PinHandle.Detect(rpio.AnyEdge) p.PinHandle.Detect(AnyEdge)
if p.PullConfig == PullUp { if p.PullConfig == PullUp {
p.PinHandle.PullUp() p.PinHandle.PullUp()
@ -98,4 +96,3 @@ func (p *Pin) Configure() {
func (p *Pin) Changed() bool { func (p *Pin) Changed() bool {
return p.PinHandle.EdgeDetected() return p.PinHandle.EdgeDetected()
} }

View File

@ -3,32 +3,25 @@ package PinControlService
import ( import (
"errors" "errors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/stianeikeland/go-rpio"
"time" "time"
) )
type PinControlService struct { type PinControlService struct {
Pins map[string]Pin Pins map[string]Pin
timer* time.Ticker timer *time.Ticker
exit chan bool exit chan bool
OnChangeCallback PinCallback OnChangeCallback PinCallback
OnCycleCallback PinCallback OnCycleCallback PinCallback
} }
func (p *PinControlService) AddPin(
func (p*PinControlService) AddPin(
config PinConfig) { config PinConfig) {
pin := NewPin(config) pin := NewPin(config)
p.Pins[pin.Name] = pin p.Pins[pin.Name] = pin
} }
func (p*PinControlService) Command(pinName string, command PinCommand) error { func (p *PinControlService) Command(pinName string, command PinCommand) error {
if pin, found := p.Pins[pinName]; found == false { if pin, found := p.Pins[pinName]; found == false {
return errors.New("pin not configured") return errors.New("pin not configured")
} else { } else {
@ -36,25 +29,25 @@ func (p*PinControlService) Command(pinName string, command PinCommand) error {
} }
} }
func (p*PinControlService) Start() { func (p *PinControlService) Start() {
if err := rpio.Open(); err != nil { if err := HardwarePinOpen(); err != nil {
log.Fatal(err) log.Fatal(err)
panic(err) panic(err)
} }
for _,v := range p.Pins { for _, v := range p.Pins {
v.Configure() v.Configure()
} }
go p._task() go p._task()
} }
func (p*PinControlService) Stop() { func (p *PinControlService) Stop() {
p.exit <- true p.exit <- true
} }
func (p*PinControlService) _task() { func (p *PinControlService) _task() {
for { for {
select { select {
case <- p.timer.C: case <-p.timer.C:
for pinName, pin := range p.Pins { for pinName, pin := range p.Pins {
log.Debug("timer event") log.Debug("timer event")
if pin.Changed() { if pin.Changed() {
@ -69,7 +62,7 @@ func (p*PinControlService) _task() {
p.OnCycleCallback(pinName, pin.State()) p.OnCycleCallback(pinName, pin.State())
} }
} }
case <- p.exit: case <-p.exit:
log.Debug("stop timer") log.Debug("stop timer")
p.timer.Stop() p.timer.Stop()
return return
@ -79,11 +72,10 @@ func (p*PinControlService) _task() {
} }
func NewPinControl(config *PinControlConfig) (*PinControlService, error) { func NewPinControl(config *PinControlConfig) (*PinControlService, error) {
p := PinControlService{ p := PinControlService{
Pins: make(map[string]Pin), Pins: make(map[string]Pin),
exit: make(chan bool,1), exit: make(chan bool, 1),
timer: time.NewTicker(time.Duration(config.PollingTimeMs) * time.Millisecond)} timer: time.NewTicker(time.Duration(config.PollingTimeMs) * time.Millisecond)}
for _, pinConfig := range config.GpioPins { for _, pinConfig := range config.GpioPins {
@ -91,4 +83,4 @@ func NewPinControl(config *PinControlConfig) (*PinControlService, error) {
} }
return &p, nil return &p, nil
} }