admin: add admin tool
This commit is contained in:
parent
6e5bf54598
commit
ba4a9b22f0
2 changed files with 267 additions and 0 deletions
109
admin/main.go
Normal file
109
admin/main.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommandFunc func(tbm *TBM, args []string) error
|
||||||
|
|
||||||
|
var (
|
||||||
|
serial_device = flag.String("serial-device", "/dev/ttyUSB0", "Serial device to use")
|
||||||
|
serial_baudrate = flag.Int("serial-baud", 9600, "Serial baud rate")
|
||||||
|
|
||||||
|
commands = map[string]CommandFunc{
|
||||||
|
"ls": cmd_ls,
|
||||||
|
"cat": cmd_cat,
|
||||||
|
"stat": cmd_stat,
|
||||||
|
"cp": cmd_cp,
|
||||||
|
"rm": cmd_rm,
|
||||||
|
"mkdir": cmd_mkdir,
|
||||||
|
"rmdir": cmd_rmdir,
|
||||||
|
"date": cmd_date,
|
||||||
|
"set-date": cmd_set_date,
|
||||||
|
"time": cmd_time,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func cmd_generic(tbm *TBM, command string, args []string) error {
|
||||||
|
cmd := &Command{command, args}
|
||||||
|
tbm.Commands <- cmd
|
||||||
|
res := <-tbm.Results
|
||||||
|
|
||||||
|
if res.errcode[0] != '0' {
|
||||||
|
return fmt.Errorf("Error: %s", res.errcode)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s", res.output)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_ls(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs ls", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_cat(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs cat", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_stat(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs stat", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_cp(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs cp", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_rm(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs rm", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_mkdir(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs mkdir", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_rmdir(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "mufs rmdir", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_date(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "date", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_set_date(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "set-date", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmd_time(tbm *TBM, args []string) error {
|
||||||
|
return cmd_generic(tbm, "time", args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
args := flag.Args()
|
||||||
|
if len(args) == 0 {
|
||||||
|
log.Fatalf("Please specify at least one command")
|
||||||
|
}
|
||||||
|
command := args[0]
|
||||||
|
|
||||||
|
command_function, ok := commands[command]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("Unknown command: %s", command)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &TBM{}
|
||||||
|
err := t.Connect(*serial_device, *serial_baudrate)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Handle()
|
||||||
|
defer t.Close()
|
||||||
|
|
||||||
|
err = command_function(t, args[1:])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
158
admin/tbm.go
Normal file
158
admin/tbm.go
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tarm/serial"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TBM struct {
|
||||||
|
Commands chan *Command
|
||||||
|
Results chan *Result
|
||||||
|
Port *serial.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
type Command struct {
|
||||||
|
command string
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
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) error {
|
||||||
|
var quoted_args []string
|
||||||
|
|
||||||
|
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')
|
||||||
|
//output = append(output, 0x4)
|
||||||
|
|
||||||
|
_, err := out.Write(output)
|
||||||
|
// err is non nil if n != len(output)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCommands(out io.Writer, c chan *Command) {
|
||||||
|
for command := range c {
|
||||||
|
err := serialise(out, command.command, command.args)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue