2019-12-27 17:23:08 +00:00
|
|
|
package part
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/cyrilix/robocar-base/service"
|
|
|
|
"github.com/cyrilix/robocar-pca9685/actuator"
|
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"
|
2020-01-01 19:54:38 +00:00
|
|
|
"github.com/golang/protobuf/proto"
|
2021-10-12 17:28:56 +00:00
|
|
|
"go.uber.org/zap"
|
2019-12-27 17:23:08 +00:00
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Pca9685Part struct {
|
|
|
|
client MQTT.Client
|
|
|
|
throttleCtrl *actuator.Throttle
|
|
|
|
steeringCtrl *actuator.Steering
|
|
|
|
|
|
|
|
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 *actuator.Throttle, steeringCtrl *actuator.Steering, updateFrequency int, throttleTopic, steeringTopic string) *Pca9685Part {
|
|
|
|
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
|
|
|
|
|
|
|
p.steeringCtrl.SetPercentValue(0)
|
|
|
|
p.throttleCtrl.SetPercentValue(0)
|
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)
|
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()
|
2020-01-01 19:54:38 +00:00
|
|
|
p.throttleCtrl.SetPercentValue(throttle.GetThrottle())
|
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
|
|
|
|
}
|
|
|
|
p.muSteering.Lock()
|
|
|
|
defer p.muSteering.Unlock()
|
2020-01-01 19:54:38 +00:00
|
|
|
p.steeringCtrl.SetPercentValue(steering.GetSteering())
|
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
|
|
|
|
}
|