2023-11-21 17:20:03 +08:00
|
|
|
|
package message
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2023-11-21 18:13:50 +08:00
|
|
|
|
"log/slog"
|
2023-11-21 17:20:03 +08:00
|
|
|
|
"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字节
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewCanetFrame(buf []byte) *CanetFrame {
|
|
|
|
|
cf := &CanetFrame{}
|
|
|
|
|
cf.Decode(buf)
|
|
|
|
|
return cf
|
|
|
|
|
}
|
|
|
|
|
func (p *CanetFrame) Encode() []byte {
|
|
|
|
|
buf := make([]byte, 0, 13)
|
|
|
|
|
//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)
|
|
|
|
|
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) 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{}
|
2023-11-22 11:21:17 +08:00
|
|
|
|
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x,", p.FF, p.RTR, p.CanLen,
|
2023-11-21 17:20:03 +08:00
|
|
|
|
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
|
|
|
|
|
sb.WriteString("CanData = ")
|
|
|
|
|
for _, d := range p.CanData {
|
|
|
|
|
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
|
|
|
|
|
}
|
|
|
|
|
return sb.String()
|
|
|
|
|
}
|
2023-11-21 18:13:50 +08:00
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
)
|