From a4004a1d053ecca987452efd5568bfb55bc104c1 Mon Sep 17 00:00:00 2001 From: JiXieShi Date: Fri, 19 Apr 2024 15:08:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A1=B9=E7=9B=AE=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- command.go | 49 +++++++++++++++++++ config.go | 14 ++++++ flag.go | 97 +++++++++++++++++++++++++++++++++++++ main.go | 139 ++++++++++++----------------------------------------- 4 files changed, 190 insertions(+), 109 deletions(-) create mode 100644 command.go create mode 100644 config.go create mode 100644 flag.go diff --git a/command.go b/command.go new file mode 100644 index 0000000..25613a7 --- /dev/null +++ b/command.go @@ -0,0 +1,49 @@ +package main + +import ( + "encoding/hex" + "fmt" + "log" + "os" + "strings" +) + +type Command struct { + name string + description string + function func() +} + +func cmdhelp() { + var page = 0 + fmt.Printf(">-------Help(%v)-------<\n", page) + for i := 0; i < len(commands); i++ { + strout(config.outputCode, fmt.Sprintf(" %-10v --%v\n", commands[i].name, commands[i].description)) + } +} +func cmdexit() { + os.Exit(0) +} +func cmdargs() { + fmt.Printf(">-------Args(%v)-------<\n", len(args)-1) + fmt.Printf("%q\n", args[1:]) +} +func cmdhex() { + fmt.Printf(">-----Hex Send-----<\n") + fmt.Printf("%q\n", args[1:]) + s := strings.Join(args[1:], "") + b, err := hex.DecodeString(s) + if err != nil { + log.Fatal(err) + } + _, err = serialPort.Write(b) + if err != nil { + log.Fatal(err) + } +} +func cmdinit() { + commands = append(commands, Command{name: ".help", description: "帮助信息", function: cmdhelp}) + commands = append(commands, Command{name: ".args", description: "参数信息", function: cmdargs}) + commands = append(commands, Command{name: ".hex", description: "发送Hex", function: cmdhex}) + commands = append(commands, Command{name: ".exit", description: "退出终端", function: cmdexit}) +} diff --git a/config.go b/config.go new file mode 100644 index 0000000..e3f44ca --- /dev/null +++ b/config.go @@ -0,0 +1,14 @@ +package main + +type Config struct { + portName string + baudRate int + dataBits int + stopBits int + outputCode string + inputCode string + endStr string + enableLog bool + logFilePath string + parityBit int +} diff --git a/flag.go b/flag.go new file mode 100644 index 0000000..2912b6b --- /dev/null +++ b/flag.go @@ -0,0 +1,97 @@ +package main + +import ( + "flag" + "fmt" + "strings" +) + +type ptrVal struct { + *string + *int + *bool + *float64 + *float32 +} +type Val struct { + string + int + bool + float64 + float32 +} +type Flag struct { + v ptrVal + sStr string + lStr string + dv Val + help string +} + +var ( + portName = Flag{ptrVal{string: &config.portName}, "p", "port", Val{string: ""}, "要连接的串口\t(/dev/ttyUSB0、COMx)"} + baudRate = Flag{ptrVal{int: &config.baudRate}, "b", "baud", Val{int: 115200}, "波特率"} + dataBits = Flag{ptrVal{int: &config.dataBits}, "d", "data", Val{int: 8}, "数据位"} + stopBits = Flag{ptrVal{int: &config.stopBits}, "s", "stop", Val{int: 0}, "停止位停止位(0: 1停止 1:1.5停止 2:2停止)"} + outputCode = Flag{ptrVal{string: &config.outputCode}, "o", "out", Val{string: "UTF-8"}, "输出编码"} + inputCode = Flag{ptrVal{string: &config.inputCode}, "i", "in", Val{string: "UTF-8"}, "输入编码"} + endStr = Flag{ptrVal{string: &config.endStr}, "e", "end", Val{string: "\n"}, "终端换行符"} + enableLog = Flag{ptrVal{bool: &config.enableLog}, "l", "log", Val{bool: false}, "是否启用日志保存"} + logFilePath = Flag{ptrVal{string: &config.logFilePath}, "P", "Path", Val{string: "./Log.txt"}, "日志保存路径"} + parityBit = Flag{ptrVal{int: &config.parityBit}, "v", "verify", Val{int: 0}, "奇偶校验(0:无校验、1:奇校验、2:偶校验、3:1校验、4:0校验)"} + flags = []Flag{portName, baudRate, dataBits, stopBits, outputCode, inputCode, endStr, enableLog, logFilePath, parityBit} +) + +type ValType int + +const ( + notVal ValType = iota + stringVal + intVal + boolVal + floatVal +) + +func printUsage(ports []string) { + fmt.Printf("\n参数帮助:\n") + for _, f := range flags { + flagprint(f) + } + fmt.Printf("\n在线串口: %v\n", strings.Join(ports, ",")) +} +func flagFindValue(v ptrVal) ValType { + if v.string != nil { + return stringVal + } + if v.bool != nil { + return boolVal + } + if v.int != nil { + return intVal + } + return notVal +} +func flagprint(f Flag) { + switch flagFindValue(f.v) { + case stringVal: + fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%q\n", f.sStr, f.lStr, f.dv.string, f.help, f.dv.string) + case intVal: + fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", f.sStr, f.lStr, f.dv.int, f.help, f.dv.int) + case boolVal: + fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", f.sStr, f.lStr, f.dv.bool, f.help, f.dv.bool) + } +} +func flagInit(f *Flag) { + if f.v.string != nil { + flag.StringVar(f.v.string, f.sStr, f.dv.string, "") + flag.StringVar(f.v.string, f.lStr, f.dv.string, f.help) + } + if f.v.bool != nil { + flag.BoolVar(f.v.bool, f.sStr, f.dv.bool, "") + flag.BoolVar(f.v.bool, f.lStr, f.dv.bool, f.help) + } + if f.v.int != nil { + flag.IntVar(f.v.int, f.sStr, f.dv.int, "") + flag.IntVar(f.v.int, f.lStr, f.dv.int, f.help) + } +} diff --git a/main.go b/main.go index 8949050..c616fc4 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "encoding/hex" "flag" "fmt" "github.com/zimolab/charsetconv" @@ -13,24 +12,6 @@ import ( "strings" ) -type Config struct { - enableLog bool - logFilePath string - portName string - endStr string - inputCode string - outputCode string - baudRate int - parityBit int - stopBits int - dataBits int -} -type Command struct { - name string - description string - function func() -} - var ( config Config commands []Command @@ -39,105 +20,37 @@ var ( args []string ) -func checkPortAvailability() { +func checkPortAvailability(name string) ([]string, error) { ports, err := serial.GetPortsList() if err != nil { log.Fatal(err) } if len(ports) == 0 { - log.Fatal("未找到串口!") + return nil, fmt.Errorf("无串口") + } + if name == "" { + return ports, fmt.Errorf("串口未指定") } - fmt.Printf("找到的串口: ") for _, port := range ports { - fmt.Printf(" %v", port) + if strings.Compare(port, name) == 0 { + return ports, nil + } } + return ports, fmt.Errorf("串口 " + name + " 未在线") } -func printUsage() { - checkPortAvailability() - fmt.Printf("\n参数帮助:\n") - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "p", "port", "", "连接的串口(/dev/ttyUSB0、COMx)", "") - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "b", "baud", 115200, "波特率", 115200) - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "d", "data", 8, "数据位", 8) - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "s", "stop", 0, "停止位停止位(0: 1停止 1:1.5停止 2:2停止)", 0) - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "o", "out", "UTF-8", "输出编码", "UTF-8") - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "i", "in", "UTF-8", "输入编码", "UTF-8") - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "e", "end", "\n", "终端换行符", "\\n") - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "l", "log", false, "是否启用日志保存", false) - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "P", "Path", "./Log.txt", "日志保存路径", "./Log.txt") - fmt.Printf("\t-%v -%v %T \n\t %v\t默认值:%v\n", "v", "verify", 0, "奇偶校验(0:无校验、1:奇校验、2:偶校验、3:1校验、4:0校验)", 0) -} func init() { log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile | log.Lmsgprefix) - flag.BoolVar(&config.enableLog, "log", false, "是否启用日志保存") - flag.BoolVar(&config.enableLog, "l", false, "") - - flag.StringVar(&config.logFilePath, "Path", "./Log.txt", "日志保存路径") - flag.StringVar(&config.logFilePath, "P", "./Log.txt", "") - - flag.StringVar(&config.portName, "port", "", "连接的串口\t(/dev/ttyUSB0、COMx)") - flag.StringVar(&config.portName, "p", "", "") - - flag.StringVar(&config.endStr, "end", "\n", "终端换行符") - flag.StringVar(&config.endStr, "e", "\n", "") - - flag.IntVar(&config.baudRate, "baud", 115200, "波特率") - flag.IntVar(&config.baudRate, "b", 115200, "") - - flag.IntVar(&config.parityBit, "verify", 0, "奇偶校验(0:无校验 1:奇校验 2:偶校验 3:1校验 4:0校验)") - flag.IntVar(&config.parityBit, "v", 0, "") - - flag.IntVar(&config.stopBits, "stop", 0, "停止位(0: 1停止 1:1.5停止 2:2停止)") - flag.IntVar(&config.stopBits, "s", 0, "") - - flag.IntVar(&config.dataBits, "data", 8, "数据位") - flag.IntVar(&config.dataBits, "d", 8, "") - - flag.StringVar(&config.outputCode, "out", "UTF-8", "输出编码") - flag.StringVar(&config.outputCode, "o", "UTF-8", "") - - flag.StringVar(&config.inputCode, "in", "UTF-8", "输入编码") - flag.StringVar(&config.inputCode, "i", "UTF-8", "") + for _, f := range flags { + flagInit(&f) + } cmdinit() } -func cmdhelp() { - var page = 0 - fmt.Printf(">-------Help(%v)-------<\n", page) - for i := 0; i < len(commands); i++ { - strout(config.outputCode, fmt.Sprintf(" %-10v --%v\n", commands[i].name, commands[i].description)) - } -} -func cmdexit() { - os.Exit(0) -} -func cmdargs() { - fmt.Printf(">-------Args(%v)-------<\n", len(args)-1) - fmt.Printf("%q\n", args[1:]) -} -func cmdhex() { - fmt.Printf(">-----Hex Send-----<\n") - fmt.Printf("%q\n", args[1:]) - s := strings.Join(args[1:], "") - b, err := hex.DecodeString(s) - if err != nil { - log.Fatal(err) - } - _, err = serialPort.Write(b) - if err != nil { - log.Fatal(err) - } -} -func cmdinit() { - commands = append(commands, Command{name: ".help", description: "帮助信息", function: cmdhelp}) - commands = append(commands, Command{name: ".args", description: "参数信息", function: cmdargs}) - commands = append(commands, Command{name: ".hex", description: "发送Hex", function: cmdhex}) - commands = append(commands, Command{name: ".exit", description: "退出终端", function: cmdexit}) -} + func input() { input := bufio.NewScanner(os.Stdin) var ok = false - for { - input.Scan() + for input.Scan() { ok = false args = strings.Split(input.Text(), " ") for _, cmd := range commands { @@ -147,29 +60,35 @@ func input() { } } if !ok { - _, err := serialPort.Write(input.Bytes()) + _, err := io.WriteString(serialPort, input.Text()) if err != nil { log.Fatal(err) } _, err = io.WriteString(serialPort, config.endStr) - //_, err = io.Copy(portName, os.Stdin) if err != nil { log.Fatal(err) } } + err := serialPort.Drain() + if err != nil { + log.Fatal(err) + } } } + func strout(cs, str string) { err = charsetconv.EncodeWith(strings.NewReader(str), os.Stdout, charsetconv.Charset(cs), false) if err != nil { log.Fatal(err) } } + func output(out io.Writer) { if strings.Compare(config.inputCode, "hex") == 0 { - _, err = io.Copy(hex.NewEncoder(out), serialPort) + b, _ := bufio.NewReader(io.LimitReader(serialPort, 16)).Peek(16) + _, err = fmt.Fprintf(out, "% X %q \n", b, b) } else { - err = charsetconv.ConvertWith(serialPort, charsetconv.Charset(config.inputCode), out, charsetconv.Charset(config.outputCode), false) + err = charsetconv.ConvertWith(io.LimitReader(serialPort, 1024), charsetconv.Charset(config.inputCode), out, charsetconv.Charset(config.outputCode), false) } if err != nil { log.Fatal(err) @@ -177,9 +96,10 @@ func output(out io.Writer) { } func main() { flag.Parse() - if config.portName == "" { - fmt.Println("端口未指定") - printUsage() + ports, err := checkPortAvailability(config.portName) + if err != nil { + fmt.Println(err) + printUsage(ports) os.Exit(0) } mode := &serial.Mode{ @@ -195,10 +115,11 @@ func main() { defer func(port serial.Port) { err := port.Close() if err != nil { - } }(serialPort) + go input() + if config.enableLog { f, err := os.OpenFile(config.logFilePath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) if err != nil {