initial commit

This commit is contained in:
2022-12-16 23:27:24 +01:00
commit 60487a79db
13 changed files with 550 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
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
SendPollingEvents bool
SendChangeEvents bool
}
func NewPin(config PinConfig) Pin {
p := Pin{
Direction: config.Direction,
PullConfig: config.PullConfig,
Name: config.Name,
Id: config.PinNumber,
PinHandle: rpio.Pin(config.PinNumber),
}
if config.SendPollingEvents != nil {
p.SendPollingEvents = *config.SendPollingEvents
} else {
p.SendPollingEvents = true
}
if config.SendChangeEvents != nil {
p.SendChangeEvents = *config.SendChangeEvents
} else {
p.SendChangeEvents = true
}
if config.InitialState != "" {
p.InitialState = PinCommand(config.InitialState)
} else {
p.InitialState = Off
}
return p
}
func (p *Pin) State() PinState {
if state := p.PinHandle.Read(); state == rpio.High {
return StateOn
} else {
return StateOff
}
}
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")
}
if cmd == On {
p.PinHandle.High()
} else if cmd == Off {
p.PinHandle.Low()
} else if cmd == Toggle {
p.PinHandle.Toggle()
} else {
return errors.New("unknown command")
}
return nil
}
func (p *Pin) Configure() {
if p.Direction == Input {
p.PinHandle.Input()
} else if p.Direction == Output {
p.PinHandle.Output()
_ = p.Command(p.InitialState)
}
p.PinHandle.Detect(rpio.AnyEdge)
if p.PullConfig == PullUp {
p.PinHandle.PullUp()
} else if p.PullConfig == PullDown {
p.PinHandle.PullDown()
} else if p.PullConfig == PullOff {
p.PinHandle.PullOff()
}
}
func (p *Pin) Changed() bool {
return p.PinHandle.EdgeDetected()
}

View File

@@ -0,0 +1,25 @@
package PinControlService
type PinConfig struct {
PinNumber int `yaml:"number"`
Name string `yaml:"name"`
Direction PinDirection `yaml:"direction"`
PullConfig PinPull `yaml:"pull-config"`
InitialState PinCommand `yaml:"initial-state"`
SendPollingEvents *bool `yaml:"send-polling-events"`
SendChangeEvents *bool `yaml:"send-change-events"`
}
type PinControlConfig struct {
GpioPins []PinConfig `yaml:"gpio-pins"`
PollingTimeMs int `yaml:"polling-time-ms"`
}
func NewPinControlConfig() PinControlConfig {
return PinControlConfig{
GpioPins: make([]PinConfig, 0),
PollingTimeMs: 100,
}
}

View File

@@ -0,0 +1,94 @@
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
OnChangeCallback PinCallback
OnCycleCallback PinCallback
}
func (p*PinControlService) AddPin(
config PinConfig) {
pin := NewPin(config)
p.Pins[pin.Name] = pin
}
func (p*PinControlService) Command(pinName string, command PinCommand) error {
if pin, found := p.Pins[pinName]; found == false {
return errors.New("pin not configured")
} else {
return pin.Command(command)
}
}
func (p*PinControlService) Start() {
if err := rpio.Open(); err != nil {
log.Fatal(err)
panic(err)
}
for _,v := range p.Pins {
v.Configure()
}
go p._task()
}
func (p*PinControlService) Stop() {
p.exit <- true
}
func (p*PinControlService) _task() {
for {
select {
case <- p.timer.C:
for pinName, pin := range p.Pins {
log.Debug("timer event")
if pin.Changed() {
log.Debugf("detected pin change for pin %s (pin no %d)", pin.Name, pin.Id)
if pin.SendChangeEvents && p.OnChangeCallback != nil {
p.OnChangeCallback(pinName, pin.State())
}
}
if pin.SendPollingEvents && p.OnCycleCallback != nil {
p.OnCycleCallback(pinName, pin.State())
}
}
case <- p.exit:
log.Debug("stop timer")
p.timer.Stop()
return
}
}
}
func NewPinControl(config *PinControlConfig) (*PinControlService, error) {
p := PinControlService{
Pins: make(map[string]Pin),
exit: make(chan bool,1),
timer: time.NewTicker(time.Duration(config.PollingTimeMs) * time.Millisecond)}
for _, pinConfig := range config.GpioPins {
p.AddPin(pinConfig)
}
return &p, nil
}

View File

@@ -0,0 +1,23 @@
package PinControlService
type PinCommand string
type PinState string
type PinDirection string
type PinPull string
type PinCallback func(pinName string, state PinState)
const (
On PinCommand = "ON"
Off PinCommand = "OFF"
Toggle PinCommand = "TOGGLE"
StateOn PinState = "ON"
StateOff PinState = "OFF"
Input PinDirection = "Input"
Output PinDirection = "Output"
PullUp PinPull = "PULL_UP"
PullDown PinPull = "PULL_DOWN"
PullOff PinPull = "PULL_OFF"
)