261 lines
5.9 KiB
Go
261 lines
5.9 KiB
Go
package message
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/binary"
|
||
"fmt"
|
||
"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 {
|
||
//列车id
|
||
TrainId string
|
||
PulseCount1 uint32
|
||
PulseCount2 uint32
|
||
}
|
||
|
||
func (tp *TrainSpeedPlaceReportMsg) ParsePulseCount1(s1, s2 uint32) {
|
||
tp.PulseCount1 += s1
|
||
tp.PulseCount2 += s2
|
||
}
|
||
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir bool, s1, s2 uint32) []byte {
|
||
data := make([]byte, 0)
|
||
data = binary.BigEndian.AppendUint16(data, uint16(IsTrue(runDir)))
|
||
data = binary.BigEndian.AppendUint32(data, s1)
|
||
data = binary.BigEndian.AppendUint32(data, s2)
|
||
data = binary.BigEndian.AppendUint32(data, tp.PulseCount1)
|
||
data = binary.BigEndian.AppendUint32(data, tp.PulseCount2)
|
||
now := time.Now().UTC()
|
||
// 将时间转换为毫秒
|
||
millis := now.UnixNano() / int64(time.Millisecond)
|
||
millisStr := strconv.Itoa(int(millis))
|
||
strs := []rune(millisStr)
|
||
|
||
second, _ := strconv.Atoi(string(strs[:len(strs)-3]))
|
||
mm, _ := strconv.Atoi(string(strs[len(strs)-3:]))
|
||
data = binary.BigEndian.AppendUint32(data, uint32(second))
|
||
data = binary.BigEndian.AppendUint16(data, uint16(mm))
|
||
|
||
return data
|
||
}
|
||
|
||
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
|
||
)
|