351 lines
11 KiB
Go
351 lines
11 KiB
Go
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
|
||
|
||
// 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)
|
||
|
||
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() {
|
||
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}
|
||
// 循环推送信息
|
||
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]))
|
||
}
|