feat: red on brake
This commit is contained in:
parent
c971d51015
commit
8b67d8a434
@ -15,7 +15,8 @@ const (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var mqttBroker, username, password, clientId string
|
var mqttBroker, username, password, clientId string
|
||||||
var driveModeTopic, recordTopic, speedZoneTopic string
|
var driveModeTopic, recordTopic, speedZoneTopic, throttleTopic string
|
||||||
|
var enableSpeedZoneMode bool
|
||||||
|
|
||||||
mqttQos := cli.InitIntFlag("MQTT_QOS", 0)
|
mqttQos := cli.InitIntFlag("MQTT_QOS", 0)
|
||||||
_, mqttRetain := os.LookupEnv("MQTT_RETAIN")
|
_, mqttRetain := os.LookupEnv("MQTT_RETAIN")
|
||||||
@ -25,6 +26,8 @@ func main() {
|
|||||||
flag.StringVar(&driveModeTopic, "mqtt-topic-drive-mode", os.Getenv("MQTT_TOPIC_DRIVE_MODE"), "Mqtt topic that contains DriveMode value, use MQTT_TOPIC_DRIVE_MODE if args not set")
|
flag.StringVar(&driveModeTopic, "mqtt-topic-drive-mode", os.Getenv("MQTT_TOPIC_DRIVE_MODE"), "Mqtt topic that contains DriveMode value, use MQTT_TOPIC_DRIVE_MODE if args not set")
|
||||||
flag.StringVar(&recordTopic, "mqtt-topic-record", os.Getenv("MQTT_TOPIC_RECORD"), "Mqtt topic that contains video recording state, use MQTT_TOPIC_RECORD if args not set")
|
flag.StringVar(&recordTopic, "mqtt-topic-record", os.Getenv("MQTT_TOPIC_RECORD"), "Mqtt topic that contains video recording state, use MQTT_TOPIC_RECORD if args not set")
|
||||||
flag.StringVar(&speedZoneTopic, "mqtt-topic-speed-zone", os.Getenv("MQTT_TOPIC_SPEED_ZONE"), "Mqtt topic that contains speed zone, use MQTT_TOPIC_SPEED_ZONE if args not set")
|
flag.StringVar(&speedZoneTopic, "mqtt-topic-speed-zone", os.Getenv("MQTT_TOPIC_SPEED_ZONE"), "Mqtt topic that contains speed zone, use MQTT_TOPIC_SPEED_ZONE if args not set")
|
||||||
|
flag.StringVar(&throttleTopic, "mqtt-topic-throttle", os.Getenv("MQTT_TOPIC_THROTTLE"), "Mqtt topic that contains throttle, use MQTT_TOPIC_THROTTLE if args not set")
|
||||||
|
flag.BoolVar(&enableSpeedZoneMode, "enable-speedzone-mode", false, "Enable speed-zone mode")
|
||||||
|
|
||||||
logLevel := zap.LevelFlag("log", zap.InfoLevel, "log level")
|
logLevel := zap.LevelFlag("log", zap.InfoLevel, "log level")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -53,7 +56,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer client.Disconnect(50)
|
defer client.Disconnect(50)
|
||||||
|
|
||||||
p := part.NewPart(client, driveModeTopic, recordTopic, speedZoneTopic)
|
mode := part.LedModeBrake
|
||||||
|
if enableSpeedZoneMode {
|
||||||
|
mode = part.LedModeSpeedZone
|
||||||
|
}
|
||||||
|
p := part.NewPart(client, driveModeTopic, recordTopic, speedZoneTopic, throttleTopic, mode)
|
||||||
defer p.Stop()
|
defer p.Stop()
|
||||||
|
|
||||||
cli.HandleExit(p)
|
cli.HandleExit(p)
|
||||||
|
@ -12,29 +12,41 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewPart(client mqtt.Client, driveModeTopic, recordTopic, speedZoneTopic string) *LedPart {
|
const (
|
||||||
|
LedModeBrake LedMode = iota
|
||||||
|
LedModeSpeedZone
|
||||||
|
)
|
||||||
|
|
||||||
|
type LedMode int
|
||||||
|
|
||||||
|
func NewPart(client mqtt.Client, driveModeTopic, recordTopic, speedZoneTopic, throttleTopic string, ledMode LedMode) *LedPart {
|
||||||
return &LedPart{
|
return &LedPart{
|
||||||
led: led.New(),
|
led: led.New(),
|
||||||
|
mode: ledMode,
|
||||||
client: client,
|
client: client,
|
||||||
onDriveModeTopic: driveModeTopic,
|
onDriveModeTopic: driveModeTopic,
|
||||||
onRecordTopic: recordTopic,
|
onRecordTopic: recordTopic,
|
||||||
onSpeedZoneTopic: speedZoneTopic,
|
onSpeedZoneTopic: speedZoneTopic,
|
||||||
|
onThrottleTopic: throttleTopic,
|
||||||
muDriveMode: sync.Mutex{},
|
muDriveMode: sync.Mutex{},
|
||||||
driveMode: events.DriveMode_INVALID,
|
driveMode: events.DriveMode_INVALID,
|
||||||
muRecord: sync.Mutex{},
|
muRecord: sync.Mutex{},
|
||||||
recordEnabled: false,
|
recordEnabled: false,
|
||||||
muSpeedZone: sync.Mutex{},
|
muSpeedZone: sync.Mutex{},
|
||||||
speedZone: events.SpeedZone_UNKNOWN,
|
speedZone: events.SpeedZone_UNKNOWN,
|
||||||
|
muThrottle: sync.Mutex{},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LedPart struct {
|
type LedPart struct {
|
||||||
led led.ColoredLed
|
led led.ColoredLed
|
||||||
|
mode LedMode
|
||||||
client mqtt.Client
|
client mqtt.Client
|
||||||
onDriveModeTopic string
|
onDriveModeTopic string
|
||||||
onRecordTopic string
|
onRecordTopic string
|
||||||
onSpeedZoneTopic string
|
onSpeedZoneTopic string
|
||||||
|
onThrottleTopic string
|
||||||
|
|
||||||
muDriveMode sync.Mutex
|
muDriveMode sync.Mutex
|
||||||
driveMode events.DriveMode
|
driveMode events.DriveMode
|
||||||
@ -43,6 +55,9 @@ type LedPart struct {
|
|||||||
|
|
||||||
muSpeedZone sync.Mutex
|
muSpeedZone sync.Mutex
|
||||||
speedZone events.SpeedZone
|
speedZone events.SpeedZone
|
||||||
|
|
||||||
|
muThrottle sync.Mutex
|
||||||
|
throttle float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *LedPart) Start() error {
|
func (p *LedPart) Start() error {
|
||||||
@ -57,7 +72,7 @@ func (p *LedPart) Start() error {
|
|||||||
func (p *LedPart) Stop() {
|
func (p *LedPart) Stop() {
|
||||||
defer p.led.SetBlink(0)
|
defer p.led.SetBlink(0)
|
||||||
defer p.led.SetColor(led.ColorBlack)
|
defer p.led.SetColor(led.ColorBlack)
|
||||||
service.StopService("led", p.client, p.onDriveModeTopic, p.onRecordTopic, p.onSpeedZoneTopic)
|
service.StopService("led", p.client, p.onDriveModeTopic, p.onRecordTopic, p.onSpeedZoneTopic, p.onThrottleTopic)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *LedPart) setDriveMode(m events.DriveMode) {
|
func (p *LedPart) setDriveMode(m events.DriveMode) {
|
||||||
@ -119,12 +134,46 @@ func (p *LedPart) onSpeedZone(_ mqtt.Client, message mqtt.Message) {
|
|||||||
p.updateColor()
|
p.updateColor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *LedPart) setThrottle(throttle float32) {
|
||||||
|
p.muThrottle.Lock()
|
||||||
|
defer p.muThrottle.Unlock()
|
||||||
|
p.throttle = throttle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *LedPart) onThrottle(_ mqtt.Client, message mqtt.Message) {
|
||||||
|
var throttleMessage events.ThrottleMessage
|
||||||
|
err := proto.Unmarshal(message.Payload(), &throttleMessage)
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Errorf("unable to unmarshal %T message: %v", throttleMessage, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.setThrottle(throttleMessage.GetThrottle())
|
||||||
|
p.updateColor()
|
||||||
|
}
|
||||||
|
|
||||||
func (p *LedPart) updateColor() {
|
func (p *LedPart) updateColor() {
|
||||||
p.muSpeedZone.Lock()
|
p.muSpeedZone.Lock()
|
||||||
defer p.muSpeedZone.Unlock()
|
defer p.muSpeedZone.Unlock()
|
||||||
p.muDriveMode.Lock()
|
p.muDriveMode.Lock()
|
||||||
defer p.muDriveMode.Unlock()
|
defer p.muDriveMode.Unlock()
|
||||||
|
p.muThrottle.Lock()
|
||||||
|
defer p.muThrottle.Unlock()
|
||||||
|
|
||||||
|
if p.throttle <= -0.05 {
|
||||||
|
p.led.SetColor(led.Color{Red: int(p.throttle * -255)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p.mode {
|
||||||
|
case LedModeBrake:
|
||||||
|
p.updateBrakeColor()
|
||||||
|
case LedModeSpeedZone:
|
||||||
|
p.updateSpeedZoneColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *LedPart) updateSpeedZoneColor() {
|
||||||
switch p.driveMode {
|
switch p.driveMode {
|
||||||
case events.DriveMode_USER:
|
case events.DriveMode_USER:
|
||||||
p.led.SetColor(led.ColorGreen)
|
p.led.SetColor(led.ColorGreen)
|
||||||
@ -142,6 +191,16 @@ func (p *LedPart) updateColor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *LedPart) updateBrakeColor() {
|
||||||
|
|
||||||
|
switch p.driveMode {
|
||||||
|
case events.DriveMode_USER:
|
||||||
|
p.led.SetColor(led.ColorGreen)
|
||||||
|
case events.DriveMode_PILOT:
|
||||||
|
p.led.SetColor(led.ColorBlue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *LedPart) registerCallbacks() error {
|
func (p *LedPart) registerCallbacks() error {
|
||||||
err := service.RegisterCallback(p.client, p.onDriveModeTopic, p.onDriveMode)
|
err := service.RegisterCallback(p.client, p.onDriveModeTopic, p.onDriveMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -158,5 +217,10 @@ func (p *LedPart) registerCallbacks() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = service.RegisterCallback(p.client, p.onThrottleTopic, p.onThrottle)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func TestLedPart_OnDriveMode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
value := msg.DriveMode
|
value := msg.DriveMode
|
||||||
if l.color != c.color {
|
if l.color != c.color {
|
||||||
t.Errorf("driveMode(%v)=invalid value for color: %v, wants %v", value, l.color, c.color)
|
t.Errorf("driveMode(%v)=invalid value for expectedColor: %v, wants %v", value, l.color, c.color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ func TestLedPart_OnRecord(t *testing.T) {
|
|||||||
|
|
||||||
func TestLedPart_OnSpeedZone(t *testing.T) {
|
func TestLedPart_OnSpeedZone(t *testing.T) {
|
||||||
l := fakeLed{}
|
l := fakeLed{}
|
||||||
p := LedPart{led: &l, driveMode: events.DriveMode_PILOT}
|
p := LedPart{led: &l, mode: LedModeSpeedZone, driveMode: events.DriveMode_PILOT}
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg mqtt.Message
|
msg mqtt.Message
|
||||||
@ -109,7 +109,65 @@ func TestLedPart_OnSpeedZone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
value := msg.GetSpeedZone()
|
value := msg.GetSpeedZone()
|
||||||
if l.color != c.color {
|
if l.color != c.color {
|
||||||
t.Errorf("driveMode(%v)=invalid value for color: %v, wants %v", value, l.color, c.color)
|
t.Errorf("driveMode(%v)=invalid value for expectedColor: %v, wants %v", value, l.color, c.color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLedPart_OnThrottle(t *testing.T) {
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
msg mqtt.Message
|
||||||
|
expectedColor led.Color
|
||||||
|
}{
|
||||||
|
{"throttle stop",
|
||||||
|
testtools.NewFakeMessageFromProtobuf("throttle", &events.ThrottleMessage{Throttle: 0.}),
|
||||||
|
led.ColorBlue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"throttle normal",
|
||||||
|
testtools.NewFakeMessageFromProtobuf("throttle", &events.ThrottleMessage{Throttle: 0.5}),
|
||||||
|
led.ColorBlue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"near zero",
|
||||||
|
testtools.NewFakeMessageFromProtobuf("throttle", &events.ThrottleMessage{Throttle: -0.01}),
|
||||||
|
led.ColorBlue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"slow brake",
|
||||||
|
testtools.NewFakeMessageFromProtobuf("throttle", &events.ThrottleMessage{Throttle: -0.06}),
|
||||||
|
led.Color{Red: 15},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"normal brake",
|
||||||
|
testtools.NewFakeMessageFromProtobuf("throttle", &events.ThrottleMessage{Throttle: -0.5}),
|
||||||
|
led.Color{Red: 127},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"high brake",
|
||||||
|
testtools.NewFakeMessageFromProtobuf("throttle", &events.ThrottleMessage{Throttle: -1.}),
|
||||||
|
led.ColorRed,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
l := fakeLed{}
|
||||||
|
p := LedPart{led: &l, mode: LedModeBrake, driveMode: events.DriveMode_PILOT}
|
||||||
|
|
||||||
|
p.onThrottle(nil, c.msg)
|
||||||
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
var msg events.ThrottleMessage
|
||||||
|
err := proto.Unmarshal(c.msg.Payload(), &msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to unmarshal drive mode message: %v", err)
|
||||||
|
}
|
||||||
|
value := msg.GetThrottle()
|
||||||
|
if l.color != c.expectedColor {
|
||||||
|
t.Errorf("driveMode(%v)=invalid value for expectedColor: %v, wants %v", value, l.color, c.expectedColor)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user