rts-sim-testing-service/third_party/message/train_pc_sim_message.go

306 lines
6.9 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 message
import (
"bytes"
"encoding/binary"
"fmt"
"math"
"strconv"
"time"
)
const PC_SIM_HEADER = 0xEB
type TrainPcSimBaseMessage struct {
Type byte
DataLen byte
Data []byte
Crc uint16 // 校验码
}
// 编码
func (tp *TrainPcSimBaseMessage) Encode() []byte {
pack := make([]byte, 0)
pack = append(pack, PC_SIM_HEADER)
pack = append(pack, tp.Type)
pack = append(pack, byte(len(tp.Data)+1+1+1+2))
if len(tp.Data) > 0 {
pack = append(pack, tp.Data...)
//dataBufs := bytes.NewBuffer(nil)
//binary.Write(dataBufs, binary.BigEndian, tp.Data)
//data := dataBufs.Bytes()
//pack = append(pack, data...)
}
pack = binary.BigEndian.AppendUint16(pack, uint16(0xffff))
//pack = binary.BigEndian.AppendUint16(pack, uint16(crc.CalculateCRC(crc.CRC16, pack[1:])))
return pack
}
func TrainPcSimDecode(data []byte) []*TrainPcSimBaseMessage {
bms := make([]*TrainPcSimBaseMessage, 0)
buf := bytes.NewBuffer(data)
//hexData := hex.EncodeToString(data)
for {
if buf.Len() < 3 {
return bms /*, fmt.Errorf("解析仿真pc数据失败数据长度小于3")*/
}
header, _ := buf.ReadByte()
if header != PC_SIM_HEADER {
return bms /*, fmt.Errorf("数据包头错误,数据头为%v", hexData)*/
}
msgType, _ := buf.ReadByte()
dataLen, _ := buf.ReadByte()
dataLen = dataLen - 3 - 2
if buf.Len() < int(dataLen) {
return bms /*, fmt.Errorf("数据长度不够,数据类型为%v,需要长度:%v,实际长度:%v", msgType, dataLen, buf.Len())*/
}
sourceData := make([]byte, dataLen)
buf.Read(sourceData)
var crc uint16
binary.Read(buf, binary.BigEndian, &crc)
bms = append(bms, &TrainPcSimBaseMessage{Type: msgType, DataLen: dataLen - 2, Data: sourceData, Crc: crc})
}
return bms
}
// 解码
func (tp *TrainPcSimBaseMessage) Decode(data []byte) error {
if len(data) < 3 {
return fmt.Errorf("")
}
buf := bytes.NewBuffer(data)
h, _ := buf.ReadByte()
if h != PC_SIM_HEADER {
return fmt.Errorf("")
}
var pcType byte
pcType, _ = buf.ReadByte()
dataLen, _ := buf.ReadByte()
dataLen = dataLen - 3
if buf.Len() < int(dataLen) {
return fmt.Errorf("")
}
var dd = make([]byte, dataLen-2)
binary.Read(buf, binary.BigEndian, &dd)
var crcCode uint16
binary.Read(buf, binary.BigEndian, &crcCode)
tp.Type = pcType
tp.DataLen = dataLen
tp.Data = dd
tp.Crc = crcCode
return nil
//crc.CalculateCRC(crc.CRC16, data)
}
func IsTrue(d bool) byte {
if d {
return 1
}
return 0
}
func IsTrueForByte(d byte) bool {
if d == 1 {
return true
}
return false
}
// 确定、否定是你软件里的概念吧比如ATP输出量---紧急我们就认为是低电平有效。即0代表有紧急1代表无紧急
// 比如ATP的输入量---钥匙我们认为是高电平有效即1代表上钥匙0代表下钥匙。
func AtpLowPowerByte(d byte) bool {
if d == 0 {
return true
}
return false
}
// 列车速度位置报告
type TrainSpeedPlaceReportMsg struct {
PulseCount1 float32
PulseCount2 float32
Pp1 float32
Pp2 float32
HistoryCount float32
Tmp bool
PcCount float32
}
func (tp *TrainSpeedPlaceReportMsg) ParsePulseCount1(s1, s2 uint32) {
//tp.PulseCount1 += tp.HistoryCount
//tp.PulseCount2 += tp.HistoryCount
tp.PulseCount1 += float32(s1) * 200 / math.Pi / 840
tp.PulseCount2 += float32(s2) * 200 / math.Pi / 840
//tp.HistoryCount += s1
}
func (tp *TrainSpeedPlaceReportMsg) ParsePulseCut(s1, s2 float32) {
/* if s1 == 0 || s2 == 0 {
tp.PulseCount1 = tp.HistoryCount
tp.PulseCount2 = tp.HistoryCount
return
}*/
tp.HistoryCount += s1
d1 := tp.PulseCount1 - s1
if d1 <= 0 {
d1 = 0
}
d2 := tp.PulseCount1 - s2
if d2 <= 0 {
d2 = 0
}
tp.PulseCount1 = d1
tp.PulseCount2 = d2
}
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir uint16, s1 uint32) []byte {
data := make([]byte, 0)
data = binary.BigEndian.AppendUint16(data, runDir)
data = binary.BigEndian.AppendUint32(data, s1)
data = binary.BigEndian.AppendUint32(data, s1)
tp.PcCount = tp.PulseCount1 * 200 / math.Pi / float32(840)
data = binary.BigEndian.AppendUint32(data, uint32(tp.PcCount))
data = binary.BigEndian.AppendUint32(data, uint32(tp.PcCount))
/*now := time.Now().UTC()
// 将时间转换为毫秒
millis := now.UnixNano() / int64(time.Millisecond)
millisStr := strconv.Itoa(int(millis))
strs := []rune(millisStr)
sec := now.Unix()
millisStr2 := strconv.Itoa(int(sec))
strs2 := []rune(millisStr2)
dd, _ := strconv.Atoi(string(strs2[5:]))
mm, _ := strconv.Atoi(string(strs[len(strs)-3:]))*/
sec, ms := tp.time()
data = binary.BigEndian.AppendUint32(data, sec)
data = binary.BigEndian.AppendUint16(data, ms)
return data
}
func (tp *TrainSpeedPlaceReportMsg) time() (uint32, uint16) {
now := time.Now().UnixMilli()
timeNowStr := strconv.Itoa(int(now))
timeStrs := []rune(timeNowStr)
sec, _ := strconv.Atoi(string(timeStrs[5:10]))
ms, _ := strconv.Atoi(string(timeStrs[10:]))
return uint32(sec), uint16(ms)
}
func (tp *TrainSpeedPlaceReportMsg) Decode(d []byte) {
buf := bytes.NewBuffer(d)
var runDir uint16
binary.Read(buf, binary.BigEndian, &runDir)
var s1 uint32
binary.Read(buf, binary.BigEndian, &s1)
var s2 uint32
binary.Read(buf, binary.BigEndian, &s2)
var c1 uint32
binary.Read(buf, binary.BigEndian, &c1)
var c2 uint32
binary.Read(buf, binary.BigEndian, &c2)
var ts uint32
binary.Read(buf, binary.BigEndian, &ts)
var mts uint16
binary.Read(buf, binary.BigEndian, &mts)
fmt.Println(fmt.Sprintf("列车方向:%v,1路脉冲数:%v,2路脉冲数:%v,1路累计数:%v,2路累计数:%v,时间:%v,时间(毫秒):%v", runDir, s1, s2, c1, c2, ts, mts))
}
// 轨旁向列车pc仿真发送的命令码
const (
//手柄零位方向向前
DIR_ZERO_FORWARD = 0x2d
//钥匙开关状态
KEY_STATE = iota - 1
//手柄向前控制
HANDLE_FORWORD
//手柄向后控制
HANDLE_BACKWORD
//外部紧急制动反馈
OUTER_EMERGENCY_BRAKE
//列车制动状态
TRAIN_BRAKE_STATE
//开左门
LEFT_OPEN_DOOR
//关右门
CLOSE_RIGHT_DOOR
//关左门
CLOSE_LEFT_DOOR
//开右门
OPEN_RIGHT_DOOR
//折返按钮
TURN_BACK
//强制门允许
FORCE_DOOR_ALLOW
//模式降级按钮
TRAIN_MODE_DOWN
//确认按钮
CONFIRM
//模式升级按钮
TRAIN_MODE_UP
//牵引制动手柄零位
HANDLE_TO_ZERO
//ATO发车按钮
ATO_SEND_TRAIN
//列车完整性
TRAIN_INTEGRITY
//车载ATP/ATO旁路状态
ATP_ATO_BYPASS_STATe
//车辆牵引已切除状态
TRAIN_TRACTION_CUTED
//障碍物检测按钮
OBSTACLE_CHECK
//驾驶室激活反馈按钮
DRIVER_ACTIVE_REPORT
//制动重故障按钮
BRAKE_HEAVY_FAULT
//左门状态按钮
LEFT_DOOR_STATE
//右门状态按钮
RIGHT_DOOR_STATE
//唤醒按钮
WAKE_UP
//检修按钮
OVERHAUL
//欠压按钮
UNDERVOLTAGE
//休眠按钮
SLEEP
_
//紧急手柄拉下
EMERGENT_HANDLE_DOWN
//车门锁闭状态
DOOR_LOCK_STATE
//逃生门状态
LIFE_DOOR
//车辆低压上电状态
TRAIN_LOW_POWER
//ATP上电按钮
ATP_POWER_ON
//atp切除
ATP_CUT
//AA自动开关门
DOOR_MODE_AA
//AM自开人关
DOOR_MODE_AM
//MM人开人关
DOOR_MODE_MM
_
NOT_BREAK
)