Skip to content

Commit

Permalink
go-client v0.5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
stfnmllr committed Mar 24, 2024
1 parent 77fb281 commit 62c8585
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 136 deletions.
63 changes: 31 additions & 32 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ name: build
on: [push]
jobs:

lint:
vetlint:
runs-on: ubuntu-latest
name: Go lint
name: Go vet lint

steps:

- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.22'

- run: |
- name: Vet
run: |
go vet ./...
- name: Lint
run: |
go install golang.org/x/lint/golint@latest
golint ./...
Expand All @@ -25,7 +30,7 @@ jobs:
matrix:
goos: [linux]
goarch: [amd64, arm, arm64]
go: ['1.20']
go: ['1.22.1']
fail-fast: false

name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build
Expand All @@ -34,6 +39,7 @@ jobs:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOARM: 6
GOTOOLCHAIN: go${{ matrix.go }}

steps:

Expand All @@ -42,13 +48,13 @@ jobs:
sudo apt-get update
sudo apt-get -y install qemu-user
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
go-version: ${{ matrix.go }}

- name: Get dependencies
run: |
go get -v -t -d ./...
Expand All @@ -57,25 +63,24 @@ jobs:
run: |
go build -v ./...
- name: Vet
run: |
go vet ./...
build-macos:
runs-on: macos-latest
strategy:
matrix:
go: ['1.20']
go: ['1.22.1']
fail-fast: false

name: Go ${{ matrix.go }} macOS

env:
GOTOOLCHAIN: go${{ matrix.go }}

steps:
- uses: actions/checkout@v3

- uses: actions/checkout@v4

- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}

Expand All @@ -87,25 +92,24 @@ jobs:
run: |
go build -v ./...
- name: Vet
run: |
go vet ./...
build-windows:
runs-on: windows-latest
strategy:
matrix:
go: ['1.20']
go: ['1.22.1']
fail-fast: false

name: Go ${{ matrix.go }} Windows

env:
GOTOOLCHAIN: go${{ matrix.go }}

steps:
- uses: actions/checkout@v3

- uses: actions/checkout@v4

- name: Setup go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}

Expand All @@ -116,8 +120,3 @@ jobs:
- name: Build
run: |
go build -v ./...
- name: Vet
run: |
go vet ./...
4 changes: 2 additions & 2 deletions .github/workflows/reuse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v1.1
uses: fsfe/reuse-action@v2
2 changes: 1 addition & 1 deletion .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ Upstream-Contact: stefan.miller_at_sap.com
Source: https://github.com/pico-cs/go-client

Files: *
Copyright: 2021-2023 Stefan Miller
Copyright: 2021-2024 Stefan Miller
License: GPL-3.0-or-later
25 changes: 14 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,28 @@ all:
go vet ./...
golint -set_exit_status=true ./...
staticcheck -checks all -fail none ./...
golangci-lint run ./...
go test ./...
#see fsfe reuse tool (https://git.fsfe.org/reuse/tool)
@echo "reuse (license) check"
reuse lint
pipx run reuse lint

#go generate
generate:
@echo "generate"
go generate ./...

#install additional tools
tools:
#install stringer
@echo "install latest stringer version"
go install golang.org/x/tools/cmd/stringer@latest
#install linter
@echo "install latest go linter version"
go install golang.org/x/lint/golint@latest
#install staticcheck
@echo "install latest staticcheck version"
go install honnef.co/go/tools/cmd/staticcheck@latest

#install fsfe reuse tool (https://git.fsfe.org/reuse/tool)
# pre-conditions:
# - Python 3.6+
# - pip
# install pre-conditions in Debian like linux distros:
# - sudo apt install python3
# - sudo apt install python3-pip
reuse:
pip3 install --user --upgrade reuse
#install golangci-lint
@echo "install latest golangci-lint version"
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@

## Licensing

Copyright 2021-2023 Stefan Miller and pico-cs contributers. Please see our [LICENSE](LICENSE.md) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/pico-cs/go-client).
Copyright 2021-2024 Stefan Miller and pico-cs contributers. Please see our [LICENSE](LICENSE.md) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/pico-cs/go-client).

