Skip to content

Commit

Permalink
refactor: project structure cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
faryon93 committed Jul 21, 2020
1 parent 2aeec03 commit a151cb4
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 64 deletions.
87 changes: 87 additions & 0 deletions can/frame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package can

// ---------------------------------------------------------------------------------------
// imports
// ---------------------------------------------------------------------------------------

import (
"errors"
"fmt"
"strconv"
"time"
)

// ---------------------------------------------------------------------------------------
// types
// ---------------------------------------------------------------------------------------

type Frame struct {
Id int
Length int
Data [8]byte

Timestamp time.Time
}

// ---------------------------------------------------------------------------------------
// public functions
// ---------------------------------------------------------------------------------------

func ParseFrame(cmd string) (*Frame, error) {
msg := Frame{}

if len(cmd) < 5 {
return nil, errors.New("cmd not long enough")
}

id, err := strconv.ParseUint(cmd[1:4], 16, 16)
if err != nil {
return nil, err
}
msg.Id = int(id)

length, err := strconv.ParseUint(cmd[4:5], 10, 8)
if err != nil {
return nil, err
}
msg.Length = int(length)

if len(cmd) < 5+msg.Length*2 {
return nil, errors.New("cmd not long enough")
}

for i := 0; i < msg.Length; i++ {
d, err := strconv.ParseUint(cmd[5+2*i:5+2*i+2], 16, 8)
if err != nil {
return nil, err
}
msg.Data[i] = byte(d)
}

return &msg, nil
}

// ---------------------------------------------------------------------------------------
// public members
// ---------------------------------------------------------------------------------------

func (f *Frame) ToUint64() uint64 {
u := uint64(0)

for i := 0; i < f.Length; i++ {

u |= uint64(f.Data[i]) << (i * 8)
}

return u
}

func (f *Frame) String() string {
str := fmt.Sprintf("%x [%d] ", f.Id, f.Length)

for i := 0; i < f.Length; i++ {
str += fmt.Sprintf("%02x ", f.Data[i])
}

return str
}
31 changes: 31 additions & 0 deletions can/frame_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package can

// ---------------------------------------------------------------------------------------
// imports
// ---------------------------------------------------------------------------------------

import "testing"

// ---------------------------------------------------------------------------------------
// tests
// ---------------------------------------------------------------------------------------

func TestFrame_ToUint64(t *testing.T) {
msg := Frame{Length: 2, Data: [8]byte{1, 0, 0, 0, 0, 0, 0, 0}}
if msg.ToUint64() != 1 {
t.Errorf("ToUint64() should be 1 but was %d", msg.ToUint64())
return
}

msg = Frame{Length: 2, Data: [8]byte{4, 0, 0, 0xff, 0, 0, 0, 0}}
if msg.ToUint64() != 4 {
t.Errorf("ToUint64() should be 0 but was %d: length attribut not considered?", msg.ToUint64())
return
}

msg = Frame{Length: 2, Data: [8]byte{4, 1, 0, 0, 0, 0, 0, 0}}
if msg.ToUint64() != 260 {
t.Errorf("ToUint64() should be 260 but was %d: length attribut not considered?", msg.ToUint64())
return
}
}
93 changes: 77 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,57 @@
package main

// ---------------------------------------------------------------------------------------
// imports
// ---------------------------------------------------------------------------------------

import (
"bytes"
"errors"
"flag"
"github.com/tarm/serial"
"io"
"log"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"

"canlisten/can"

"github.com/tarm/serial"
)

// ---------------------------------------------------------------------------------------
// constants
// ---------------------------------------------------------------------------------------

const (
CmdCanTransmit = 't'
)

// ---------------------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------------------

var (
Device string
Device string
Running = true
)

func read(s *serial.Port) (string, error) {
// ---------------------------------------------------------------------------------------
// helper functions
// ---------------------------------------------------------------------------------------

func ReadNextCommand(s *serial.Port) (string, error) {
buf := make([]byte, 1)
str := bytes.NewBufferString("")

for {
for Running {
n, err := s.Read(buf)
if err != nil {
if err == io.EOF {
continue
} else if err != nil {
return "", err
}

Expand All @@ -37,43 +68,73 @@ func read(s *serial.Port) (string, error) {
return str.String(), nil
}
}

return "", errors.New("empty response")
}

func GetPrintableCmd(cmd string) string {
cmd = strings.Replace(cmd, "\r", "!", -1)
cmd = strings.Replace(cmd, "\a", "?", -1)

return cmd
}

// ---------------------------------------------------------------------------------------
// application entry
// ---------------------------------------------------------------------------------------

func main() {
flag.StringVar(&Device, "dev", "/dev/ttyACM0", "")
flag.Parse()

c := &serial.Config{Name: Device, Baud: 115200}
c := &serial.Config{Name: Device, Baud: 115200, ReadTimeout: 50 * time.Millisecond}
s, err := serial.OpenPort(c)
if err != nil {
log.Fatal(err)
}
defer s.Close()

// Open CAN interface with 1MBit/s
_, err = s.Write([]byte("C\rS8\rO\r"))
if err != nil {
log.Println("failed to open serial port")
}

stdout := log.New(os.Stdout, "", log.LstdFlags | log.Lmicroseconds)
for {
cmd, err := read(s)
// gracefull shutdown on sigint/sigterm
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigs
Running = false
log.Println("closing application")
}()

// print all can messages to stdout
stdout := log.New(os.Stdout, "", log.LstdFlags|log.Lmicroseconds)
canCounter := 0
for Running {
cmd, err := ReadNextCommand(s)
if err != nil {
log.Println("read failed:", err.Error())
log.Println("ReadNextCommand failed:", err.Error())
continue
}

if cmd[0] != 't' {
if cmd[0] != CmdCanTransmit {
log.Printf("ignoring command \"%s\": unexpected opcode", GetPrintableCmd(cmd))
continue
}

can, err := ParseMsgCan(cmd)
frame, err := can.ParseFrame(cmd)
if err != nil {
cmd = strings.Replace(cmd, "\r", "!", -1)
cmd = strings.Replace(cmd, "\a", "?", -1)
log.Printf("failed to parse message \"%s\": %s", cmd, err.Error())
log.Printf("failed to parse message \"%s\": %s", GetPrintableCmd(cmd), err.Error())
continue
}
frame.Timestamp = time.Now()

stdout.Printf("%s %s", filepath.Base(Device), can.String())
// count message and print to stdout
canCounter++
stdout.Printf("%s %s", filepath.Base(Device), frame.String())
}

log.Printf("statistics: rx=%d", canCounter)
}
48 changes: 0 additions & 48 deletions msg_can.go

This file was deleted.

0 comments on commit a151cb4

Please sign in to comment.