Skip to content

Commit

Permalink
update serial writer to retry initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
dmowcomber committed Aug 8, 2024
1 parent 1ea22db commit b5e4089
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 25 deletions.
35 changes: 28 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ func main() {
Baud: 115200,
ReadTimeout: 1 * time.Second,
}
serialWriter, err := serial.OpenPort(serialConfig)
if err != nil {
log.Fatal(err)
}
log.Println("connected")

port := 8080
Expand All @@ -53,18 +49,43 @@ func main() {
ReadTimeout: 1 * time.Second,
}

track := rail.NewTrack(serialWriter)
track := rail.New()
apiServer := api.New(track, router, httpServer)

throt := throttle.New(address, serialWriter)
throt := throttle.New(address)
throttleCLI := cli.New(throt, track)

go func() {
log.Println("initializing serial writter")
var lastErr error

ticker := time.NewTicker(500 * time.Millisecond)
go func() {
for range ticker.C {
serialWriter, err := serial.OpenPort(serialConfig)
if err != nil {
if lastErr == nil || err.Error() != lastErr.Error() {
log.Printf("failed to initialize serial writer: %s", err.Error())
log.Println("silently retrying to initializes serial writter")
lastErr = err
}
continue
}
track.SetWriter(serialWriter)
throt.SetWriter(serialWriter)
log.Println("successfully initialized serial writter")
return
}
}()
}()

go signalWatcher(track, apiServer, throttleCLI)

// run the cli
go throttleCLI.Run()

// run api server
err = apiServer.Run()
err := apiServer.Run()
if err != nil {
log.Fatalf("unable to start the api: %q", err.Error())
}
Expand Down
16 changes: 12 additions & 4 deletions rail/track.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rail

