2024-01-17 17:49:11 +08:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net"
|
|
|
|
|
"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
|
|
|
|
|
|
2024-01-24 17:12:34 +08:00
|
|
|
|
// var IP = net.IPv4(192, 168, 3, 7)
|
|
|
|
|
// var SendIP = net.IPv4(192, 168, 3, 7)
|
|
|
|
|
var IP = net.IPv4(127, 0, 0, 1)
|
|
|
|
|
var SendIP = net.IPv4(127, 0, 0, 1)
|
2024-01-17 17:49:11 +08:00
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
listen, err := net.ListenUDP("udp", &net.UDPAddr{
|
|
|
|
|
IP: IP,
|
|
|
|
|
Port: 5000,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("Listen udp err: %v", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
go func() {
|
2024-02-26 10:48:45 +08:00
|
|
|
|
tick := time.Tick(10 * time.Millisecond)
|
|
|
|
|
remoteAddr, err2 := net.Dial("udp", SendIP.String()+":"+"10000")
|
|
|
|
|
if err2 != nil {
|
|
|
|
|
fmt.Printf("Dial udp err: %v", err2)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
//remoteAddr := &net.UDPAddr{IP: SendIP, Port: 10000}
|
2024-01-17 17:49:11 +08:00
|
|
|
|
// 循环推送信息
|
|
|
|
|
for {
|
|
|
|
|
<-tick
|
|
|
|
|
ti.LifeSignal = ti.LifeSignal + 1
|
|
|
|
|
data := decoderVobcTrainInfo(ti)
|
2024-02-26 10:48:45 +08:00
|
|
|
|
_, err2 := remoteAddr.Write(data)
|
|
|
|
|
if err2 != nil {
|
|
|
|
|
panic(err2)
|
|
|
|
|
}
|
|
|
|
|
//_, err := listen.WriteToUDP(data, remoteAddr)
|
2024-01-17 17:49:11 +08:00
|
|
|
|
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)
|
2024-02-26 10:48:45 +08:00
|
|
|
|
case 0:
|
|
|
|
|
idleTrain(ti)
|
|
|
|
|
|
2024-01-17 17:49:11 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-26 10:48:45 +08:00
|
|
|
|
// 惰行
|
|
|
|
|
func idleTrain(ti *ReceiveTrainInfo) {
|
|
|
|
|
ti.TractionForce = 0
|
|
|
|
|
ti.BrakeForce = 0
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-17 17:49:11 +08:00
|
|
|
|
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]))
|
|
|
|
|
}
|