package dynamics import ( "encoding/binary" "fmt" "github.com/panjf2000/gnet/v2" "go.uber.org/zap" "joylink.club/bj-rtsts-server/config" "net" "time" ) var ( // TurnoutInfoChan 用来存放要发送的道岔信息 TurnoutInfoChan = make(chan *TurnoutInfo, 1000) ) func RunSendTurnoutInfoTask() { go func() { tick := time.Tick(10 * time.Millisecond) for range tick { info := <-TurnoutInfoChan err := SendTurnoutInfo(info) if err != nil { zap.S().Error(err) } } }() } // SendTurnoutInfo 发送道岔信息 func SendTurnoutInfo(info *TurnoutInfo) error { 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 { zap.S().Error("UDP通信失败", err) return err } 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 if info.NPosition { b |= 1 << 7 } if info.RPosition { b |= 1 << 6 } data = append(data, b) _, err = conn.Write(data) return err } type udpServer struct { gnet.BuiltinEventEngine eng gnet.Engine addr string multicore bool eventHandlers []gnet.EventHandler } func (server *udpServer) OnBoot(eng gnet.Engine) gnet.Action { server.eng = eng 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]) trainInfo.Number = buf[2] trainInfo.Len = binary.BigEndian.Uint16(buf[3:5]) trainInfo.Link = buf[5] trainInfo.LinkOffset = binary.BigEndian.Uint32(buf[6:10]) trainInfo.Slope = buf[10] b := buf[11] trainInfo.UpSlope = (b & (1 << 7)) != 0 trainInfo.Up = (b & (1 << 6)) != 0 trainInfo.TotalResistance = binary.BigEndian.Uint16(buf[13:15]) trainInfo.Resistance1 = binary.BigEndian.Uint16(buf[15:17]) trainInfo.Resistance2 = binary.BigEndian.Uint16(buf[17:19]) trainInfo.Resistance3 = binary.BigEndian.Uint16(buf[19:21]) trainInfo.Speed = binary.BigEndian.Uint16(buf[21:23]) trainInfo.HeadSpeed1 = binary.BigEndian.Uint16(buf[23:25]) trainInfo.HeadSpeed2 = binary.BigEndian.Uint16(buf[25:27]) trainInfo.TailSpeed1 = binary.BigEndian.Uint16(buf[27:29]) trainInfo.TailSpeed2 = binary.BigEndian.Uint16(buf[29:31]) trainInfo.HeadRadarSpeed = binary.BigEndian.Uint16(buf[31:33]) trainInfo.TailRadarSpeed = binary.BigEndian.Uint16(buf[33:35]) for _, handler := range trainInfoHandlers { handler.HandleTrainInfo(trainInfo) } return gnet.None } 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)) }