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 { 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 )