56 changes: 39 additions & 17 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const (
const (
replyChSize = 1
pushChSize = 100
timeout = 5
timeout = 30
)

// Client represents a command station client instance.
Expand Down Expand Up @@ -160,16 +160,33 @@ func (c *Client) shutdown() error {
return err
}

// Reconnect tries to reconnect the client.
func (c *Client) reconnect() error {
var err error
for i := 0; i < reconnectRetry; i++ {
time.Sleep(reconnectWait)
if err = c.conn.Connect(); err == nil {
return nil
}
}
return err
}

// Reconnect reconnects the client.
func (c *Client) Reconnect() error {
c.shutdown() // ignore error
if err := c.conn.Reconnect(); err != nil {
c.shutdown() //nolint: errcheck
if err := c.reconnect(); err != nil {
return err
}
c.startup()
return nil
}

// IsSerialConn returns true if the connection is serial, false otherwise.
func (c *Client) IsSerialConn() bool {
_, ok := c.conn.(*Serial)
return ok
}

// Close closes the client connection.
func (c *Client) Close() error { return c.shutdown() }

Expand Down Expand Up @@ -212,12 +229,14 @@ func (c *Client) reader(wg *sync.WaitGroup) (<-chan any, <-chan string) {

scanner := bufio.NewScanner(c.conn)

//TODO check scanner.Error()

multi := false
var multiMsg []string

for scanner.Scan() {
if err := scanner.Err(); err != nil {
replyCh <- err
}

//log.Printf("message: %s", scanner.Text())

rk, msg := c.parseReply(scanner.Bytes())
Expand All @@ -244,9 +263,6 @@ func (c *Client) reader(wg *sync.WaitGroup) (<-chan any, <-chan string) {
multi = false
}
}
//if err := scanner.Err(); err != nil {
// fmt.Fprintln(os.Stderr, "reading standard input:", err)
//}

close(replyCh)
close(pushCh)
Expand All @@ -270,24 +286,25 @@ func (c *Client) pusher(wg *sync.WaitGroup, pushCh <-chan string, handler func(M
}

func (c *Client) write(cmd string, args []any) error {
c.w.WriteByte(tagStart)
c.w.WriteString(cmd)
c.w.WriteByte(tagStart) //nolint: errcheck
c.w.WriteString(cmd) //nolint: errcheck
for _, arg := range args {
c.w.WriteByte(' ') // argument separator
// argument separator
c.w.WriteByte(' ') //nolint: errcheck

rv := reflect.ValueOf(arg)
switch rv.Kind() {
case reflect.Bool:
c.w.WriteByte(formatBool(rv.Bool()))
c.w.WriteByte(formatBool(rv.Bool())) //nolint: errcheck
case reflect.Uint8, reflect.Uint:
c.w.WriteString(strconv.FormatUint(rv.Uint(), 10))
c.w.WriteString(strconv.FormatUint(rv.Uint(), 10)) //nolint: errcheck
case reflect.String:
c.w.WriteString(rv.String())
c.w.WriteString(rv.String()) //nolint: errcheck
default:
panic(fmt.Sprintf("invalid argument %[1]v type %[1]T", arg)) // should never happen
}
}
c.w.WriteByte('\r')
c.w.WriteByte('\r') //nolint: errcheck
if err := c.w.Flush(); err != nil {
return err
}
Expand Down Expand Up @@ -749,7 +766,12 @@ func (c *Client) FlashFormat() (bool, error) {
return strconv.ParseBool(v)
}

var rebootWait = 5 * time.Second

// Reboot reboots the command station (debugging).
func (c *Client) Reboot() error {
return c.call(cmdReboot)
err := c.call(cmdReboot)
// wait some time to be sure that device is re-booted.
time.Sleep(rebootWait)
return err
}
9 changes: 7 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ func testRefreshBuffer(c *client.Client, t *testing.T) {

func testRefreshBufferDelete(c *client.Client, t *testing.T) {
// reset refresh buffer
c.RefreshBufferReset()

if _, err := c.RefreshBufferReset(); err != nil {
t.Fatal(err)
}
if _, err := c.SetLocoSpeed128(3, 12); err != nil { // add loco to buffer
t.Fatal(err)
}
Expand Down Expand Up @@ -159,6 +160,10 @@ func testReboot(c *client.Client, t *testing.T) {
t.Fatal(err)
}
if err := c.Reconnect(); err != nil {
if c.IsSerialConn() { // after reboot connection port might be different.
t.Log(err)
return
}
t.Fatal(err)
}
testBoard(c, t)
Expand Down
4 changes: 2 additions & 2 deletions client/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (

const (
reconnectRetry = 10
reconnectWait = 5 * time.Second // wait some time to reconnect
reconnectWait = 500 * time.Millisecond
)

// Conn is a stream oriented connection to the pico board.
type Conn interface {
Reconnect() error
Connect() error
io.ReadWriteCloser
}
Loading

0 comments on commit 62c8585

Please sign in to comment.