| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 | 
							- package modbus
 
- import (
 
- 	"fmt"
 
- 	"golib/v2/gnet"
 
- )
 
- type Enum struct {
 
- 	No    uint16 `xml:"No,attr"`
 
- 	Label string `xml:"Label,attr"`
 
- 	Key   string `xml:"Key,attr"`
 
- 	Tag   string `xml:"Tag,attr"`
 
- }
 
- type Register struct {
 
- 	No    uint16 `xml:"No,attr"`     // No 起始位置, 请输入 10 进制的数字
 
- 	Label string `xml:"Label,attr"`  // Label 中文标签
 
- 	Len   uint16 `xml:"RetLen,attr"` // Len 数据长度, 即 No 包含的数据长度. 根据长度自动变换 8(1)/16(2)/32(4)/64(8) 位解析
 
- 	Type  string `xml:"Type,attr"`   // Type 数据类型, 见下方数据类型
 
- 	Key   string `xml:"Key,attr"`    // Key 字段, 用于转换成 map 时
 
- 	Bit   bool   `xml:"Bit,attr"`    // Bit 用于将读取的数据逐帧解析到 Key 当中, 当 Bit 为 true 时必须配置 Enums
 
- 	Tag   string `xml:"Tag,attr"`
 
- 	Enum  []Enum `xml:"Enums>Enum"`
 
- }
 
- type Page struct {
 
- 	Order    string     `xml:"Order,attr"`
 
- 	Code     uint8      `xml:"Code,attr"`          // Code 功能码
 
- 	Register []Register `xml:"Registers>Register"` // Register 已注册需要解析的数据列表
 
- 	codeMap  map[uint16]Register
 
- 	keyMap   map[string]Register
 
- }
 
- func (p *Page) HasNo(no uint16) (Register, bool) {
 
- 	reg, ok := p.codeMap[no]
 
- 	if !ok {
 
- 		return Register{}, false
 
- 	}
 
- 	return reg, true
 
- }
 
- func (p *Page) HasKey(key string) (Register, bool) {
 
- 	reg, ok := p.keyMap[key]
 
- 	if !ok {
 
- 		return Register{}, false
 
- 	}
 
- 	return reg, true
 
- }
 
- func (p *Page) Tag(tag string) []string {
 
- 	k := make([]string, 0)
 
- 	for _, reg := range p.Register {
 
- 		if reg.Tag == tag {
 
- 			k = append(k, reg.Tag)
 
- 		} else {
 
- 			if !reg.Bit {
 
- 				continue
 
- 			}
 
- 			for _, enum := range reg.Enum {
 
- 				if enum.Tag == tag {
 
- 					k = append(k, reg.Tag)
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- 	return k
 
- }
 
- // Parse  使用当前 Page 解析数据到 valueMap. 其中 b 是数据包, no 是起始地址; len 寄存器数量
 
- // 即从 no 开始解析 len 个寄存器, 并根据配置将其保存在 valueMap 内
 
- func (p *Page) Parse(b []byte, no, len uint16, valueMap map[string]any) {
 
- 	for i := uint16(0); i < len; i++ {
 
- 		r := no + i
 
- 		if reg, ok := p.codeMap[r]; ok {
 
- 			bs := b[i*2 : i*2+reg.Len]
 
- 			var order gnet.BinaryOrder
 
- 			switch p.Order {
 
- 			case "big":
 
- 				order = gnet.BigEndian
 
- 			case "little":
 
- 				order = gnet.LittleEndian
 
- 			default:
 
- 				continue
 
- 			}
 
- 			if reg.Bit {
 
- 				parseBit(order, reg, bs, valueMap)
 
- 			} else {
 
- 				valueMap[reg.Key] = parseByteValue(order, reg, bs)
 
- 			}
 
- 		}
 
- 	}
 
- }
 
- type ItemInfo struct {
 
- 	Name  string // Name 页面名称
 
- 	Pages []Page `xml:"Pages>Page"`
 
- }
 
- func (i *ItemInfo) Page(funcCode uint8) *Page {
 
- 	for _, p := range i.Pages {
 
- 		if p.Code == funcCode {
 
- 			return &p
 
- 		}
 
- 	}
 
- 	return &Page{}
 
- }
 
- func (i *ItemInfo) Init() {
 
- 	for pi, page := range i.Pages {
 
- 		page.codeMap = make(map[uint16]Register)
 
- 		page.keyMap = make(map[string]Register)
 
- 		for _, reg := range page.Register {
 
- 			str := fmt.Sprintf("itemName: %s, Page: %d, No.: %d: ", i.Name, pi, reg.No)
 
- 			if reg.Bit && len(reg.Enum) == 0 {
 
- 				panic(str + "Bit == true but Enum == 0")
 
- 			}
 
- 			switch reg.Type {
 
- 			case TypeUInt, TypeInt, TypeFloat, TypeBool:
 
- 				break
 
- 			default:
 
- 				panic(str + "unknown Type: " + reg.Type)
 
- 			}
 
- 			if !reg.Bit && reg.Key == "" {
 
- 				panic(str + "Key == empty")
 
- 			}
 
- 			if _, ok := page.codeMap[reg.No]; ok {
 
- 				panic(str + "duplicate No.")
 
- 			}
 
- 			page.codeMap[reg.No] = reg
 
- 			if _, ok := page.keyMap[reg.Key]; ok {
 
- 				panic(str + "duplicate Key")
 
- 			}
 
- 			page.keyMap[reg.Key] = reg
 
- 		}
 
- 		i.Pages[pi] = page
 
- 	}
 
- }
 
- // 数据类型
 
- const (
 
- 	TypeUInt  = "uint"  // TypeInt 数字类型.
 
- 	TypeInt   = "int"   // TypeInt 数字类型.
 
- 	TypeFloat = "float" // TypeFloat 小数类型
 
- 	TypeBool  = "bool"  // TypeBool 布尔类型
 
- )
 
 
  |