diff --git a/config/config.go b/config/config.go index 16a2546..da11d70 100644 --- a/config/config.go +++ b/config/config.go @@ -32,8 +32,10 @@ type log struct { Stdout bool // 是否输出到控制台 } type dynamics struct { + Ip string UdpLocalPort int - UdpRemoteAddr string + UdpRemotePort int + HttpPort int } var Config AppConfig diff --git a/dynamics/example.go b/dynamics/example.go deleted file mode 100644 index e34d28a..0000000 --- a/dynamics/example.go +++ /dev/null @@ -1,8 +0,0 @@ -package dynamics - -// 该包下函数的使用示例 -func example() { - RunUdpServer() //启动udp服务 - _ = SendTurnoutInfo(nil) //发送道岔状态 - _ = SendTrainInitReq(nil) //发送列车初始化请求 -} diff --git a/dynamics/example/main.go b/dynamics/example/main.go new file mode 100644 index 0000000..ace1e57 --- /dev/null +++ b/dynamics/example/main.go @@ -0,0 +1,101 @@ +package main + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "github.com/gin-gonic/gin" + "github.com/panjf2000/gnet/v2" + "joylink.club/bj-rtsts-server/config" + "joylink.club/bj-rtsts-server/dynamics" + "log" + "net" + "strconv" + "time" +) + +// 这里用来测试通信与数据传输是否正常 + +func main() { + loadAndChangeConfig() + //注册列车信息处理逻辑 + dynamics.RegisterTrainInfoHandler(&ExampleTrainInfoHandler{}) + //启动udp服务 + go dynamics.RunUdpServer() + ////启动仅用于的测试的模拟远程udp服务 + go runTestUdpServer() + ////启动http服务 + go runTestHttpServer() + time.Sleep(2 * time.Second) + //向本地udp服务发送数据 + sendDataToLocalUdpServer() + //向远程udp服务发送数据 + _ = dynamics.SendTurnoutInfo(&dynamics.TurnoutInfo{Code: 02}) + //发送http请求 + _, _, _ = dynamics.SendTrainInitReq(&dynamics.InitTrainInfo{Speed: 10}) +} + +func loadAndChangeConfig() { + config.LoadConfig() + config.Config.Dynamics.Ip = "127.0.0.1" + config.Config.Dynamics.HttpPort = 3500 +} + +func sendDataToLocalUdpServer() { + addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:"+strconv.Itoa(config.Config.Dynamics.UdpLocalPort)) + conn, _ := net.DialUDP("udp", nil, addr) + buf, _ := hex.DecodeString("0009012EE009000000070380000006000100020003000A000A000A000A000A000A000A") + conn.Write(buf) + conn.Close() +} + +func runTestHttpServer() { + engine := gin.Default() + engine.POST("/api/aerodynamics/init/train", func(context *gin.Context) { + info := dynamics.InitTrainInfo{} + err := context.ShouldBindJSON(&info) + if err != nil { + println(err.Error()) + } + data, err := json.MarshalIndent(info, "", " ") + fmt.Println("---------------- 接收到的列车初始化信息 ----------------") + fmt.Println(string(data)) + if info.Speed != 10 { + println("http服务接收到的数据异常") + } + }) + engine.Run(fmt.Sprintf(":%d", config.Config.Dynamics.HttpPort)) +} + +func runTestUdpServer() { + server := &testUdpServer{addr: fmt.Sprintf("udp://:%d", config.Config.Dynamics.UdpRemotePort), multicore: false} + log.Fatal(gnet.Run(server, server.addr, gnet.WithMulticore(server.multicore))) +} + +type testUdpServer struct { + gnet.BuiltinEventEngine + + eng gnet.Engine + addr string + multicore bool + + eventHandlers []gnet.EventHandler +} + +func (server *testUdpServer) OnTraffic(c gnet.Conn) gnet.Action { + buf, err := c.Next(-1) + if err != nil { + println(err.Error()) + } + fmt.Println("---------------- 远程udp服务接收到的字节数据 ----------------") + fmt.Println(buf) + return gnet.None +} + +type ExampleTrainInfoHandler struct { +} + +func (handler *ExampleTrainInfoHandler) HandleTrainInfo(info dynamics.TrainInfo) { + fmt.Println("处理列车信息...") + fmt.Println(info) +} diff --git a/dynamics/http.go b/dynamics/http.go index 97127a6..78ba398 100644 --- a/dynamics/http.go +++ b/dynamics/http.go @@ -3,20 +3,32 @@ package dynamics import ( "bytes" "encoding/json" - "errors" + "fmt" + "go.uber.org/zap" + "joylink.club/bj-rtsts-server/config" "net/http" - "strconv" ) -func SendTrainInitReq(info *InitTrainInfo) error { - ip := "127.0.0.1" +func SendTrainInitReq(info *InitTrainInfo) (int, *[]byte, error) { + defer func() { + if r := recover(); r != nil { + zap.S().Error("发送列车初始化请求失败", r) + } + }() + ip := config.Config.Dynamics.Ip + var port string + if config.Config.Dynamics.HttpPort != 0 { + port = fmt.Sprintf(":%d", config.Config.Dynamics.HttpPort) + } uri := "/api/aerodynamics/init/train" - url := "http://" + ip + uri + url := "http://" + ip + port + uri data, _ := json.Marshal(info) resp, _ := http.Post(url, "application/json", bytes.NewBuffer(data)) - if resp.StatusCode != http.StatusOK { - return errors.New("响应的http状态码:" + strconv.Itoa(resp.StatusCode)) + var buf []byte + _, err := resp.Body.Read(buf) + if err != nil { + return resp.StatusCode, nil, err } - return resp.Body.Close() + return resp.StatusCode, &buf, resp.Body.Close() } diff --git a/dynamics/udp.go b/dynamics/udp.go index 97b0303..bb11e1f 100644 --- a/dynamics/udp.go +++ b/dynamics/udp.go @@ -2,27 +2,32 @@ package dynamics import ( "encoding/binary" - "errors" "fmt" "github.com/panjf2000/gnet/v2" + "go.uber.org/zap" "joylink.club/bj-rtsts-server/config" - "log" "net" ) -var server *udpServer - // SendTurnoutInfo 发送道岔信息 func SendTurnoutInfo(info *TurnoutInfo) error { - if server == nil { - return errors.New("服务尚未启动") - } - remoteAddr, _ := net.ResolveUDPAddr("udp", config.Config.Dynamics.UdpRemoteAddr) + defer func() { + if r := recover(); r != nil { + zap.S().Error("发送道岔信息失败", r) + } + }() + addr := fmt.Sprintf("%v:%v", config.Config.Dynamics.Ip, config.Config.Dynamics.UdpRemotePort) + remoteAddr, _ := net.ResolveUDPAddr("udp", addr) conn, err := net.DialUDP("udp", nil, remoteAddr) if err != nil { - panic(err) + zap.S().Error("UDP通信失败", err) } - defer conn.Close() + defer func(conn *net.UDPConn) { + err := conn.Close() + if err != nil { + zap.S().Error(err) + } + }(conn) var data []byte data = binary.BigEndian.AppendUint16(data, info.Code) var b byte @@ -50,12 +55,17 @@ type udpServer struct { func (server *udpServer) OnBoot(eng gnet.Engine) gnet.Action { server.eng = eng - log.Printf("echo server with multi-core=%t is listening on %s\n", server.multicore, server.addr) + zap.S().Infof("udp server with multi-core=%t is listening on %s\n", server.multicore, server.addr) return gnet.None } // OnTraffic 接收到数据后的解析 func (server *udpServer) OnTraffic(c gnet.Conn) gnet.Action { + defer func() { + if r := recover(); r != nil { + zap.S().Error("udp服务数据解析异常", r) + } + }() buf, _ := c.Next(-1) trainInfo := TrainInfo{} trainInfo.LifeSignal = binary.BigEndian.Uint16(buf[0:2]) @@ -78,12 +88,26 @@ func (server *udpServer) OnTraffic(c gnet.Conn) gnet.Action { trainInfo.TailSpeed2 = binary.BigEndian.Uint16(buf[29:31]) trainInfo.HeadRadarSpeed = binary.BigEndian.Uint16(buf[31:33]) trainInfo.TailRadarSpeed = binary.BigEndian.Uint16(buf[33:35]) - fmt.Println(trainInfo) + + for _, handler := range trainInfoHandlers { + handler.HandleTrainInfo(trainInfo) + } return gnet.None } -func RunUdpServer() { - server = &udpServer{addr: fmt.Sprintf("udp://:%d", config.Config.Dynamics.UdpLocalPort), multicore: false} - log.Fatal(gnet.Run(server, server.addr, gnet.WithMulticore(server.multicore))) +var trainInfoHandlers []TrainInfoHandler + +type TrainInfoHandler interface { + HandleTrainInfo(info TrainInfo) +} + +func RegisterTrainInfoHandler(handler TrainInfoHandler) { + trainInfoHandlers = append(trainInfoHandlers, handler) +} + +func RunUdpServer() { + server := &udpServer{addr: fmt.Sprintf("udp://:%d", config.Config.Dynamics.UdpLocalPort), multicore: false} + err := gnet.Run(server, server.addr, gnet.WithMulticore(server.multicore)) + zap.L().Fatal("udp服务启动失败", zap.Error(err)) } diff --git a/xiannccda.setting.yml b/xiannccda.setting.yml index 375e6f2..08e2973 100644 --- a/xiannccda.setting.yml +++ b/xiannccda.setting.yml @@ -6,8 +6,9 @@ server: port: 8080 # 动力学端口配置 dynamics: + ip: 127.0.0.1 udpLocalPort: 4000 - udpRemoteAddr: 127.0.0.1:3000 + udpRemotePort: 3000 # 数据源 datasource: