package message import ( "bytes" "encoding/binary" "fmt" "log/slog" "strings" ) // CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节) type CanetFrame struct { FF bool //true-1扩展帧 RTR bool //true-1远程帧 CanLen byte //CAN帧数据长度[0,8],CanData中有效数据字节数 CanId CanFrameId //CAN帧ID CanData []byte //CAN帧数据,8字节 IsTrainPcSim bool //是否列车pc仿真 } func NewCanetFrame(buf []byte, isTrainPcSim bool) *CanetFrame { cf := &CanetFrame{IsTrainPcSim: isTrainPcSim} cf.Decode(buf) return cf } func NewCanetFrame2(buf []byte, isTrainPcSim bool) *CanetFrame { cf := &CanetFrame{IsTrainPcSim: isTrainPcSim} cf.Decode2(buf) return cf } func (p *CanetFrame) Encode2() []byte { buf := make([]byte, 0) //CAN 帧ID frameId := uint32(p.CanId.ID1)<<21 | uint32(p.CanId.ID2)<<13 | uint32(p.CanId.ID3)<<5 | uint32(p.CanId.ID4) buf = binary.BigEndian.AppendUint32(buf, frameId) //CAN 帧数据 if len(p.CanData) != 8 { panic("len(p.CanData)!=8") } buf = append(buf, p.CanData...) return buf } func (p *CanetFrame) Encode() []byte { buf := make([]byte, 0) if !p.IsTrainPcSim { //canet200帧信息 b1 := byte(0x00) if p.FF { b1 |= 0x80 //bit7 } if p.RTR { b1 |= 0x40 //bit6 } b1 |= p.CanLen & 0x0f buf = append(buf, b1) } //CAN 帧ID buf = append(buf, p.CanId.ID1) buf = append(buf, p.CanId.ID2) buf = append(buf, p.CanId.ID3) if p.IsTrainPcSim { buf = append(buf, p.CanId.ID4) } else { buf = append(buf, p.CanId.ID4<<3) } //CAN 帧数据 if len(p.CanData) != 8 { panic("len(p.CanData)!=8") } buf = append(buf, p.CanData...) return buf } func (p *CanetFrame) Decode2(buf []byte) { bb := bytes.NewBuffer(buf) var idSource uint32 binary.Read(bb, binary.BigEndian, &idSource) data := make([]byte, bb.Len()) _, err := bb.Read(data) if err != nil { fmt.Println(err) return } b1 := byte(idSource >> 21) b2 := byte((idSource << 7) >> 13) b3 := byte((idSource << 15) >> 20) b4 := byte(idSource & 0x1f) p.CanId.ID1 = b1 p.CanId.ID2 = b2 p.CanId.ID3 = b3 p.CanId.ID4 = b4 p.CanData = data } func (p *CanetFrame) Decode(buf []byte) { if len(buf) != 13 { panic("len(buf)!=13") } p.FF = buf[0]&0x80 == 0x80 p.RTR = buf[0]&0x40 == 0x40 p.CanLen = buf[0] & 0x0f //1 2 3 4 p.CanId.ID1 = buf[1] p.CanId.ID2 = buf[2] p.CanId.ID3 = buf[3] p.CanId.ID4 = buf[4] >> 3 // p.CanData = buf[5:] } func (p *CanetFrame) String() string { sb := strings.Builder{} sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x, isTrainPcSim=%v", p.FF, p.RTR, p.CanLen, p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4, p.IsTrainPcSim)) sb.WriteString("CanData = ") for _, d := range p.CanData { sb.WriteString(fmt.Sprintf(" 0x%0x ", d)) } return sb.String() } // CanFrameType 获取canet帧类型 func (p *CanetFrame) CanFrameType() CanFrameType { switch p.CanId.ID3 { case 0x01: { //状态应答帧0x01 return CfStatusRsp } case 0x8d: { //msgTimeA数据帧0x80+0x0d return CfMsgTimeA } case 0x8e: { //msgTimeB数据帧0x80+0x0e return CfMsgTimeB } case 0xff: { //msgEnd数据帧0x80+0x7f return CfMsgEnd } case 0x02: { if p.CanId.ID1 == 0x62 && p.CanId.ID2 == 0x81 { return CfReq } else { return CfTimeSync } } default: if p.CanId.ID3 >= 0x80 && p.CanId.ID3 <= 0x8c { //数据帧0x80+(0x00-0x0c) return CfMsg } else { slog.Warn(fmt.Sprintf("无法识别的Canet帧[%s]", p.String())) return CfNon } } } // CanFrameType 帧类型定义 type CanFrameType = byte // Can帧类型枚举 const ( CfNon = CanFrameType(0) CfReq = CanFrameType(1) //查询帧0x02 CfStatusRsp = CanFrameType(2) //状态应答帧0x01 CfTimeSync = CanFrameType(3) //时间同步校验帧0x02 CfMsg = CanFrameType(4) //数据帧0x80+(0x00-0x0c) CfMsgTimeA = CanFrameType(5) //msgTimeA数据帧0x80+0x0d CfMsgTimeB = CanFrameType(6) //msgTimeB数据帧0x80+0x0e CfMsgEnd = CanFrameType(7) //msgEnd数据帧0x80+0x7f )