robocar-pca9685/pkg/part/part.go

131 lines
3.4 KiB
Go
Raw Normal View History

2019-12-27 17:23:08 +00:00
package part
import (
"fmt"
"github.com/cyrilix/robocar-base/service"
2020-01-01 19:54:38 +00:00
"github.com/cyrilix/robocar-protobuf/go/events"
2019-12-27 17:23:08 +00:00
MQTT "github.com/eclipse/paho.mqtt.golang"
2021-10-12 17:28:56 +00:00
"go.uber.org/zap"
2022-01-03 18:34:49 +00:00
"google.golang.org/protobuf/proto"
"io"
2019-12-27 17:23:08 +00:00
"sync"
)
type ActuatorController interface {
// SetPercentValue Set percent value
SetPercentValue(p float32) error
io.Closer
}
2019-12-27 17:23:08 +00:00
type Pca9685Part struct {
client MQTT.Client
throttleCtrl ActuatorController
steeringCtrl ActuatorController
2019-12-27 17:23:08 +00:00
muSteering sync.Mutex
2020-01-01 19:54:38 +00:00
steeringValue float32
2019-12-27 17:23:08 +00:00
muThrottle sync.Mutex
2020-01-01 19:54:38 +00:00
throttleValue float32
2019-12-27 17:23:08 +00:00
updateFrequency int
throttleTopic string
steeringTopic string
2020-01-01 19:43:13 +00:00
cancel chan interface{}
2019-12-27 17:23:08 +00:00
}
func NewPca9685Part(client MQTT.Client, throttleCtrl ActuatorController, steeringCtrl ActuatorController, updateFrequency int, throttleTopic, steeringTopic string) *Pca9685Part {
2019-12-27 17:23:08 +00:00
return &Pca9685Part{
client: client,
throttleCtrl: throttleCtrl,
steeringCtrl: steeringCtrl,
updateFrequency: updateFrequency,
throttleTopic: throttleTopic,
steeringTopic: steeringTopic,
2020-01-01 19:43:13 +00:00
cancel: make(chan interface{}),
2019-12-27 17:23:08 +00:00
}
}
func (p *Pca9685Part) Start() error {
if err := p.registerCallbacks(); err != nil {
return fmt.Errorf("unable to start service: %v", err)
}
2020-02-03 18:16:07 +00:00
if err := p.steeringCtrl.SetPercentValue(0); err != nil {
return fmt.Errorf("unable to start steering controller: %w", err)
}
if err := p.throttleCtrl.SetPercentValue(0); err != nil {
return fmt.Errorf("unable to set init value '0%%': %w", err)
}
2020-01-01 19:43:13 +00:00
2019-12-27 17:23:08 +00:00
for {
2020-01-01 19:43:13 +00:00
select {
case <-p.cancel:
return nil
}
2019-12-27 17:23:08 +00:00
}
}
func (p *Pca9685Part) Stop() {
2020-01-01 19:43:13 +00:00
close(p.cancel)
if err := p.steeringCtrl.Close(); err != nil {
zap.S().Errorf("unable to close steering controller: %v", err)
}
if err := p.throttleCtrl.Close(); err != nil {
zap.S().Errorf("unable to close throttle controller: %v", err)
}
2019-12-27 17:23:08 +00:00
service.StopService("pca9685", p.client, p.throttleTopic, p.steeringTopic)
}
func (p *Pca9685Part) onThrottleChange(_ MQTT.Client, message MQTT.Message) {
2020-01-01 19:54:38 +00:00
var throttle events.ThrottleMessage
err := proto.Unmarshal(message.Payload(), &throttle)
2019-12-27 17:23:08 +00:00
if err != nil {
2021-10-12 17:28:56 +00:00
zap.S().Warnw("unable to unmarshall throttle msg", "topic",
message.Topic(),
"error", err)
2019-12-27 17:23:08 +00:00
return
}
2021-10-12 17:28:56 +00:00
zap.S().Debugf("new throttle value: %v", throttle.GetThrottle())
2019-12-27 17:23:08 +00:00
p.muThrottle.Lock()
defer p.muThrottle.Unlock()
err = p.throttleCtrl.SetPercentValue(throttle.GetThrottle())
if err != nil {
zap.S().Errorf("unable to set steering value '%v': %w", throttle.GetThrottle(), err)
}
2019-12-27 17:23:08 +00:00
}
func (p *Pca9685Part) onSteeringChange(_ MQTT.Client, message MQTT.Message) {
2020-01-01 19:54:38 +00:00
var steering events.SteeringMessage
err := proto.Unmarshal(message.Payload(), &steering)
2019-12-27 17:23:08 +00:00
if err != nil {
2021-10-12 17:28:56 +00:00
zap.S().Warnw("unable to unmarshal steering msg",
"topic", message.Topic(),
"error", err,
)
2019-12-27 17:23:08 +00:00
return
}
2022-02-25 18:05:58 +00:00
zap.S().Debugf("new steering value: %v", steering.GetSteering())
2019-12-27 17:23:08 +00:00
p.muSteering.Lock()
defer p.muSteering.Unlock()
err = p.steeringCtrl.SetPercentValue(steering.GetSteering())
if err != nil {
zap.S().Errorf("unable to set steering value '%v': %w", steering.GetSteering(), err)
}
2019-12-27 17:23:08 +00:00
}
func (p *Pca9685Part) registerCallbacks() error {
err := service.RegisterCallback(p.client, p.throttleTopic, p.onThrottleChange)
if err != nil {
return fmt.Errorf("unable to register throttle callback: %v", err)
}
err = service.RegisterCallback(p.client, p.steeringTopic, p.onSteeringChange)
if err != nil {
return fmt.Errorf("unable to register steering callback: %v", err)
}
return nil
}