diff --git a/go.mod b/go.mod index aea4869..142a2d4 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.17 require ( github.com/eclipse/paho.mqtt.golang v1.3.5 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 ) require ( 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/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect ) diff --git a/internal/PinControlService/HardwarePinEmu.go b/internal/PinControlService/HardwarePinEmu.go new file mode 100644 index 0000000..d571dbe --- /dev/null +++ b/internal/PinControlService/HardwarePinEmu.go @@ -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 +} diff --git a/internal/PinControlService/HardwarePinInterface.go b/internal/PinControlService/HardwarePinInterface.go new file mode 100644 index 0000000..af5935f --- /dev/null +++ b/internal/PinControlService/HardwarePinInterface.go @@ -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 +) diff --git a/internal/PinControlService/HardwarePinRpi.go b/internal/PinControlService/HardwarePinRpi.go new file mode 100644 index 0000000..2a9ebe1 --- /dev/null +++ b/internal/PinControlService/HardwarePinRpi.go @@ -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() +} diff --git a/internal/PinControlService/Pin.go b/internal/PinControlService/Pin.go index 3d2ec62..8c01ef1 100644 --- a/internal/PinControlService/Pin.go +++ b/internal/PinControlService/Pin.go @@ -3,28 +3,26 @@ package PinControlService import ( "errors" log "github.com/sirupsen/logrus" - "github.com/stianeikeland/go-rpio" ) type Pin struct { - Id int - Name string - Direction PinDirection - PullConfig PinPull - InitialState PinCommand - PinHandle rpio.Pin + Id int + Name string + Direction PinDirection + PullConfig PinPull + InitialState PinCommand + PinHandle HardwarePinInterface SendPollingEvents bool - SendChangeEvents bool - + SendChangeEvents bool } func NewPin(config PinConfig) Pin { p := Pin{ - Direction: config.Direction, + Direction: config.Direction, PullConfig: config.PullConfig, - Name: config.Name, - Id: config.PinNumber, - PinHandle: rpio.Pin(config.PinNumber), + Name: config.Name, + Id: config.PinNumber, + PinHandle: NewHardwarePin(config.PinNumber), } if config.SendPollingEvents != nil { @@ -49,14 +47,14 @@ func NewPin(config PinConfig) Pin { } func (p *Pin) State() PinState { - if state := p.PinHandle.Read(); state == rpio.High { + if state := p.PinHandle.Read(); State(state) == HighState { return StateOn } else { 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) if p.Direction != Output { return errors.New("pin is not an output") @@ -83,7 +81,7 @@ func (p *Pin) Configure() { _ = p.Command(p.InitialState) } - p.PinHandle.Detect(rpio.AnyEdge) + p.PinHandle.Detect(AnyEdge) if p.PullConfig == PullUp { p.PinHandle.PullUp() @@ -98,4 +96,3 @@ func (p *Pin) Configure() { func (p *Pin) Changed() bool { return p.PinHandle.EdgeDetected() } - diff --git a/internal/PinControlService/PinControlService.go b/internal/PinControlService/PinControlService.go index d9cd7c1..7dad069 100644 --- a/internal/PinControlService/PinControlService.go +++ b/internal/PinControlService/PinControlService.go @@ -3,32 +3,25 @@ package PinControlService import ( "errors" log "github.com/sirupsen/logrus" - "github.com/stianeikeland/go-rpio" "time" ) - - - - type PinControlService struct { - Pins map[string]Pin - timer* time.Ticker - exit chan bool + Pins map[string]Pin + timer *time.Ticker + exit chan bool OnChangeCallback PinCallback - OnCycleCallback PinCallback - + OnCycleCallback PinCallback } - -func (p*PinControlService) AddPin( +func (p *PinControlService) AddPin( config PinConfig) { pin := NewPin(config) 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 { return errors.New("pin not configured") } else { @@ -36,25 +29,25 @@ func (p*PinControlService) Command(pinName string, command PinCommand) error { } } -func (p*PinControlService) Start() { - if err := rpio.Open(); err != nil { +func (p *PinControlService) Start() { + if err := HardwarePinOpen(); err != nil { log.Fatal(err) panic(err) } - for _,v := range p.Pins { + for _, v := range p.Pins { v.Configure() } go p._task() } -func (p*PinControlService) Stop() { +func (p *PinControlService) Stop() { p.exit <- true } -func (p*PinControlService) _task() { +func (p *PinControlService) _task() { for { select { - case <- p.timer.C: + case <-p.timer.C: for pinName, pin := range p.Pins { log.Debug("timer event") if pin.Changed() { @@ -69,7 +62,7 @@ func (p*PinControlService) _task() { p.OnCycleCallback(pinName, pin.State()) } } - case <- p.exit: + case <-p.exit: log.Debug("stop timer") p.timer.Stop() return @@ -79,11 +72,10 @@ func (p*PinControlService) _task() { } - func NewPinControl(config *PinControlConfig) (*PinControlService, error) { p := PinControlService{ - Pins: make(map[string]Pin), - exit: make(chan bool,1), + Pins: make(map[string]Pin), + exit: make(chan bool, 1), timer: time.NewTicker(time.Duration(config.PollingTimeMs) * time.Millisecond)} for _, pinConfig := range config.GpioPins { @@ -91,4 +83,4 @@ func NewPinControl(config *PinControlConfig) (*PinControlService, error) { } return &p, nil -} \ No newline at end of file +}