package main import ( "encoding/binary" "fmt" "io" "joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/train_pc_sim" "log/slog" "net" "strconv" "strings" ) type TcpConnHandler = func(conn net.Conn) type TcpMsgHandler = func(n int, data []byte) func tcpRunAcceptTask(listen net.Listener, port int, connHandler TcpConnHandler, msgHandler TcpMsgHandler) { go func() { defer func() { if err := recover(); err != nil { slog.Error(fmt.Sprintf("TCP服务端[port:%d]接收连接任务异常:", port), err) tcpRunAcceptTask(listen, port, connHandler, msgHandler) } }() for { conn, err := listen.Accept() if err != nil { slog.Error(fmt.Sprintf("TCP服务端[port:%d]接收连接出错:", port), err) } connHandler(conn) tcpRunReadTask(conn, port, msgHandler) } }() } func tcpRunReadTask(conn net.Conn, port int, msgHandler TcpMsgHandler) { go func() { /* defer func() { if err := recover(); err != nil { slog.Error(fmt.Sprintf("TCP服务端[port:%d]读数据任务异常:", port), err) serConn.Close() serConn = nil } }()*/ for { data := make([]byte, 1024) l, err := conn.Read(data) if err != nil { if err == io.EOF { slog.Warn(fmt.Sprintf("TCP服务端[port:%d]断开[%s]连接:", port, conn.RemoteAddr().String())) break } slog.Error(fmt.Sprintf("TCP服务端[port:%d]读取[%s]数据出错:", port, conn.RemoteAddr().String()), err) } msgHandler(l, data) } }() } func StartTcpServer(port int, connHandler TcpConnHandler, msgHandler TcpMsgHandler) (net.Listener, error) { listen, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) if err != nil { return nil, err } tcpRunAcceptTask(listen, port, connHandler, msgHandler) return listen, err } var serConnMap map[int]net.Conn = make(map[int]net.Conn) func createServer(port int, h TcpMsgHandler) { StartTcpServer(port, func(conn net.Conn) { fmt.Println("TCP服务端接收到连接") serConnMap[port] = conn }, h) } func connTrain() *message.TrainPcSimBaseMessage { msg := &message.TrainPcSimBaseMessage{} msg.Type = train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE msg.Data = []byte{0x01} return msg } func changeDoorMode() *message.TrainPcSimBaseMessage { msg := &message.TrainPcSimBaseMessage{} msg.Type = train_pc_sim.RECIVE_TRAIN_DOOR_MODE msg.Data = []byte{0x02} return msg } func boolsToByte(flags [8]bool) byte { var result uint8 for index, b := range flags { if b { result = result + (1 << index) } } return result } func pcSimInfoOut() *message.TrainPcSimBaseMessage { msg := &message.TrainPcSimBaseMessage{} msg.Type = train_pc_sim.RECIVE_TRAIN_INTERFACE_CABINET_OUTR data := make([]byte, 0) data = append(data, boolsToByte([8]bool{false, false, false, false, false, false, false, false})) data = append(data, boolsToByte([8]bool{false, false, false, false, false, false, false, false})) data = append(data, boolsToByte([8]bool{false, false, false, false, false, false, false, false})) data = append(data, boolsToByte([8]bool{false, false, false, false, false, false, false, false})) data = append(data, boolsToByte([8]bool{true, false, false, false, false, false, false, false})) msg.Data = data return msg } func pcSimInfoOutReport() *message.TrainPcSimBaseMessage { msg := &message.TrainPcSimBaseMessage{} msg.Type = train_pc_sim.RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK data := make([]byte, 0) data = append(data, boolsToByte([8]bool{true, true, false, false, false, false, false, false})) msg.Data = data return msg } var autoIncNo = 0 func queryBtm() *message.TrainPcSimBaseMessage { msg := &message.TrainPcSimBaseMessage{} msg.Type = train_pc_sim.RECIVE_TRAIN_QUERY_STATUS autoIncNo = autoIncNo + 1 data := make([]byte, 0) data = append(data, 0x62) data = append(data, 0x81) data = append(data, 0x02) data = append(data, byte(autoIncNo)<<3) data = append(data, boolsToByte([8]bool{true, true, false, false, false, false, false, false})) data = append(data, 0) //速度低位 data = append(data, 0) //当前时间高位 data = append(data, 0) //当前时间 data = append(data, 0) //当前时间 data = append(data, 0) //当前时间低位 data = append(data, 0) //当前时间低位 data = append(data, 0) //CRC16-H(MSB data = append(data, 0) //CRC16-L(LSB) msg.Data = data return msg } func pcSimNumReportOut() *message.TrainPcSimBaseMessage { msg := &message.TrainPcSimBaseMessage{} msg.Type = train_pc_sim.RECIVE_TRAIN_MOCK_DATA sd := uint16(1234) data := make([]byte, 2) binary.BigEndian.PutUint16(data, sd) msg.Data = data return msg } // 测试创建连接 /*func TestConn(t *testing.T) { createServer(func(n int, data []byte) { }) select {} }*/ func startService(port int) { createServer(port, func(n int, data []byte) { msg := &message.TrainPcSimBaseMessage{} d := data[:n] msg.Decode(d) pd := fmt.Sprintf("%X", d) if msg.Type == train_pc_sim.SENDER_TRAIN_TC_ACTIVE { fmt.Println("接收驾驶端激活 port:", port) } else if msg.Type == train_pc_sim.SENDER_TRAIN_TC_NOT_ACTIVE { fmt.Println("接收驾驶端未激活 port:", port) fmt.Println(pd) } else if msg.Type == train_pc_sim.SENDER_TRAIN_OUTR_INFO { fmt.Println(pd) t := msg.Data[0] s := msg.Data[1] tt := strconv.Itoa(int(t)) switch t { case 0: tt = "驾驶台" case 1: tt = "手柄向前" case 2: tt = "手柄向后" case 14: tt = "手柄归零" case 4: tt = "制动状态" } fmt.Println("接受列车输出数字量", tt, s, port) fmt.Println(pd) } else if msg.Type == train_pc_sim.RECIVE_TRAIN_CREATE_REMOVE { state := msg.Data[0] if state == 0x01 { fmt.Println("创建列车 port:", port) } else if state == 0x00 { fmt.Println("删除列车 port:", port) } fmt.Println(pd) } else if msg.Type == train_pc_sim.SENDER_TRAIN_HAND_KEY_FORWARD { fmt.Println("列车手柄向前 port:", port) fmt.Println(pd) } else if msg.Type == train_pc_sim.RECIVE_TRAIN_HAND_KEY_CANCLE_FORWARD { fmt.Println("列车手柄取消向前 port:", port) fmt.Println(pd) } else if msg.Type == train_pc_sim.RECIVE_TRAIN_HAND_KEY_BACKWARD { fmt.Println("列车手柄向后 port:", port) fmt.Println(pd) } else if msg.Type == train_pc_sim.RECIVE_TRAIN_HAND_KEY_CACLE_BACKWARD { fmt.Println("列车手柄取消向后 port:", port) fmt.Println(pd) } else if msg.Type == train_pc_sim.RECIVE_TRAIN_BTM_HAS_DATA { fmt.Println("有数据应答 port:", port) fmt.Println(pd) } else if msg.Type == train_pc_sim.RECIVE_TRAIN_BTM_NOT_DATA { } /*else if msg.Type == train_pc_sim.SENDER_TRAIN_LOCATION_INFO { fmt.Println("列车速度位置报告") fmt.Println(pd) mp := message.TrainSpeedPlaceReportMsg{} mp.Decode(msg.Data) }*/ }) } func main() { port1 := 5600 port2 := 5601 go startService(port1) go startService(port2) //reader := bufio.NewReader(os.Stdin) var command string for { fmt.Scanln(&command) if command != "" { fmt.Println(command) } strs := strings.Split(command, ",") if len(strs) < 2 { fmt.Println("eeeeeeee") command = "" continue } p1s, comm := strs[0], strs[1] portInt, _ := strconv.Atoi(p1s) serConn := serConnMap[portInt] command = comm if command == "create-train" { msg := connTrain() serConn.Write(msg.Encode()) } else if command == "door-mode" { msg := changeDoorMode() serConn.Write(msg.Encode()) } else if command == "info-out" { msg := pcSimInfoOut() serConn.Write(msg.Encode()) } else if command == "info-out-report" { msg := pcSimInfoOutReport() serConn.Write(msg.Encode()) } else if command == "query-btm" { msg := queryBtm() serConn.Write(msg.Encode()) } else if command == "num-out" { msg := pcSimNumReportOut() serConn.Write(msg.Encode()) } command = "" /*content, _ := reader.ReadString('\n') if content == "create-train" { }*/ } select {} }