package zigbee import ( "encoding/binary" "errors" "time" "github.com/valyala/bytebufferpool" ) var ( HeadFlag2Down uint8 = 0xF2 HeadFlag2Up uint8 = 0xF3 ) var ( CmdSendData uint8 = 0x0B CmdSendDataAck uint8 = 0x8B CmdSetPid uint8 = 0x13 CmdGetPid uint8 = 0x14 CmdSetPidAck uint8 = 0x93 CmdGetPidAck uint8 = 0x94 ) var ErrorProtocol = errors.New("协议错误") var ErrorInvalidCrc1 = errors.New("外层CRC校验错误") var ErrorInvalidCrc2 = errors.New("内层CRC校验错误") type Pack interface { SetData(Count, No, Cmd uint16, Data []byte) EnCode() (*bytebufferpool.ByteBuffer, error) DeCode(Data []byte) error } // MsgHeader2 消息格式 type MsgHeader2 struct { Head byte //集中到单灯F2,单灯到集中F3 PoleID uint32 //杆号 Cmd2 uint8 //固定为F2 Seq uint8 //流水号,循环利用 Length2 uint8 //包体2长度 Body2 Pack //包体内容,普通功能协议或升级功能协议 Crc2 uint16 //内层CRC } func (o *MsgHeader2) SetDody(body Pack) { o.Body2 = body } func (o *MsgHeader2) SetData(PoleID uint32, Seq uint8) { o.PoleID = PoleID o.Seq = Seq } func (o *MsgHeader2) EnCode() (*bytebufferpool.ByteBuffer, error) { bytebuf, err := o.Body2.EnCode() //Body2 Pack //包体内容,普通功能协议或升级功能协议 defer func() { if bytebuf != nil { bytebufferpool.Put(bytebuf) } }() if err != nil { return nil, err } buff := bytebufferpool.Get() buff.WriteByte(HeadFlag2Down) //Head byte //集中到单灯F2,单灯到集中F3 tmp := make([]byte, 4) binary.BigEndian.PutUint32(tmp, o.PoleID) buff.Write(tmp) //LampID uint32 //杆号 buff.WriteByte(0xF2) //Cmd2 uint8 //固定为F2 buff.WriteByte(o.Seq) //Seq uint8 //流水号,循环利用 buff.WriteByte(uint8(bytebuf.Len())) //Length2 uint8 //包体2长度 buff.Write(bytebuf.B) //Body2 Pack //包体内容,普通功能协议或升级功能协议 crc16 := CRC16(buff.B) tmp2 := make([]byte, 2) binary.BigEndian.PutUint16(tmp2, crc16) buff.Write(tmp2) //计算内层CRC16 return buff, nil } func (o *MsgHeader2) DeCode(Data []byte) error { if len(Data) >= 10 { o.Head = Data[0] //集中到单灯F2,单灯到集中F3 o.PoleID = binary.BigEndian.Uint32(Data[1:5]) //杆号 o.Cmd2 = Data[5] //固定为F2 o.Seq = Data[6] //流水号,循环利用 o.Length2 = Data[7] //包体2长度 o.Crc2 = binary.BigEndian.Uint16(Data[o.Length2+8 : o.Length2+10]) crc := CRC16(Data[0 : o.Length2+8]) if crc != o.Crc2 { return ErrorInvalidCrc2 } return o.Body2.DeCode(Data[8 : o.Length2+8]) } return ErrorProtocol } // GeneralFunc 普通功能协议 type GeneralFunc struct { Len uint8 //此包长度 Count uint8 //总包数 No uint8 //当前升级包号 Cmd uint8 //单杆命令 Data []byte //数据内容 } func (o *GeneralFunc) SetData(Count, No, Cmd uint16, Data []byte) { o.Cmd = uint8(Cmd) o.Data = Data o.Count = uint8(Count) o.No = uint8(No) } func (o *GeneralFunc) EnCode() (*bytebufferpool.ByteBuffer, error) { buff := bytebufferpool.Get() buff.WriteByte(uint8(4 + len(o.Data))) // Len uint8 //此包长度 buff.WriteByte(0) //Count uint8 //总包数 buff.WriteByte(0) //No uint8 //当前升级包号 buff.WriteByte(o.Cmd) //M1Cmd uint8 //单杆命令 buff.Write(o.Data) //mapData []byte //数据内容 return buff, nil } func (o *GeneralFunc) DeCode(Data []byte) error { if len(Data) >= 4 { o.Len = Data[0] o.Count = Data[1] o.No = Data[2] o.Cmd = Data[3] o.Data = Data[4:] return nil } return ErrorProtocol } // UpgradeFunc 升级功能协议 type UpgradeFunc struct { Len uint8 //此包长度 Count uint16 //总包数 No uint16 //当前升级包号 Cmd uint8 //单杆命令 Data []byte //数据内容 } func (o *UpgradeFunc) SetData(Count, No, Cmd uint16, Data []byte) { o.Cmd = uint8(Cmd) o.Data = Data o.Count = Count o.No = No } func (o *UpgradeFunc) EnCode() (*bytebufferpool.ByteBuffer, error) { buff := bytebufferpool.Get() buff.WriteByte(uint8(6 + len(o.Data))) // Len uint8 //此包长度 tmp := make([]byte, 2) binary.BigEndian.PutUint16(tmp, o.Count) buff.Write(tmp) //Count uint16 //总包数 binary.BigEndian.PutUint16(tmp, o.No) buff.Write(tmp) //No uint16 //当前升级包号 buff.WriteByte(o.Cmd) //M1Cmd uint8 //单杆命令 buff.Write(o.Data) //mapData []byte //数据内容 return buff, nil } func (o *UpgradeFunc) DeCode(Data []byte) error { if len(Data) >= 4 { o.Len = Data[0] o.Count = binary.BigEndian.Uint16(Data[1:3]) o.No = binary.BigEndian.Uint16(Data[3:5]) o.Cmd = Data[5] o.Data = Data[6:] return nil } return ErrorProtocol } type OnOffTime struct { OnHour uint8 `json:"onhour"` OnMinite uint8 `json:"onminite"` OffHour uint8 `json:"offhour"` OffMinite uint8 `json:"offminite"` Brightness uint8 `json:"brightness"` //亮度0~100 } func (o *OnOffTime) SetData(onHour, onMinite, offHour, offMinite, brightness uint8) { o.OnHour = onHour o.OnMinite = onMinite o.OffHour = offHour o.OffMinite = offMinite o.Brightness = brightness } func (o *OnOffTime) EnCode() []byte { buff := make([]byte, 5) buff[0] = o.OnHour buff[1] = o.OnMinite buff[2] = o.OffHour buff[3] = o.OffMinite buff[4] = o.Brightness return buff } func (o *OnOffTime) DeCode(data []byte) error { if len(data) >= 5 { o.OnHour = data[0] o.OnMinite = data[1] o.OffHour = data[2] o.OffMinite = data[3] o.Brightness = data[4] return nil } return ErrorProtocol } func (o *OnOffTime) InTimeRange(t time.Time) bool { h := uint8(t.Hour()) m := uint8(t.Minute()) if o.OnHour > o.OffHour { //跨日情况,例如19:30~5:30,开灯时间大于关灯时间 if h > o.OnHour || h < o.OffHour || (h == o.OnHour && m >= o.OnMinite) || (h == o.OffHour && m <= o.OffMinite) { return true } } else if o.OnHour < o.OffHour { //开灯时间小于关灯时间 if (h > o.OnHour && h < o.OffHour) || (h == o.OnHour && m >= o.OnMinite) || (h == o.OffHour && m <= o.OffMinite) { return true } } else { //开灯时间等于关灯时间 if h == o.OnHour && m >= o.OnMinite && m <= o.OffMinite { return true } } return false } // CalculateChddjkZigbeeResponselength 长和单灯控制器zigbee协议,预估长度,非精确长度 func CalculateChddjkZigbeeResponselength(adu []byte) int { return int(float32(len(adu)) * 1.5) }