diff --git a/rts-sim-module b/rts-sim-module index 6935764..f1feee0 160000 --- a/rts-sim-module +++ b/rts-sim-module @@ -1 +1 @@ -Subproject commit 693576459c8875f7fd82c84df1cd39d4487be65d +Subproject commit f1feee09ccf3d267278789299f09dbd8eb159d8b diff --git a/third_party/interlock/beijing11/msg.go b/third_party/interlock/beijing11/msg.go index bf8b9e8..b0f97d3 100644 --- a/third_party/interlock/beijing11/msg.go +++ b/third_party/interlock/beijing11/msg.go @@ -2,6 +2,7 @@ package beijing11 import ( "encoding/binary" + "github.com/snksoft/crc" ) const ( //不知道对不对,问也不回,先瞎写吧 @@ -10,11 +11,12 @@ const ( //不知道对不对,问也不回,先瞎写吧 ) const ( - SignalAspect_No = 0x01 //灭灯 - SignalAspect_H = 0x02 //红灯 - SignalAspect_L = 0x03 //绿灯 - SignalAspect_U = 0x04 //黄灯 - SignalAspect_HU = 0x05 //红黄 + SignalAspect_No = 0x99 //灭灯,这个值目前未知,先用一个应该没被使用的值占位 + SignalAspect_H = 0x01 //红灯 + SignalAspect_L = 0x04 //绿灯 + SignalAspect_U = 0x02 //黄灯 + SignalAspect_HU = 0x03 //红黄 + SignalAspect_B = 0x08 //白灯 ) func GetStateByte(state bool) byte { @@ -265,10 +267,12 @@ func (t *ToInterlockFrame) encode() []byte { for _, state := range t.SPKSStates { data = state.encode(data) } - ////车库门,数量0 - //data = binary.BigEndian.AppendUint16(data, 0) - //CRC32,不校验,随便填 - data = append(data, 0xff, 0xff, 0xff, 0xff) + //填充字节 + fillSlice := make([]byte, 19) + fillSlice[2] = 1 + data = append(data, fillSlice...) + //CRC32 + data = binary.BigEndian.AppendUint32(data, crc32(data[3:])) //填充报文长度 binary.BigEndian.PutUint16(data[1:3], uint16(len(data)-7)) return data @@ -387,3 +391,9 @@ type XcjState struct { BackConfirm byte //返回确认状态 BackMode byte //模式 } + +var crcHash = crc.NewHash(&crc.Parameters{Width: 32, Polynomial: 0x4c11db7, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0}) + +func crc32(data []byte) uint32 { + return uint32(crcHash.CalculateCRC(data)) +} diff --git a/third_party/interlock/beijing11/msg_test.go b/third_party/interlock/beijing11/msg_test.go index 04de094..8152080 100644 --- a/third_party/interlock/beijing11/msg_test.go +++ b/third_party/interlock/beijing11/msg_test.go @@ -3,41 +3,25 @@ package beijing11 import ( "encoding/binary" "encoding/hex" - "encoding/json" "fmt" "joylink.club/bj-rtsts-server/util/myreader" "testing" ) func TestFromInterlockFrame_Decode(t *testing.T) { - str := "82009a3c0163010006000100000200000300000600000700000800000200010000050000020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000480000580000680000780000800000900000a00001d00001e00001f000020000021000022000023000024000025000000000000040001aaaa0002aaaa0003aaaa0004aaaa00000000000000000000000040ace569" + str := "58bea4c65e0e583f5bdedc310800450000bd030c0000801100003d0b0a0d3d0b7814413c40d800a9fcf182009a3c016301000600010000020000030000060000070000080000020001000005aa00020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000400000500000600000700000800000900000a00001d00001e00001f000020000021000022000023000024000025000000000000040001aaaa0002aaaa0003aaaa0004aaaa0000000000000000000000004c428d88" data, err := hex.DecodeString(str) if err != nil { t.Fatal(err) } - frame := &FromInterlockFrame{} - err = frame.Decode(data) - if err != nil { - t.Fatal(err) - } - marshal, err := json.Marshal(frame) - if err != nil { - t.Fatal(err) - } - fmt.Println(string(marshal)) -} - -func TestToInterlockFrame_Decode(t *testing.T) { - str := "83009663013c0100060001010002010003010006010007010008010002000155ffaaaaaa000555ffaaaaaa00020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000440000540000640000740000840000940000a40001d40001e40001f40002040002140002240002340002440002540000000000004000155aa000255aa000355aa000455aaffffffff" - data, err := hex.DecodeString(str) - if err != nil { - t.Fatal(err) + if data[0] != 0x82 { + data = data[42:] //去掉wireshark抓包携带的额外字节 } reader := myreader.NewReader(data) - fmt.Printf("%x【报文类型】\t\n", reader.ReadByte()) - fmt.Printf("%x【报文长度】\t\n", reader.ReadBytes(2)) - fmt.Printf("%x【轨旁编号】\t\n", reader.ReadBytes(2)) - fmt.Printf("%x【联锁编号】\t\n", reader.ReadBytes(2)) + fmt.Printf("%x\t【报文类型】\n", reader.ReadByte()) + fmt.Printf("%x\t【报文长度】\n", reader.ReadBytes(2)) + fmt.Printf("%x\t【联锁编号】\n", reader.ReadBytes(2)) + fmt.Printf("%x\t【轨旁编号】\n", reader.ReadBytes(2)) { //道岔 deviceNum := reader.ReadBytes(2) fmt.Printf("%x\t", deviceNum) @@ -50,7 +34,110 @@ func TestToInterlockFrame_Decode(t *testing.T) { deviceNum := reader.ReadBytes(2) fmt.Printf("%x\t", deviceNum) for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { - fmt.Printf("%x ", reader.ReadBytes(8)) + fmt.Printf("%x ", reader.ReadBytes(3)) + } + fmt.Println("【屏蔽门】") + } + { //紧急停车按钮 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { + fmt.Printf("%x ", reader.ReadBytes(4)) + } + fmt.Println("【紧急停车按钮】") + } + { //扣车按钮 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + fmt.Println("【扣车按钮】") + } + { //信号机 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { + fmt.Printf("%x ", reader.ReadBytes(3)) + } + fmt.Println("【信号机】") + } + { //计轴区段 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { + fmt.Printf("%x ", reader.ReadBytes(3)) + } + fmt.Println("【计轴区段】") + } + { //无人折返 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + fmt.Println("【无人折返】") + } + { //防淹门 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + fmt.Println("【防淹门】") + } + { //SPKS + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { + fmt.Printf("%x ", reader.ReadBytes(4)) + } + fmt.Println("【SPKS】") + } + { //车库门 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + fmt.Println("【车库门】") + } + { //预留 + deviceNum := reader.ReadBytes(10) + fmt.Printf("%x\t", deviceNum) + fmt.Println("【预留】") + } + //CRC32 + fmt.Printf("%x【CRC32】\n", reader.ReadBytes(4)) + //{ //json + // frame := &FromInterlockFrame{} + // err = frame.Decode(data) + // if err != nil { + // t.Fatal(err) + // } + // marshal, err := json.Marshal(frame) + // if err != nil { + // t.Fatal(err) + // } + // fmt.Println(string(marshal)) + //} +} + +func TestToInterlockFrame_Decode(t *testing.T) { + str := "583f5bdedc3158bea4c65e0e0800450000f6dfe9400040115dd63d0b78143d0b0a0dd341413c00e2e8c88300d363013c0100060001010002010003010006010007010008010002000102eeaaaaaa000502eeaaaaaa00020001aa000005aa0000000011000101000201000301000401000501000601000701001501001601001701001801001901001a01001b01002901002a01002c010015000100000200000300000400000500000600000700000800000900000a00001b00001c00001d00001e00001f000020000021000022000023000024000025000000000000040001aaff0002aaff0003aaff0004aaff00000100000000000000000000000000000000f38414ee" + data, err := hex.DecodeString(str) + if err != nil { + t.Fatal(err) + } + if data[0] != 0x83 { + data = data[42:] //去掉wireshark抓包携带的额外字节 + } + reader := myreader.NewReader(data) + fmt.Printf("%x\t【报文类型】\n", reader.ReadByte()) + fmt.Printf("%x\t【报文长度】\n", reader.ReadBytes(2)) + fmt.Printf("%x\t【轨旁编号】\n", reader.ReadBytes(2)) + fmt.Printf("%x\t【联锁编号】\n", reader.ReadBytes(2)) + { //道岔 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { + fmt.Printf("%x ", reader.ReadBytes(3)) + } + fmt.Println("【道岔】") + } + { //屏蔽门 + deviceNum := reader.ReadBytes(2) + fmt.Printf("%x\t", deviceNum) + for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ { + fmt.Printf("%x ", reader.ReadBytes(7)) } fmt.Println("【屏蔽门】") } @@ -102,5 +189,5 @@ func TestToInterlockFrame_Decode(t *testing.T) { fmt.Println("【SPKS】") } //CRC32 - fmt.Printf("%x【CRC32】", reader.ReadBytes(4)) + fmt.Printf("%x【CRC32】\n", reader.ReadBytes(reader.Len())) } diff --git a/third_party/interlock/beijing11/service.go b/third_party/interlock/beijing11/service.go index 0429aea..059aad5 100644 --- a/third_party/interlock/beijing11/service.go +++ b/third_party/interlock/beijing11/service.go @@ -10,8 +10,10 @@ import ( "joylink.club/bj-rtsts-server/ts/simulation/wayside/memory" "joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/entity" + "joylink.club/rtsssimulation/fi" "log/slog" "math" + "net" "runtime/debug" "sort" "sync" @@ -31,13 +33,12 @@ var ( ) type serviceContext struct { - cancelFunc context.CancelFunc //用来结束各个协程的函数 - client udp.UdpClient //向联锁发送数据的客户端 - server udp.UdpServer //接收联锁数据的服务端 - sim *memory.VerifySimulation //启动服务所使用的仿真 - iConfig config.InterlockConfig //启动服务使用的联锁配置 - deviceTable *StationDeviceIndexTable //联锁站的设备ID表,key-车站名 - driveMsgSlice []*FromInterlockFrame //驱动消息切片 + cancelFunc context.CancelFunc //用来结束各个协程的函数 + ioAddr *net.UDPAddr //向联锁发送数据的客户端 + server udp.UdpServer //接收联锁数据的服务端(同时也是向联锁发送数据的udp客户端) + sim *memory.VerifySimulation //启动服务所使用的仿真 + iConfig config.InterlockConfig //启动服务使用的联锁配置 + deviceTable *StationDeviceIndexTable //联锁站的设备ID表,key-车站名 } func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) { @@ -55,13 +56,16 @@ func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimu if serviceCtx != nil { panic(fmt.Sprintf("%s重复启动联锁站[%s]通信服务", logTag, interlockConfig.Code)) } - //UDP客户端 - client := udp.NewClient(fmt.Sprintf("%s:%d", interlockConfig.Ip, interlockConfig.RemotePort)) + //仿真IO地址 + ioAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", interlockConfig.Ip, interlockConfig.RemotePort)) + if err != nil { + panic(fmt.Sprintf("%s解析IP地址出错:%s", logTag, err)) + } ctx, cancelFunc := context.WithCancel(context.Background()) serviceCtx = &serviceContext{ cancelFunc: cancelFunc, - client: client, + ioAddr: ioAddr, sim: simulation, iConfig: interlockConfig, deviceTable: table, @@ -69,7 +73,7 @@ func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimu //UDP服务端 server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg) serviceCtx.server = server - err := server.Listen() + err = server.Listen() if err != nil { panic(fmt.Sprintf("%s启动UDP服务失败:%s", logTag, err)) } @@ -86,201 +90,220 @@ func (s *serviceContext) handleDriveMsg(data []byte) { logger().Error("解析数据出错", "error", err) return } - if len(s.driveMsgSlice) < 2 { - if frame.InterlockCode == 0x3c01 || frame.InterlockCode == 0x3c02 { - s.driveMsgSlice = append(s.driveMsgSlice, frame) + + wd := entity.GetWorldData(s.sim.World) + for _, cmd := range frame.TurnoutData.CmdList { + uid := s.deviceTable.TurnoutMap[cmd.Id].uid + if cmd.Cmd == 0x55 { + err = fi.DriveTurnoutDCOn(s.sim.World, uid) + } else if cmd.Cmd == 0xaa { + err = fi.DriveTurnoutFCOn(s.sim.World, uid) + } else { + err = fi.DriveTurnoutDCOff(s.sim.World, uid) + } + if err != nil { + logger().Error("驱动道岔出错", "error", err) + } + } + for _, cmd := range frame.PSDData.CmdList { + row := s.deviceTable.PsdMap[cmd.Id] + entry := wd.EntityMap[row.uid] + circuit := component.PsdCircuitType.Get(entry) + logger().Info(fmt.Sprintf("屏蔽门命令:%x", cmd.Cmd)) + switch cmd.Cmd { + case 0xAA: //短编组开门 + wd.SetQdBit(row.relateDeviceMap[S], true) + wd.SetQdBit(row.relateDeviceMap[L], false) + wd.SetQdBit(component.UidType.Get(circuit.GMJ).Id, false) + case 0xBB: //长编组开门 + wd.SetQdBit(row.relateDeviceMap[S], false) + wd.SetQdBit(row.relateDeviceMap[L], true) + wd.SetQdBit(component.UidType.Get(circuit.GMJ).Id, false) + case 0x55: //关门 + wd.SetQdBit(row.relateDeviceMap[S], false) + wd.SetQdBit(row.relateDeviceMap[L], false) + wd.SetQdBit(component.UidType.Get(circuit.GMJ).Id, true) + } + } + for _, cmd := range frame.ESBData.CmdList { + uid := s.deviceTable.EsbMap[cmd.Id].uid + esb := s.sim.Repo.FindEsb(uid) + if cmd.JjtcplCmd == 0x55 { + err = fi.PressDownButton(s.sim.World, esb.PlaId()) + if err != nil { + logger().Error("驱动ESB出错", "error", err) + } + continue + } else { + err = fi.PressUpButton(s.sim.World, esb.PlaId()) + if err != nil { + logger().Error("驱动ESB出错", "error", err) + } + } + if cmd.JjtcCmd == 0x55 { + err := fi.DriveRelayDown(s.sim.World, esb.RelayId()) + if err != nil { + logger().Error("驱动ESB出错", "error", err) + } + } else { + err := fi.DriveRelayUp(s.sim.World, esb.RelayId()) + if err != nil { + logger().Error("驱动ESB出错", "error", err) + } + } + } + for _, cmd := range frame.SignalData.CmdList { + uid := s.deviceTable.SignalMap[cmd.Id].uid + entry := wd.EntityMap[uid] + if entry.HasComponent(component.Signal2XH1ElectronicType) { // 2XH1信号机 + signal2XH1 := component.Signal2XH1ElectronicType.Get(entry) + switch cmd.Cmd { + case SignalAspect_No: + wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_DDJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_LXJ).Id, false) + case SignalAspect_H: + wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_LXJ).Id, false) + case SignalAspect_L: + wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_LXJ).Id, true) + default: + logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) + } + } else if entry.HasComponent(component.Signal3XH1ElectronicType) { // 3XH1信号机 + signal3XH1 := component.Signal3XH1ElectronicType.Get(entry) + switch cmd.Cmd { + case SignalAspect_No: + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false) + case SignalAspect_H: + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false) + case SignalAspect_L: + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false) + case SignalAspect_U: + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false) + case SignalAspect_HU: + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, true) + default: + logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) + } + } else if entry.HasComponent(component.Signal3XH2ElectronicType) { // 3XH2信号机 + signal3XH2 := component.Signal3XH2ElectronicType.Get(entry) + switch cmd.Cmd { + case SignalAspect_No: + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, false) + case SignalAspect_H: + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, false) + case SignalAspect_L: + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, false) + case SignalAspect_HU: + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, true) + default: + logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) + } + } else if entry.HasComponent(component.Signal3XH3ElectronicType) { // 3XH3信号机 + signal3XH3 := component.Signal3XH3ElectronicType.Get(entry) + switch cmd.Cmd { + case SignalAspect_No: + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, false) + case SignalAspect_H: + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, false) + case SignalAspect_U: + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, false) + case SignalAspect_HU: + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, true) + default: + logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) + } + } else if entry.HasComponent(component.Signal3XH4ElectronicType) { // 3XH4信号机 + signal3XH4 := component.Signal3XH4ElectronicType.Get(entry) + switch cmd.Cmd { + case SignalAspect_No: + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, false) + case SignalAspect_H: + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, false) + case SignalAspect_L: + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, true) + case SignalAspect_U: + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, false) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, true) + wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, false) + default: + logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) + } + } else { + logger().Error(fmt.Sprintf("信号机[%s]的型号未知", uid)) + } + } + for _, cmd := range frame.AxleSectionData.CmdList { + if cmd.Cmd == 0x80 { + uid := s.deviceTable.AxleSectionMap[cmd.Id].uid + physicalSectionUid := s.sim.Repo.FindAxleCountingSection(uid).PhysicalSection().Id() + _, err := fi.PhysicalSectionDrstDrive(s.sim.World, physicalSectionUid) + if err != nil { + logger().Error(fmt.Sprintf("计轴区段[%s]复位出错:%s", uid, err)) + } + } + } + for _, cmd := range frame.SPKSData.CmdList { + uid := s.deviceTable.SpksMap[cmd.Id].uid + spks := s.sim.Repo.FindSpks(uid) + if cmd.SPKSPLCmd == 0x55 { + err = fi.PressDownButton(s.sim.World, spks.PlaId()) + } else { + err = fi.PressUpButton(s.sim.World, spks.PlaId()) + } + if cmd.SPKSCmd == 0x55 { + err = fi.DriveRelayDown(s.sim.World, spks.Relay()) + } else { + err = fi.DriveRelayUp(s.sim.World, spks.Relay()) } } - - //wd := entity.GetWorldData(s.sim.World) - ////for _, cmd := range frame.TurnoutData.CmdList { - //// uid := s.deviceTable.TurnoutMap[cmd.Id].uid - ////} - //for _, cmd := range frame.PSDData.CmdList { - // row := s.deviceTable.PsdMap[cmd.Id] - // entry := wd.EntityMap[row.uid] - // circuit := component.PsdCircuitType.Get(entry) - // switch cmd.Cmd { - // case 0xAA: //短编组开门 - // component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[S]]).Td = true - // component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[L]]).Td = false - // component.RelayDriveType.Get(circuit.GMJ).Td = false - // case 0xBB: //长编组开门 - // component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[S]]).Td = false - // component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[L]]).Td = true - // component.RelayDriveType.Get(circuit.GMJ).Td = false - // case 0x55: - // component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[S]]).Td = false - // component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[L]]).Td = false - // component.RelayDriveType.Get(circuit.GMJ).Td = true - // } - //} - //for _, cmd := range frame.ESBData.CmdList { - // uid := s.deviceTable.EsbMap[cmd.Id].uid - // esb := s.sim.Repo.FindEsb(uid) - // if cmd.JjtcplCmd == ON { - // err := fi.DriveRelayUp(s.sim.World, esb.RelayId()) - // if err != nil { - // logger().Error("驱动ESB出错", "error", err) - // } - // continue - // } - // if cmd.JjtcCmd == ON { - // err := fi.DriveRelayDown(s.sim.World, esb.RelayId()) - // if err != nil { - // logger().Error("驱动ESB出错", "error", err) - // } - // } else { - // err := fi.DriveRelayUp(s.sim.World, esb.RelayId()) - // if err != nil { - // logger().Error("驱动ESB出错", "error", err) - // } - // } - //} - //for _, cmd := range frame.SignalData.CmdList { - // uid := s.deviceTable.SignalMap[cmd.Id].uid - // entry := wd.EntityMap[uid] - // if entry.HasComponent(component.Signal2XH1ElectronicType) { // 2XH1信号机 - // signal2XH1 := component.Signal2XH1ElectronicType.Get(entry) - // switch cmd.Cmd { - // case SignalAspect_No: - // component.RelayDriveType.Get(signal2XH1.Z2XH1_DDJ).Td = true - // component.RelayDriveType.Get(signal2XH1.Z2XH1_LXJ).Td = false - // case SignalAspect_H: - // component.RelayDriveType.Get(signal2XH1.Z2XH1_DDJ).Td = false - // component.RelayDriveType.Get(signal2XH1.Z2XH1_LXJ).Td = false - // case SignalAspect_L: - // component.RelayDriveType.Get(signal2XH1.Z2XH1_DDJ).Td = false - // component.RelayDriveType.Get(signal2XH1.Z2XH1_LXJ).Td = true - // default: - // logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) - // } - // } else if entry.HasComponent(component.Signal3XH1ElectronicType) { // 3XH1信号机 - // signal3XH1 := component.Signal3XH1ElectronicType.Get(entry) - // switch cmd.Cmd { - // case SignalAspect_No: - // component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = true - // component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false - // case SignalAspect_H: - // component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false - // case SignalAspect_L: - // component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = true - // component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = true - // component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false - // case SignalAspect_U: - // component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = true - // component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false - // case SignalAspect_HU: - // component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false - // component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = true - // default: - // logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) - // } - // } else if entry.HasComponent(component.Signal3XH2ElectronicType) { // 3XH2信号机 - // signal3XH2 := component.Signal3XH2ElectronicType.Get(entry) - // switch cmd.Cmd { - // case SignalAspect_No: - // component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = true - // component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = false - // case SignalAspect_H: - // component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = false - // case SignalAspect_L: - // component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = true - // component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = false - // case SignalAspect_HU: - // component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = true - // default: - // logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) - // } - // } else if entry.HasComponent(component.Signal3XH3ElectronicType) { // 3XH3信号机 - // signal3XH3 := component.Signal3XH3ElectronicType.Get(entry) - // switch cmd.Cmd { - // case SignalAspect_No: - // component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = true - // component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = false - // case SignalAspect_H: - // component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = false - // case SignalAspect_U: - // component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = true - // component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = false - // case SignalAspect_HU: - // component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = true - // default: - // logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) - // } - // } else if entry.HasComponent(component.Signal3XH4ElectronicType) { // 3XH4信号机 - // signal3XH4 := component.Signal3XH4ElectronicType.Get(entry) - // switch cmd.Cmd { - // case SignalAspect_No: - // component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = true - // component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = false - // case SignalAspect_H: - // component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = false - // component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = false - // case SignalAspect_L: - // component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = true - // component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = true - // case SignalAspect_U: - // component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = false - // component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = true - // component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = false - // default: - // logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd)) - // } - // } else { - // logger().Error(fmt.Sprintf("信号机[%s]的型号未知", uid)) - // } - //} - //for _, cmd := range frame.AxleSectionData.CmdList { - // if cmd.Cmd == 0x80 { - // uid := s.deviceTable.AxleSectionMap[cmd.Id].uid - // physicalSectionUid := s.sim.Repo.FindAxleCountingSection(uid).PhysicalSection().Id() - // _, err := fi.PhysicalSectionDrstDrive(s.sim.World, physicalSectionUid) - // if err != nil { - // logger().Error(fmt.Sprintf("计轴区段[%s]复位出错:%s", uid, err)) - // } - // } - //} - ////for _, cmd := range frame.SPKSData.CmdList { - //// uid := s.deviceTable.SpksMap[cmd.Id].uid - ////} } func Stop(stationCode string) { mu.Lock() defer mu.Unlock() - context := serviceContextMap[stationCode] - if context != nil { - if context.client != nil { - context.client.Close() - } - if context.server != nil { - context.server.Close() + serviceContext := serviceContextMap[stationCode] + if serviceContext != nil { + if serviceContext.server != nil { + serviceContext.server.Close() } delete(serviceContextMap, stationCode) } @@ -459,47 +482,39 @@ func (s *serviceContext) runCollectTask(ctx context.Context) { case <-ctx.Done(): return default: - for _, driveMsg := range s.driveMsgSlice { - frame := s.collectDeviceState(driveMsg) - data := frame.encode() - err := s.client.Send(data) - if err != nil { - logger().Error("向联锁发送数据失败", "error", err) - } else { - logger().Info(fmt.Sprintf("向联锁发送数据:%x", data)) - } + frame := s.collectDeviceState() + data := frame.encode() + _, err := s.server.WriteToUdp(data, s.ioAddr) + if err != nil { + logger().Error("向联锁发送数据失败", "error", err) + } else { + logger().Info(fmt.Sprintf("向联锁发送数据:%x", data)) } - - //frame := s.collectDeviceState() - //data := frame.encode() - //err := s.client.Send(data) - //if err != nil { - // logger().Error("向联锁发送数据失败", "error", err) - //} else { - // logger().Info(fmt.Sprintf("向联锁发送数据:%x", data)) - //} } } }() } -func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterlockFrame { +func (s *serviceContext) collectDeviceState() *ToInterlockFrame { wd := entity.GetWorldData(s.sim.World) frame := &ToInterlockFrame{} frame.WaysideCode = waysideCode - frame.InterlockCode = msg.InterlockCode + frame.InterlockCode = s.deviceTable.InterlockCode //道岔 - for _, cmd := range msg.TurnoutData.CmdList { - row := s.deviceTable.TurnoutMap[cmd.Id] + for _, row := range s.deviceTable.TurnoutMap { entry := wd.EntityMap[row.uid] tp := component.TurnoutPositionType.Get(entry) var stateByte byte - if tp.Dw { - stateByte = 0x01 - } else if tp.Fw { - stateByte = 0x02 + if entry.HasComponent(component.TurnoutFaultCiqdType) { + stateByte = 0xff } else { - stateByte = 0x08 + if tp.Dw { + stateByte = 0x01 + } else if tp.Fw { + stateByte = 0x02 + } else { + stateByte = 0x08 + } } frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{ Id: row.index, @@ -510,8 +525,7 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id }) //屏蔽门 - for _, cmd := range msg.PSDData.CmdList { - row := s.deviceTable.PsdMap[cmd.Id] + for _, row := range s.deviceTable.PsdMap { entry := wd.EntityMap[row.uid] psdState := component.PsdStateType.Get(entry) mkxBytes := make([]byte, 0, 3) @@ -521,10 +535,22 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc } mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val)) } + var state byte + if psdState.Close { + state = 0x02 + } else { + state = 0x01 + } + var hsjc byte + if psdState.InterlockRelease { + hsjc = 0xff + } else { + hsjc = 0xee + } frame.PsdStates = append(frame.PsdStates, &PSDState{ Id: row.index, - State: GetStateByte(psdState.Close), - Hsjc: 0xff, + State: state, + Hsjc: hsjc, PCB: mkxBytes[0], POB: mkxBytes[1], DPB: mkxBytes[2], @@ -534,8 +560,7 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc return frame.PsdStates[i].Id < frame.PsdStates[j].Id }) //紧急停车 - for _, cmd := range msg.ESBData.CmdList { - row := s.deviceTable.EsbMap[cmd.Id] + for _, row := range s.deviceTable.EsbMap { esb := s.sim.Repo.FindEsb(row.uid) relay := wd.EntityMap[esb.RelayId()] pla := wd.EntityMap[esb.PlaId()] @@ -543,14 +568,14 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc Id: row.index, State: GetStateByte(!component.BitStateType.Get(relay).Val), PlState: GetStateByte(component.BitStateType.Get(pla).Val), + //PlState: 0x00, }) } sort.Slice(frame.ESBStates, func(i, j int) bool { return frame.ESBStates[i].Id < frame.ESBStates[j].Id }) //信号机 - for _, cmd := range msg.SignalData.CmdList { - row := s.deviceTable.SignalMap[cmd.Id] + for _, row := range s.deviceTable.SignalMap { entry := wd.EntityMap[row.uid] lights := component.SignalLightsType.Get(entry) isL := false @@ -598,11 +623,10 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc return frame.SignalStates[i].Id < frame.SignalStates[j].Id }) //计轴区段 - for _, cmd := range msg.AxleSectionData.CmdList { - row := s.deviceTable.AxleSectionMap[cmd.Id] + for _, row := range s.deviceTable.AxleSectionMap { entry := wd.EntityMap[row.uid] sectionState := component.AxleCountingSectionStateType.Get(entry) - var stateByte byte = 0x40 + var stateByte byte = 0x00 if sectionState.Occupied { stateByte = 0x40 } @@ -615,15 +639,15 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id }) //SPKS - for _, cmd := range msg.SPKSData.CmdList { - row := s.deviceTable.SpksMap[cmd.Id] + for _, row := range s.deviceTable.SpksMap { spks := s.sim.Repo.FindSpks(row.uid) relay := wd.EntityMap[spks.Relay()] pla := wd.EntityMap[spks.PlaId()] frame.SPKSStates = append(frame.SPKSStates, &SPKSState{ Id: row.index, - State: GetStateByte(component.BitStateType.Get(relay).Val), + State: GetStateByte(!component.BitStateType.Get(relay).Val), PlState: GetStateByte(component.BitStateType.Get(pla).Val), + //PlState: 0xff, }) } sort.Slice(frame.SPKSStates, func(i, j int) bool { @@ -632,149 +656,6 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc return frame } -//func (s *serviceContext) collectDeviceState() *ToInterlockFrame { -// wd := entity.GetWorldData(s.sim.World) -// frame := &ToInterlockFrame{} -// frame.WaysideCode = waysideCode -// frame.InterlockCode = s.deviceTable.InterlockCode -// //道岔 -// for _, row := range s.deviceTable.TurnoutMap { -// entry := wd.EntityMap[row.uid] -// tp := component.TurnoutPositionType.Get(entry) -// var stateByte byte -// if tp.Dw { -// stateByte = 0x01 -// } else if tp.Fw { -// stateByte = 0x02 -// } else { -// stateByte = 0x08 -// } -// frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{ -// Id: row.index, -// State: stateByte, -// }) -// } -// sort.Slice(frame.TurnoutStates, func(i, j int) bool { -// return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id -// }) -// //屏蔽门 -// for _, row := range s.deviceTable.PsdMap { -// entry := wd.EntityMap[row.uid] -// psdState := component.PsdStateType.Get(entry) -// mkxBytes := make([]byte, 0, 3) -// for _, mkxRelayUid := range []string{row.relateDeviceMap[POB], row.relateDeviceMap[PCB], row.relateDeviceMap[DPB]} { -// if mkxRelayUid == "" { -// continue -// } -// mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val)) -// } -// frame.PsdStates = append(frame.PsdStates, &PSDState{ -// Id: row.index, -// State: GetStateByte(psdState.Close), -// Hsjc: 0xff, -// PCB: mkxBytes[0], -// POB: mkxBytes[1], -// DPB: mkxBytes[2], -// }) -// } -// sort.Slice(frame.PsdStates, func(i, j int) bool { -// return frame.PsdStates[i].Id < frame.PsdStates[j].Id -// }) -// //紧急停车 -// for _, row := range s.deviceTable.EsbMap { -// esb := s.sim.Repo.FindEsb(row.uid) -// relay := wd.EntityMap[esb.RelayId()] -// pla := wd.EntityMap[esb.PlaId()] -// frame.ESBStates = append(frame.ESBStates, &ESBState{ -// Id: row.index, -// State: GetStateByte(!component.BitStateType.Get(relay).Val), -// PlState: GetStateByte(component.BitStateType.Get(pla).Val), -// }) -// } -// sort.Slice(frame.ESBStates, func(i, j int) bool { -// return frame.ESBStates[i].Id < frame.ESBStates[j].Id -// }) -// //信号机 -// for _, row := range s.deviceTable.SignalMap { -// entry := wd.EntityMap[row.uid] -// lights := component.SignalLightsType.Get(entry) -// isL := false -// isH := false -// isU := false -// isA := false -// isB := false -// for _, light := range lights.Lights { -// switch { -// case light.HasComponent(component.LdTag): -// isL = component.BitStateType.Get(light).Val -// case light.HasComponent(component.HdTag): -// isH = component.BitStateType.Get(light).Val -// case light.HasComponent(component.UdTag): -// isU = component.BitStateType.Get(light).Val -// case light.HasComponent(component.BdTag): -// isB = component.BitStateType.Get(light).Val -// case light.HasComponent(component.AdTag): -// isA = component.BitStateType.Get(light).Val -// } -// } -// var stateByte byte -// if isH && isU { -// stateByte = 0x03 -// } else { -// switch { -// case isL: -// stateByte = 0x04 -// case isH: -// stateByte = 0x01 -// case isU: -// stateByte = 0x02 -// case isB: -// stateByte = 0x08 -// case isA: -// stateByte = 0x09 -// } -// } -// frame.SignalStates = append(frame.SignalStates, &SignalState{ -// Id: row.index, -// State: stateByte, -// }) -// } -// sort.Slice(frame.SignalStates, func(i, j int) bool { -// return frame.SignalStates[i].Id < frame.SignalStates[j].Id -// }) -// //计轴区段 -// for _, row := range s.deviceTable.AxleSectionMap { -// entry := wd.EntityMap[row.uid] -// sectionState := component.AxleCountingSectionStateType.Get(entry) -// var stateByte byte = 0x40 -// if sectionState.Occupied { -// stateByte = 0x40 -// } -// frame.AxleSectionStates = append(frame.AxleSectionStates, &AxleSectionState{ -// Id: row.index, -// State: stateByte, -// }) -// } -// sort.Slice(frame.AxleSectionStates, func(i, j int) bool { -// return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id -// }) -// //SPKS -// for _, row := range s.deviceTable.SpksMap { -// spks := s.sim.Repo.FindSpks(row.uid) -// relay := wd.EntityMap[spks.Relay()] -// pla := wd.EntityMap[spks.PlaId()] -// frame.SPKSStates = append(frame.SPKSStates, &SPKSState{ -// Id: row.index, -// State: GetStateByte(component.BitStateType.Get(relay).Val), -// PlState: GetStateByte(component.BitStateType.Get(pla).Val), -// }) -// } -// sort.Slice(frame.SPKSStates, func(i, j int) bool { -// return frame.SPKSStates[i].Id < frame.SPKSStates[j].Id -// }) -// return frame -//} - func logger() *slog.Logger { loggerInit.Do(func() { privateLogger = slog.Default().With("tag", logTag) diff --git a/third_party/udp/udp_server.go b/third_party/udp/udp_server.go index b2f19b8..75df4bd 100644 --- a/third_party/udp/udp_server.go +++ b/third_party/udp/udp_server.go @@ -10,6 +10,7 @@ import ( type UdpServer interface { Listen() error Close() + WriteToUdp(data []byte, addr *net.UDPAddr) (int, error) } type UdpMsgHandler func(b []byte) @@ -53,6 +54,10 @@ func (s *server) Close() { <-s.done } +func (s *server) WriteToUdp(data []byte, addr *net.UDPAddr) (int, error) { + return s.conn.WriteToUDP(data, addr) +} + func (s *server) listenAndHandle(ctx context.Context) { defer close(s.done) defer s.conn.Close() diff --git a/util/myreader/reader.go b/util/myreader/reader.go index e857938..765e650 100644 --- a/util/myreader/reader.go +++ b/util/myreader/reader.go @@ -36,3 +36,7 @@ func (r *Reader) ReadBytes(n int) []byte { r.Read(b) return b } + +func (r *Reader) Len() int { + return r.r.Len() +}