package main import ( "encoding/binary" "fmt" "net" "os" "strconv" "time" ) var ti = &ReceiveTrainInfo{ LifeSignal: 1, Tc1Active: true, Tc2Active: false, DirectionForward: true, TurnbackStatus: true, TractionSafetyCircuit: true, MaintainBrakeStatus: true, BrakeForce: 9040, TrainLoad: 16000, } var trainRun bool // var IP = net.IPv4(192, 168, 3, 7) // var SendIpPort = net.IPv4(192, 168, 3, 7) var IP = net.IPv4(127, 0, 0, 1) var SendIpPort = "127.0.0.1:10000" var tick = 10 * time.Millisecond // 参数1:ip 参数2:间隔 func main() { if len(os.Args) >= 2 && os.Args[1] != "" { SendIpPort = os.Args[1] } if len(os.Args) >= 3 && os.Args[2] != "" { i, err := strconv.Atoi(os.Args[2]) if err != nil { panic(err) } tick = time.Duration(i) * time.Millisecond } fmt.Println("目的IP_Port:", SendIpPort) fmt.Println("间隔:", tick, "毫秒") listen, err := net.ListenUDP("udp", &net.UDPAddr{ IP: IP, Port: 5000, }) if err != nil { fmt.Printf("Listen udp err: %v", err) return } go func() { tick := time.Tick(tick) remoteAddr, err := net.Dial("udp", SendIpPort) if err != nil { fmt.Printf("Dial udp err: %v", err) return } //remoteAddr := &net.UDPAddr{IP: SendIpPort, Port: 10000} // 循环推送信息 for { <-tick ti.LifeSignal = ti.LifeSignal + 1 data := decoderVobcTrainInfo(ti) _, err2 := remoteAddr.Write(data) if err2 != nil { panic(err2) } //_, err := listen.WriteToUDP(data, remoteAddr) if err != nil { fmt.Printf("write failed, err: %v\n", err) } } }() go func() { var model int for { fmt.Println("请输入:") fmt.Scan(&model) switchTrainModel(model, ti) } }() for { var data [1024]byte _, addr, err := listen.ReadFromUDP(data[:]) if err != nil { fmt.Printf("Read failed from addr: %v, err: %v\n", addr, err) break } m := &TrainSpeedMsg{} m.Decode(data[:]) if trainRun { if m.Speed > 800 { changeTractionForce1(ti) } else { changeTractionForce2(ti) } } } } func switchTrainModel(m int, ti *ReceiveTrainInfo) { switch m { case 1: trainRun = true tractionTrain(ti) case 2: trainRun = false stopTrain(ti) case 3: changeHeader(ti) case 0: idleTrain(ti) } } func changeHeader(ti *ReceiveTrainInfo) { ti.Tc1Active = !ti.Tc1Active ti.Tc2Active = !ti.Tc2Active } func stopTrain(ti *ReceiveTrainInfo) { ti.TractionForce = 0 ti.BrakeForce = 19040 } func tractionTrain(ti *ReceiveTrainInfo) { ti.TractionForce = 18000 ti.BrakeForce = 9040 } // 惰行 func idleTrain(ti *ReceiveTrainInfo) { ti.TractionForce = 0 ti.BrakeForce = 0 } func changeTractionForce1(ti *ReceiveTrainInfo) { ti.TractionForce = 9040 } func changeTractionForce2(ti *ReceiveTrainInfo) { ti.TractionForce = 18000 } // 解析VOBC列车信息 func decoderVobcTrainInfo(r *ReceiveTrainInfo) []byte { var data []byte data = binary.BigEndian.AppendUint16(data, r.LifeSignal) data = append(data, boolsToByte([8]bool{ r.Tc1Active, r.Tc2Active, r.DirectionForward, r.DirectionBackward, r.TractionStatus, r.BrakingStatus, r.EmergencyBrakingStatus, r.TurnbackStatus, })) data = append(data, boolsToByte([8]bool{ r.JumpStatus, r.ATO, r.FAM, r.CAM, r.TractionSafetyCircuit, r.ParkingBrakeStatus, r.MaintainBrakeStatus, false, })) data = binary.BigEndian.AppendUint16(data, r.TractionForce) data = binary.BigEndian.AppendUint16(data, r.BrakeForce) data = binary.BigEndian.AppendUint16(data, r.TrainLoad) // 预留 data = binary.BigEndian.AppendUint16(data, 0) data = binary.BigEndian.AppendUint16(data, 0) // 预留 data = append(data, uint8(0)) data = append(data, boolsToByte([8]bool{ r.LeftDoorOpenCommand, r.RightDoorOpenCommand, r.LeftDoorCloseCommand, r.RightDoorCloseCommand, r.AllDoorClose, false, false, false, })) // 预留 data = binary.BigEndian.AppendUint16(data, 0) data = append(data, uint8(0)) data = append(data, uint8(0)) return data } // 解析VOBC列车信息 func decoderVobcTrainState(buf []byte) *TrainVobcState { t := &TrainVobcState{} t.LifeSignal = int32(binary.BigEndian.Uint16(buf[0:2])) b2 := buf[2] t.Tc1Active = (b2 & 1) != 0 t.Tc2Active = (b2 & (1 << 1)) != 0 t.DirectionForward = (b2 & (1 << 2)) != 0 t.DirectionBackward = (b2 & (1 << 3)) != 0 t.TractionStatus = (b2 & (1 << 4)) != 0 t.BrakingStatus = (b2 & (1 << 5)) != 0 t.EmergencyBrakingStatus = (b2 & (1 << 6)) != 0 t.TurnbackStatus = (b2 & 7) != 0 b3 := buf[3] t.JumpStatus = (b3 & 1) != 0 t.Ato = (b3 & (1 << 1)) != 0 t.Fam = (b3 & (1 << 2)) != 0 t.Cam = (b3 & (1 << 3)) != 0 t.TractionSafetyCircuit = (b3 & (1 << 4)) != 0 t.ParkingBrakeStatus = (b3 & (1 << 5)) != 0 t.MaintainBrakeStatus = (b3 & (1 << 6)) != 0 t.TractionForce = int64(binary.BigEndian.Uint16(buf[4:6])) t.BrakeForce = int64(binary.BigEndian.Uint16(buf[6:8])) t.TrainLoad = int64(binary.BigEndian.Uint16(buf[8:10])) b4 := buf[15] t.LeftDoorOpenCommand = (b4 & 1) != 0 t.RightDoorOpenCommand = (b4 & (1 << 1)) != 0 t.LeftDoorCloseCommand = (b4 & (1 << 2)) != 0 t.RightDoorCloseCommand = (b4 & (1 << 3)) != 0 t.AllDoorClose = (b4 & (1 << 4)) != 0 return t } func boolsToByte(flags [8]bool) byte { var result uint8 for index, b := range flags { if b { result = result + (1 << index) } } return result } // 接收到的列车信息 type ReceiveTrainInfo struct { //【0 1】两个字节 // 生命信号 每个周期+1 LifeSignal uint16 //【2】 一个字节 // TC1激活状态 1=激活 Tc1Active bool // TC2激活状态 1=激活 Tc2Active bool // 列车方向向前 1=方向向前 DirectionForward bool // 列车方向向后 1=方向向后 DirectionBackward bool // 列车牵引状态 1=牵引 TractionStatus bool // 列车制动状态 1=制动 BrakingStatus bool // 列车紧急制动状态 1=紧急制动 EmergencyBrakingStatus bool // 列车折返状态(AR) 1=折返 TurnbackStatus bool //【3】 一个字节 // 跳跃状态 1=跳跃 JumpStatus bool // ATO模式 1=ATO模式 ATO bool // FAM模式 1=FAM模式 FAM bool // CAM模式 1=CAM模式 CAM bool // 牵引安全回路 1=牵引安全切除 TractionSafetyCircuit bool // 停放制动状态 1=停放施加 ParkingBrakeStatus bool // 保持制动状态 1=保持制动施加 MaintainBrakeStatus bool //【4 5】 两个字节 列车牵引力 100=1KN TractionForce uint16 //【6 7】 列车制动力 100=1KN BrakeForce uint16 //【8 9】 列车载荷 100=1ton TrainLoad uint16 // 【15】 一个字节 // 列车开左门指令 1=开门 LeftDoorOpenCommand bool // 列车开右门指令 1=开门 RightDoorOpenCommand bool // 列车关左门指令 1=关门 LeftDoorCloseCommand bool // 列车关右门指令 1=关门 RightDoorCloseCommand bool // 整列车门关好 1=门关好 AllDoorClose bool } type TrainVobcState struct { // 生命信号 每个周期+1 LifeSignal int32 `protobuf:"varint,1,opt,name=lifeSignal,proto3" json:"lifeSignal,omitempty"` // TC1激活状态 1=激活 Tc1Active bool `protobuf:"varint,2,opt,name=tc1Active,proto3" json:"tc1Active,omitempty"` // TC2激活状态 1=激活 Tc2Active bool `protobuf:"varint,3,opt,name=tc2Active,proto3" json:"tc2Active,omitempty"` // 列车方向向前 1=方向向前 DirectionForward bool `protobuf:"varint,4,opt,name=directionForward,proto3" json:"directionForward,omitempty"` // 列车方向向后 1=方向向后 DirectionBackward bool `protobuf:"varint,5,opt,name=directionBackward,proto3" json:"directionBackward,omitempty"` // 列车牵引状态 1=牵引 TractionStatus bool `protobuf:"varint,6,opt,name=tractionStatus,proto3" json:"tractionStatus,omitempty"` // 列车制动状态 1=制动 BrakingStatus bool `protobuf:"varint,7,opt,name=brakingStatus,proto3" json:"brakingStatus,omitempty"` // 列车紧急制动状态 1=紧急制动 EmergencyBrakingStatus bool `protobuf:"varint,8,opt,name=emergencyBrakingStatus,proto3" json:"emergencyBrakingStatus,omitempty"` // 列车折返状态(AR) 1=折返 TurnbackStatus bool `protobuf:"varint,9,opt,name=turnbackStatus,proto3" json:"turnbackStatus,omitempty"` // 跳跃状态 1=跳跃 JumpStatus bool `protobuf:"varint,10,opt,name=jumpStatus,proto3" json:"jumpStatus,omitempty"` // ATO模式 1=ATO模式 Ato bool `protobuf:"varint,11,opt,name=ato,proto3" json:"ato,omitempty"` // FAM模式 1=FAM模式 Fam bool `protobuf:"varint,12,opt,name=fam,proto3" json:"fam,omitempty"` // CAM模式 1=CAM模式 Cam bool `protobuf:"varint,13,opt,name=cam,proto3" json:"cam,omitempty"` // 牵引安全回路 1=牵引安全切除 TractionSafetyCircuit bool `protobuf:"varint,14,opt,name=tractionSafetyCircuit,proto3" json:"tractionSafetyCircuit,omitempty"` // 停放制动状态 1=停放施加 ParkingBrakeStatus bool `protobuf:"varint,15,opt,name=parkingBrakeStatus,proto3" json:"parkingBrakeStatus,omitempty"` // 保持制动状态 1=保持制动施加 MaintainBrakeStatus bool `protobuf:"varint,16,opt,name=maintainBrakeStatus,proto3" json:"maintainBrakeStatus,omitempty"` // 列车牵引力 100=1KN TractionForce int64 `protobuf:"varint,17,opt,name=tractionForce,proto3" json:"tractionForce,omitempty"` // 列车制动力 100=1KN BrakeForce int64 `protobuf:"varint,18,opt,name=brakeForce,proto3" json:"brakeForce,omitempty"` // 【列车载荷 100=1ton TrainLoad int64 `protobuf:"varint,19,opt,name=trainLoad,proto3" json:"trainLoad,omitempty"` // 列车开左门指令 1=开门 LeftDoorOpenCommand bool `protobuf:"varint,20,opt,name=leftDoorOpenCommand,proto3" json:"leftDoorOpenCommand,omitempty"` // 列车开右门指令 1=开门 RightDoorOpenCommand bool `protobuf:"varint,21,opt,name=rightDoorOpenCommand,proto3" json:"rightDoorOpenCommand,omitempty"` // 列车关左门指令 1=关门 LeftDoorCloseCommand bool `protobuf:"varint,22,opt,name=leftDoorCloseCommand,proto3" json:"leftDoorCloseCommand,omitempty"` // 列车关右门指令 1=关门 RightDoorCloseCommand bool `protobuf:"varint,23,opt,name=rightDoorCloseCommand,proto3" json:"rightDoorCloseCommand,omitempty"` // 整列车门关好 1=门关好 AllDoorClose bool `protobuf:"varint,24,opt,name=allDoorClose,proto3" json:"allDoorClose,omitempty"` } // 发送列车信息 type TrainSpeedMsg struct { // 生命信号 每个周期+1 LifeSignal uint16 // 列车速度 10=1km/h Speed int16 // 上坡 Upslope bool // 坡度值 1= 1‰ Slope int16 // 加速度 100 = 1 m/s*s Acceleration int8 // 减速度 100 = 1 m/s*s Deceleration int8 // 实际运行阻力 100 = 1KN TotalResistance int32 // 空气阻力 100 = 1KN AirResistance int32 // 坡道阻力 100 = 1KN SlopeResistance int32 // 曲线阻力 100 = 1KN CurveResistance int32 } func (t *TrainSpeedMsg) Decode(buf []byte) { t.LifeSignal = binary.BigEndian.Uint16(buf[0:2]) t.Speed = int16(binary.BigEndian.Uint16(buf[2:4])) t.Upslope = buf[4] == 1 t.Acceleration = int8(buf[6]) t.Deceleration = int8(buf[7]) t.TotalResistance = int32(binary.BigEndian.Uint32(buf[8:12])) t.AirResistance = int32(binary.BigEndian.Uint32(buf[12:16])) t.SlopeResistance = int32(binary.BigEndian.Uint32(buf[16:20])) t.CurveResistance = int32(binary.BigEndian.Uint32(buf[20:24])) t.Slope = int16(binary.BigEndian.Uint16(buf[24:26])) }