Proof of concept implementation of various ROTS features/requirements
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

170 lines
2.7 KiB

package main
import (
"fmt"
"io"
"log"
"strings"
"time"
"github.com/tarm/serial"
)
type TBM struct {
Commands chan *Command
Results chan *Result
Port *serial.Port
}
type Command struct {
command string
args []string
payload []byte
}
type Result struct {
output []byte
errcode []byte
}
func (t *TBM) Connect(device string, baud int) error {
t.Commands = make(chan *Command)
t.Results = make(chan *Result)
serialconfig := &serial.Config{Name: device, Baud: baud}
port, err := serial.OpenPort(serialconfig)
if err != nil {
return err
}
t.Port = port
return nil
}
func (t *TBM) Handle() error {
go handleResults(t.Port, t.Results)
go handleCommands(t.Port, t.Commands)
return nil
}
func (t *TBM) Close() {
t.Port.Close()
}
func deserialise(in io.Reader, init []byte) (*Result, []byte, error) {
var (
output, errorcode []byte
data, rest []byte
)
want_output := true
_ = copy(data, init)
for {
buf := make([]byte, 4096)
n, err := in.Read(buf)
if err != nil {
return nil, nil, err
}
n2 := n + len(data)
data = append(data, buf[:n]...)
for i := 0; i < n2; i++ {
// '\r' is really '\n'
if data[i] == '\r' {
data = append(data[:i], data[i+1:]...)
n2--
continue
}
if data[i] == 0x4 {
if want_output {
want_output = false
output = data[:i]
data = data[i+1:]
// The TBM gives us our own commands back
for j := 0; j < len(output); j++ {
if output[j] == '\n' {
output = output[j+1:]
break
}
}
break
} else {
errorcode = data[:i]
rest = data[i+1:]
return &Result{output, errorcode}, rest, nil
}
}
}
}
}
func handleResults(in io.Reader, c chan *Result) {
var (
res *Result
rest []byte
err error
)
for {
res, rest, err = deserialise(in, rest)
if err != nil {
log.Fatal(err)
}
c <- res
}
}
func serialise(out io.Writer, command string, args []string, payload []byte) error {
var quoted_args []string
var err error
quoted_args = append(quoted_args, command)
for _, arg := range args {
quoted_args = append(quoted_args, fmt.Sprintf("\"%s\"", arg))
}
out_string := strings.Join(quoted_args, " ")
output := []byte(out_string)
output = append(output, '\r')
_, err = out.Write(output)
// err is non nil if n != len(output)
if err != nil {
return err
}
if payload == nil {
return nil
}
// FIXME: wait for command to finish
time.Sleep(time.Second)
output = append(payload, 0x4)
_, err = out.Write(output)
return err
}
func handleCommands(out io.Writer, c chan *Command) {
for command := range c {
err := serialise(out, command.command, command.args, command.payload)
if err != nil {
log.Fatal(err)
}
}
}