rts-sim-testing-service/example/mock_train_service/main.go

367 lines
11 KiB
Go
Raw Permalink Normal View History

2024-01-17 17:49:11 +08:00
package main
import (
"encoding/binary"
"fmt"
"net"
2024-02-27 10:26:20 +08:00
"os"
"strconv"
2024-01-17 17:49:11 +08:00
"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 SendIpPort = net.IPv4(192, 168, 3, 7)
2024-01-24 17:12:34 +08:00
var IP = net.IPv4(127, 0, 0, 1)
var SendIpPort = "127.0.0.1:10000"
2024-02-27 10:26:20 +08:00
var tick = 10 * time.Millisecond
2024-01-17 17:49:11 +08:00
2024-02-27 10:26:20 +08:00
// 参数1ip 参数2间隔
2024-01-17 17:49:11 +08:00
func main() {
2024-02-27 10:26:20 +08:00
if len(os.Args) >= 2 && os.Args[1] != "" {
SendIpPort = os.Args[1]
2024-02-27 10:26:20 +08:00
}
if len(os.Args) >= 3 && os.Args[2] != "" {
i, err := strconv.Atoi(os.Args[2])
2024-02-27 10:26:20 +08:00
if err != nil {
panic(err)
}
tick = time.Duration(i) * time.Millisecond
}
fmt.Println("目的IP_Port:", SendIpPort)
2024-02-27 10:26:20 +08:00
fmt.Println("间隔:", tick, "毫秒")
2024-01-17 17:49:11 +08:00
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-27 10:26:20 +08:00
tick := time.Tick(tick)
remoteAddr, err := net.Dial("udp", SendIpPort)
2024-02-27 10:26:20 +08:00
if err != nil {
fmt.Printf("Dial udp err: %v", err)
return
}
//remoteAddr := &net.UDPAddr{IP: SendIpPort, Port: 10000}
2024-01-17 17:49:11 +08:00
// 循环推送信息
for {
<-tick
ti.LifeSignal = ti.LifeSignal + 1
data := decoderVobcTrainInfo(ti)
_, 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)
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
}
// 惰行
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]))
}