5 Commits

Author SHA1 Message Date
jixishi
604e5bb4ad 修复帧指定的错误参数指向 2024-04-26 12:49:32 +08:00
jixishi
e3415ae05a 去除TCP服务端连接 2024-04-26 11:55:26 +08:00
jixishi
d19c09e4cd TCP|UDP 客户端数据转发支持更新 帧长设置支持 2024-04-26 11:03:44 +08:00
jixishi
5bf90d1b63 TCP|UDP 客户端数据转发支持更新 2024-04-19 22:42:28 +08:00
jixishi
dffb269247 RT 2024-04-19 17:03:28 +08:00
6 changed files with 106 additions and 33 deletions

View File

@@ -1,10 +1,19 @@
# SerialTerminalForWindowsTerminal # SerialTerminalForWindowsTerminal
编写这个项目之前在windows Terminal对串口设备的支持不是很棒, 开始这个项目之前我发现Windows Terminal对串口设备的支持并不理想。
用过一段时间的 我试用了一段时间[Zhou-zhi-peng的SerialPortForWindowsTerminal](https://github.com/Zhou-zhi-peng/SerialPortForWindowsTerminal/)项目。
[SerialPortForWindowsTerminal](https://github.com/Zhou-zhi-peng/SerialPortForWindowsTerminal/)
项目。 然而,这个项目存在着编码转换的问题,导致数据显示乱码,并且作者目前并没有进行后续支持。因此,我决定创建了这个项目。
此项目没有编码转换能力在使用过程中有乱码的问题,并且作者截至目前并没有进行后续支持,于是我便编写了此项目
## 功能进展
* [x] Hex接收发送(大写hex与原文同显)
* [x] 双向编码转换
* [x] 活动端口探测
* [x] 数据日志保存
* [x] Hex断帧设置
* [x] UDP数据转发
* [x] TCP数据转发
* [ ] 文件接收发送
## 运行示例 ## 运行示例

View File

@@ -18,21 +18,21 @@ var commands []Command
func cmdhelp() { func cmdhelp() {
var page = 0 var page = 0
fmt.Printf(">-------Help(%v)-------<\n", page) strout(out, config.outputCode, fmt.Sprintf(">-------Help(%v)-------<\n", page))
for i := 0; i < len(commands); i++ { for i := 0; i < len(commands); i++ {
strout(config.outputCode, fmt.Sprintf(" %-10v --%v\n", commands[i].name, commands[i].description)) strout(out, config.outputCode, fmt.Sprintf(" %-10v --%v\n", commands[i].name, commands[i].description))
} }
} }
func cmdexit() { func cmdexit() {
os.Exit(0) os.Exit(0)
} }
func cmdargs() { func cmdargs() {
fmt.Printf(">-------Args(%v)-------<\n", len(args)-1) strout(out, config.outputCode, fmt.Sprintf(">-------Args(%v)-------<\n", len(args)-1))
fmt.Printf("%q\n", args[1:]) strout(out, config.outputCode, fmt.Sprintf("%q\n", args[1:]))
} }
func cmdhex() { func cmdhex() {
fmt.Printf(">-----Hex Send-----<\n") strout(out, config.outputCode, fmt.Sprintf(">-----Hex Send-----<\n"))
fmt.Printf("%q\n", args[1:]) strout(out, config.outputCode, fmt.Sprintf("%q\n", args[1:]))
s := strings.Join(args[1:], "") s := strings.Join(args[1:], "")
b, err := hex.DecodeString(s) b, err := hex.DecodeString(s)
if err != nil { if err != nil {

View File

@@ -1,16 +1,51 @@
package main package main
import (
"log"
"net"
)
type Config struct { type Config struct {
portName string portName string
baudRate int baudRate int
dataBits int dataBits int
stopBits int stopBits int
parityBit int
outputCode string outputCode string
inputCode string inputCode string
endStr string endStr string
enableLog bool enableLog bool
logFilePath string logFilePath string
parityBit int forWard int
frameSize int
address string
} }
type FoeWardMode int
const (
NOT FoeWardMode = iota
TCPC
UDPC
)
var config Config var config Config
func setForWardClient() (conn net.Conn) {
switch FoeWardMode(config.forWard) {
case NOT:
case TCPC:
conn, err = net.Dial("tcp", config.address)
if err != nil {
log.Fatal(err)
}
case UDPC:
conn, err = net.Dial("udp", config.address)
if err != nil {
log.Fatal(err)
}
default:
panic("未知模式设置")
}
return conn
}

View File

@@ -38,8 +38,11 @@ var (
endStr = Flag{ptrVal{string: &config.endStr}, "e", "end", Val{string: "\n"}, "终端换行符"} endStr = Flag{ptrVal{string: &config.endStr}, "e", "end", Val{string: "\n"}, "终端换行符"}
enableLog = Flag{ptrVal{bool: &config.enableLog}, "l", "log", Val{bool: false}, "是否启用日志保存"} enableLog = Flag{ptrVal{bool: &config.enableLog}, "l", "log", Val{bool: false}, "是否启用日志保存"}
logFilePath = Flag{ptrVal{string: &config.logFilePath}, "P", "Path", Val{string: "./Log.txt"}, "日志保存路径"} logFilePath = Flag{ptrVal{string: &config.logFilePath}, "P", "Path", Val{string: "./Log.txt"}, "日志保存路径"}
forWard = Flag{ptrVal{int: &config.forWard}, "f", "forward", Val{int: 0}, "转发模式(0: 无 1:TCP-C 2:UDP-C)"}
address = Flag{ptrVal{string: &config.address}, "a", "address", Val{string: "127.0.0.1:12345"}, "转发服务地址"}
frameSize = Flag{ptrVal{int: &config.frameSize}, "F", "Frame", Val{int: 16}, "帧大小"}
parityBit = Flag{ptrVal{int: &config.parityBit}, "v", "verify", Val{int: 0}, "奇偶校验(0:无校验、1:奇校验、2:偶校验、3:1校验、4:0校验)"} 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} flags = []Flag{portName, baudRate, dataBits, stopBits, outputCode, inputCode, endStr, enableLog, logFilePath, forWard, address, frameSize, parityBit}
) )
type ValType int type ValType int

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 41 KiB

62
main.go
View File

@@ -8,6 +8,7 @@ import (
"go.bug.st/serial" "go.bug.st/serial"
"io" "io"
"log" "log"
"net"
"os" "os"
"strings" "strings"
) )
@@ -18,6 +19,13 @@ var (
args []string args []string
) )
var (
in io.Reader = os.Stdin
out io.Writer = os.Stdout
ins = []io.Reader{os.Stdin}
outs = []io.Writer{os.Stdout}
)
func checkPortAvailability(name string) ([]string, error) { func checkPortAvailability(name string) ([]string, error) {
ports, err := serial.GetPortsList() ports, err := serial.GetPortsList()
if err != nil { if err != nil {
@@ -45,10 +53,11 @@ func init() {
cmdinit() cmdinit()
} }
func input() { func input(in io.Reader) {
input := bufio.NewScanner(os.Stdin) input := bufio.NewScanner(in)
var ok = false var ok = false
for input.Scan() { for {
input.Scan()
ok = false ok = false
args = strings.Split(input.Text(), " ") args = strings.Split(input.Text(), " ")
for _, cmd := range commands { for _, cmd := range commands {
@@ -67,26 +76,29 @@ func input() {
log.Fatal(err) log.Fatal(err)
} }
} }
err := serialPort.Drain() err = serialPort.Drain()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
} }
func strout(cs, str string) { func strout(out io.Writer, cs, str string) {
err = charsetconv.EncodeWith(strings.NewReader(str), os.Stdout, charsetconv.Charset(cs), false) err = charsetconv.EncodeWith(strings.NewReader(str), out, charsetconv.Charset(cs), false)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
func output(out io.Writer) { func output() {
if strings.Compare(config.inputCode, "hex") == 0 { if strings.Compare(config.inputCode, "hex") == 0 {
b, _ := bufio.NewReader(io.LimitReader(serialPort, 16)).Peek(16) b := make([]byte, 16)
_, err = fmt.Fprintf(out, "% X %q \n", b, b) r, _ := io.LimitReader(serialPort, int64(config.frameSize)).Read(b)
if r != 0 {
strout(out, config.outputCode, fmt.Sprintf("% X %q \n", b, b))
}
} else { } else {
err = charsetconv.ConvertWith(io.LimitReader(serialPort, 1024), charsetconv.Charset(config.inputCode), out, charsetconv.Charset(config.outputCode), false) err = charsetconv.ConvertWith(serialPort, charsetconv.Charset(config.inputCode), out, charsetconv.Charset(config.outputCode), false)
} }
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@@ -113,23 +125,37 @@ func main() {
defer func(port serial.Port) { defer func(port serial.Port) {
err := port.Close() err := port.Close()
if err != nil { if err != nil {
log.Fatal(err)
} }
}(serialPort) }(serialPort)
go input() if FoeWardMode(config.forWard) != NOT {
conn := setForWardClient()
ins = append(ins, conn)
outs = append(outs, conn)
defer func(conn net.Conn) {
err := conn.Close()
if err != nil {
log.Fatal(err)
}
}(conn)
}
if len(ins) != 0 {
for _, reader := range ins {
go input(reader)
}
}
if config.enableLog { if config.enableLog {
f, err := os.OpenFile(config.logFilePath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) f, err := os.OpenFile(config.logFilePath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
out := io.MultiWriter(os.Stdout, f) outs = append(outs, f)
for {
output(out)
} }
} else { if len(outs) != 1 {
for { out = io.MultiWriter(outs...)
output(os.Stdout)
} }
for {
output()
} }
} }