import (
"errors"
"io"
"log"
"sort"
Expand Down Expand Up @@ -29,15 +30,18 @@ type Track struct {
roster map[int]*throttle.Throttle
}

// NewTrack returns a new Track
func NewTrack(serial io.ReadWriter) *Track {
// New returns a new Track
func New() *Track {
return &Track{
serial: serial,
mu: &sync.Mutex{},
roster: make(map[int]*throttle.Throttle),
}
}

func (t *Track) SetWriter(serial io.ReadWriter) {
t.serial = serial
}

// GetThrottle returns a throttle for a given address.
// It creates one if needed.
func (t *Track) GetThrottle(address int) *throttle.Throttle {
Expand All @@ -46,7 +50,8 @@ func (t *Track) GetThrottle(address int) *throttle.Throttle {

throt, ok := t.roster[address]
if !ok {
throt = throttle.New(address, t.serial)
throt = throttle.New(address)
throt.SetWriter(t.serial)
t.roster[address] = throt
}
return throt
Expand Down Expand Up @@ -109,6 +114,9 @@ func (t *Track) writeString(s string) error {
}

func (t *Track) write(data []byte) error {
if t.serial == nil {
return errors.New("serial writer has not been initialized")
}
start := time.Now()
defer func() {
serialWriteLatency.Observe(time.Since(start).Seconds())
Expand Down
6 changes: 4 additions & 2 deletions rail/track_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
)

func TestTrackThrottles(t *testing.T) {
track := NewTrack(&fakeReaderWriter{})
track := New()
track.SetWriter(&fakeReaderWriter{})
throttle3 := track.GetThrottle(3)
assert.NotNil(t, throttle3)
throttle42 := track.GetThrottle(42)
Expand All @@ -19,7 +20,8 @@ func TestTrackThrottles(t *testing.T) {

func TestTrackPower(t *testing.T) {
readerWriter := &fakeReaderWriter{}
track := NewTrack(readerWriter)
track := New()
track.SetWriter(readerWriter)

track.PowerOn()
assert.Equal(t, "<1>", string(readerWriter.writtenBytes))
Expand Down
15 changes: 11 additions & 4 deletions throttle/throttle.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package throttle

import (
"errors"
"fmt"
"io"
"log"
Expand All @@ -19,15 +20,18 @@ type Throttle struct {
direction int
}

func New(address int, serial io.ReadWriter) *Throttle {
func New(address int) *Throttle {
return &Throttle{
address: address,
serial: serial,
functions: make(map[uint]bool),
direction: 1, // start in forward direction
}
}

func (t *Throttle) SetWriter(serial io.ReadWriter) {
t.serial = serial
}

func (t *Throttle) Reset() error {
t.mu.Lock()
defer t.mu.Unlock()
Expand All @@ -43,14 +47,14 @@ func (t *Throttle) Reset() error {

func (t *Throttle) DirectionForward() error {
t.mu.Lock()
t.mu.Unlock()
defer t.mu.Unlock()
t.direction = 1
return t.writeSpeedAndDirection()
}

func (t *Throttle) DirectionBackward() error {
t.mu.Lock()
t.mu.Unlock()
defer t.mu.Unlock()
t.direction = 0
return t.writeSpeedAndDirection()
}
Expand Down Expand Up @@ -150,6 +154,9 @@ func (t *Throttle) writeString(s string) error {
}

func (t *Throttle) write(data []byte) error {
if t.serial == nil {
return errors.New("serial writer has not been initialized")
}
log.Printf("writing data: %s\n", data)
_, err := t.serial.Write(data)
if err != nil {
Expand Down
15 changes: 10 additions & 5 deletions throttle/throttle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
func TestThrottleSpeed(t *testing.T) {
address := 3
readerWriter := &fakeReaderWriter{}
throt := New(address, readerWriter)
throt := New(address)
throt.SetWriter(readerWriter)

expectedSpeed := 5
throt.SetSpeed(expectedSpeed)
Expand All @@ -35,7 +36,8 @@ func TestThrottleSpeed(t *testing.T) {
func TestThrottleIndividualFunctions(t *testing.T) {
address := 3
readerWriter := &fakeReaderWriter{}
throt := New(address, readerWriter)
throt := New(address)
throt.SetWriter(readerWriter)

testCases := []struct {
function uint
Expand Down Expand Up @@ -84,7 +86,8 @@ func TestThrottleIndividualFunctions(t *testing.T) {
func TestThrottleAllFunctions(t *testing.T) {
address := 3
readerWriter := &fakeReaderWriter{}
throt := New(address, readerWriter)
throt := New(address)
throt.SetWriter(readerWriter)

testCases := []struct {
functions []uint
Expand All @@ -110,7 +113,8 @@ func TestThrottleAllFunctions(t *testing.T) {
}

func TestThrottleInvalidFunction(t *testing.T) {
throt := New(3, &fakeReaderWriter{})
throt := New(3)
throt.SetWriter(&fakeReaderWriter{})
_, err := throt.ToggleFunction(29)
assert.Error(t, err)
}
Expand All @@ -119,7 +123,8 @@ func TestThrottleWriteError(t *testing.T) {
readerWriter := &fakeReaderWriter{
writeErr: errors.New("failed to write"),
}
throt := New(3, readerWriter)
throt := New(3)
throt.SetWriter(readerWriter)
err := throt.SetSpeed(10)
assert.Error(t, err)
}
Expand Down
9 changes: 6 additions & 3 deletions ui/api/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
func TestStateHandlerDefaultState(t *testing.T) {
req := &http.Request{}
rw := &fakeResponseWriter{}
track := rail.NewTrack(&noopReaderWriter{})
track := rail.New()
track.SetWriter(&noopReaderWriter{})
// create new addresses
track.GetThrottle(3)
track.GetThrottle(42)
Expand Down Expand Up @@ -46,7 +47,8 @@ func TestStateHandlerDefaultState(t *testing.T) {
func TestStateHandler(t *testing.T) {
req := &http.Request{}
rw := &fakeResponseWriter{}
track := rail.NewTrack(&noopReaderWriter{})
track := rail.New()
track.SetWriter(&noopReaderWriter{})
api := &API{
track: track,
}
Expand Down Expand Up @@ -91,7 +93,8 @@ func TestStateHandler(t *testing.T) {
func TestStateHandlerNoThrottles(t *testing.T) {
req := &http.Request{}
rw := &fakeResponseWriter{}
track := rail.NewTrack(&noopReaderWriter{})
track := rail.New()
track.SetWriter(&noopReaderWriter{})
api := &API{
track: track,
}
Expand Down

0 comments on commit b5e4089

Please sign in to comment.