| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package ym485
- import (
- "encoding/hex"
- "errors"
- "fmt"
- "math"
- "strconv"
- "strings"
- "github.com/valyala/bytebufferpool"
- )
- var ErrorInvalidChecksum = errors.New("数据校验错误")
- var ErrorInvalidLenght = errors.New("数据长度不够")
- var ErrorEncode = errors.New("编码错误")
- type DataPack struct {
- Start byte //帧起始符,恒为0x68,1字节
- Addr string //地址域,6字节,整数,大端传输
- Start2 byte //帧起始符,恒为0x68,1字节
- Ctl uint8 //控制码,1字节
- DataLen uint8 //数据域长度,1字节
- Data []byte //数据域
- Cs uint8 //Start到Cs之前的所有字节模256
- End byte //结束符号,恒为0x16,1字节
- }
- func (o *DataPack) EnCode(Addr string, Ctl uint8, Data []byte) (*bytebufferpool.ByteBuffer, error) {
- //初始化成员
- o.Start = 0x68
- o.Addr = Addr
- o.Start2 = 0x68
- o.Ctl = Ctl
- o.DataLen = uint8(len(Data))
- o.Data = Data
- o.End = 0x16
- //addr
- tmpAddr := EncodeAddr(o.Addr)
- if tmpAddr == nil {
- return nil, ErrorEncode
- }
- //序列化
- buf := bytebufferpool.Get()
- buf.WriteByte(o.Start)
- buf.Write(tmpAddr)
- buf.WriteByte(o.Start2)
- buf.WriteByte(o.Ctl)
- buf.WriteByte(o.DataLen)
- if o.DataLen > 0 {
- TmpData := make([]byte, o.DataLen)
- for i, b := range o.Data {
- TmpData[i] = b + 0x33
- }
- buf.Write(TmpData)
- }
- //计算校验码
- o.Cs = CheckSum(buf.Bytes())
- buf.WriteByte(o.Cs)
- buf.WriteByte(o.End)
- return buf, nil
- }
- func CheckSum(data []byte) uint8 {
- var sum uint64
- for _, c := range data {
- sum += uint64(c)
- }
- return uint8(sum % 256)
- }
- func VerifySum(data []byte) bool {
- if len(data) >= 12 {
- sum := data[len(data)-2] //倒数第二个字节
- sum_ := CheckSum(data[0 : len(data)-2])
- if sum == sum_ {
- return true
- }
- }
- return false
- }
- func (o *DataPack) DeCode(data []byte) error {
- if len(data) >= 12 {
- o.Start = data[0]
- o.Addr = DecodeAddr(data[1:7])
- o.Start2 = data[7]
- o.Ctl = data[8]
- o.DataLen = data[9]
- if o.DataLen > 0 {
- if o.DataLen > uint8(len(data)-12) {
- return ErrorInvalidLenght
- }
- o.Data = make([]byte, o.DataLen)
- for i, b := range data[10 : 10+o.DataLen] {
- o.Data[i] = b - 0x33
- }
- }
- o.Cs = data[10+o.DataLen]
- o.End = data[10+o.DataLen+1]
- cs := CheckSum(data[0 : 10+o.DataLen])
- if o.Cs != cs {
- return ErrorInvalidChecksum
- }
- return nil
- }
- return ErrorInvalidLenght
- }
- func EncodeAddr(Addr string) []byte {
- len0 := len(Addr)
- repeat := 12 - len0 //地址长度最多12个字符
- if repeat > 0 {
- Addr = strings.Repeat("0", repeat) + Addr
- }
- buf, err := ASCII2Lbcd([]byte(Addr))
- if err != nil {
- return nil
- }
- buf = Rotate(buf)
- return buf
- }
- func DecodeAddr(addr []byte) string {
- if len(addr) == 0 {
- return ""
- }
- buf := Rotate(addr)
- buf = Lbcd2ASCII(buf)
- return strings.TrimLeft(string(buf), "0")
- }
- // DecodeFloat64 prec为小数部分的长度
- func DecodeFloat64(dat []byte, prec int) (float64, error) {
- if len(dat) == 0 {
- return 0.0, errors.New("参数为空")
- }
- data := Rotate(dat)
- ss := []byte(hex.EncodeToString(data))
- if prec == 0 {
- return strconv.ParseFloat(string(ss), 64)
- }
- fss := make([]byte, 0, len(ss)+1)
- fss = append(fss, ss[0:len(ss)-prec]...)
- fss = append(fss, '.')
- fss = append(fss, ss[len(ss)-prec:]...)
- return strconv.ParseFloat(string(fss), 64)
- }
- // EncodeFloat64 prec0为整数部分的长度
- //prec1为小数部分的长度
- func EncodeFloat64(fval float64, prec0, prec1 int) ([]byte, error) {
- if (prec0+prec1)%2 != 0 {
- return nil, errors.New("整数和小数总长度非双数")
- }
- ui := uint(fval * math.Pow10(prec1))
- ss := fmt.Sprintf("%d", ui)
- repeat := prec0 + prec1 - len(ss)
- ss = strings.Repeat("0", repeat) + ss
- buf, err := ASCII2Lbcd([]byte(ss))
- if err != nil {
- return nil, err
- }
- buf = Rotate(buf)
- return buf, nil
- }
- func ReleaseByteBuffer(p *bytebufferpool.ByteBuffer) {
- if p != nil {
- bytebufferpool.Put(p)
- }
- }
|