Compare commits

...

2 Commits

Author SHA1 Message Date
tiger_zhou
efe1ff69c9 Merge branch 'develop' of http://120.46.212.6:3000/joylink/rts-sim-testing-service into develop_t
# Conflicts:
#	rts-sim-module
2024-09-10 15:38:31 +08:00
3d66efe8f4 [修改]11号线模式口采集和驱动逻辑调通 2024-09-05 15:14:39 +08:00
5 changed files with 404 additions and 417 deletions

View File

@ -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))
}

View File

@ -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()))
}

View File

@ -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"
@ -32,12 +34,11 @@ var (
type serviceContext struct {
cancelFunc context.CancelFunc //用来结束各个协程的函数
client udp.UdpClient //向联锁发送数据的客户端
server udp.UdpServer //接收联锁数据的服务端
ioAddr *net.UDPAddr //向联锁发送数据的客户端
server udp.UdpServer //接收联锁数据的服务端同时也是向联锁发送数据的udp客户端
sim *memory.VerifySimulation //启动服务所使用的仿真
iConfig config.InterlockConfig //启动服务使用的联锁配置
deviceTable *StationDeviceIndexTable //联锁站的设备ID表key-车站名
driveMsgSlice []*FromInterlockFrame //驱动消息切片
}
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
////}
//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
////}
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())
}
}
}
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,41 +482,32 @@ func (s *serviceContext) runCollectTask(ctx context.Context) {
case <-ctx.Done():
return
default:
for _, driveMsg := range s.driveMsgSlice {
frame := s.collectDeviceState(driveMsg)
frame := s.collectDeviceState()
data := frame.encode()
err := s.client.Send(data)
_, 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 entry.HasComponent(component.TurnoutFaultCiqdType) {
stateByte = 0xff
} else {
if tp.Dw {
stateByte = 0x01
} else if tp.Fw {
@ -501,6 +515,7 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
} else {
stateByte = 0x08
}
}
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{
Id: row.index,
State: stateByte,
@ -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)

View File

@ -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()

View File

@ -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()
}