package decoder import ( "bytes" "encoding/binary" "encoding/hex" "github.com/aceld/zinx/ziface" "github.com/aceld/zinx/zlog" "math" ) //ffff 01 00999999 000a 68656c6c6f2074657374 // +---------------+---------------+--------------------+----------------+------------------- // | 开始标志 | type | 秒时间戳 | 长度 | 消息体 // | 0xffff(2byte) | uint8(1byte) | uint32(4byte) | uint16(2byte) | bytes(N byte) // +---------------+---------------+--------------------+----------------+------------------- const OmcMsgHeaderSize = 9 //表示OMC空包长度 type OmcDecoder struct { StartSign uint16 MsgType uint8 TimeStamp uint32 LenOfBody uint16 Value []byte } func NewOmcDecoder() ziface.IDecoder { return &OmcDecoder{} } func (omc *OmcDecoder) GetLengthField() *ziface.LengthField { return &ziface.LengthField{ MaxFrameLength: math.MaxUint16 + 9, LengthFieldOffset: 7, LengthFieldLength: 2, LengthAdjustment: 0, InitialBytesToStrip: 0, //注意现在默认是大端,使用小端需要指定编码方式 Order: binary.BigEndian, } } func (omc *OmcDecoder) decode(data []byte) *OmcDecoder { ltvData := OmcDecoder{} ltvData.StartSign = binary.BigEndian.Uint16(data[0:2]) ltvData.MsgType = data[2] ltvData.TimeStamp = binary.BigEndian.Uint32(data[3:7]) ltvData.LenOfBody = binary.BigEndian.Uint16(data[7:9]) //Determine the length of V. (确定V的长度) ltvData.Value = make([]byte, ltvData.LenOfBody) //5. Get V binary.Read(bytes.NewBuffer(data[OmcMsgHeaderSize:OmcMsgHeaderSize+ltvData.LenOfBody]), binary.BigEndian, ltvData.Value) return <vData } func (omc *OmcDecoder) Intercept(chain ziface.IChain) ziface.IcResp { //1. Get the IMessage of zinx iMessage := chain.GetIMessage() if iMessage == nil { // Go to the next layer in the chain of responsibility return chain.ProceedWithIMessage(iMessage, nil) } //2. Get Data data := iMessage.GetData() zlog.Ins().DebugF("omc-RawData size:%d data:%s\n", len(data), hex.EncodeToString(data)) // (读取的数据不超过包头,直接进入下一层) if len(data) < OmcMsgHeaderSize { return chain.ProceedWithIMessage(iMessage, nil) } //4. Decode ltvData := omc.decode(data) zlog.Ins().DebugF("omc-decode %v", ltvData) // (将解码后的数据重新设置到IMessage中, Zinx的Router需要MsgID来寻址) iMessage.SetDataLen(uint32(ltvData.LenOfBody)) iMessage.SetMsgID(uint32(ltvData.MsgType)) iMessage.SetData(ltvData.Value) //6. Pass the decoded data to the next layer. // (将解码后的数据进入下一层) return chain.ProceedWithIMessage(iMessage, *ltvData) }