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

367 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 SendIP = net.IPv4(192, 168, 3, 7)
var IP = net.IPv4(127, 0, 0, 1)
var SendIP = "127.0.0.1"
var tick = 10 * time.Millisecond
// 参数1ip 参数2间隔
func main() {
if len(os.Args) >= 2 && os.Args[1] != "" {
SendIP = os.Args[0]
}
if len(os.Args) >= 3 && os.Args[2] != "" {
i, err := strconv.Atoi(os.Args[1])
if err != nil {
panic(err)
}
tick = time.Duration(i) * time.Millisecond
}
fmt.Println("目的IP:", SendIP)
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", fmt.Sprintf("%s:%d", SendIP, 10000))
if err != nil {
fmt.Printf("Dial udp err: %v", err)
return
}
//remoteAddr := &net.UDPAddr{IP: SendIP, 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]))
}