Open whaosoft opened 1 year ago
嗯,这个只是读取库,读取转换需要解析地址:
// catchData 抓取数据--- func (d *Device) catchData(client *gos7.Client) (err error) { if d.tagCache == nil || d.Start == 0 { return nil } dataMap := make(H) for key, group := range d.tagCache.Groups { //log.Println("抓取DB:", key, group.Start, group.Length) var reader *gos7.DataReader = nil if len(key) >= 2 { area := key[0:2] if area == "DB" { dbNo, _ := strconv.Atoi(key[2:]) reader, err = client.AGReadDB(dbNo, group.Start, group.Length) } else if area == "QB" || area == "QW" || area == "QD" { reader, err = client.AGReadQ(group.Start, group.Length) } else if area == "IB" || area == "IW" || area == "ID" { reader, err = client.AGReadI(group.Start, group.Length) } else if area == "VB" || area == "VW" || area == "VD" { reader, err = client.AGReadV(group.Start, group.Length) } else if area == "MB" || area == "MW" || area == "MD" { reader, err = client.AGReadM(group.Start, group.Length) } } else { if key == "Q" { reader, err = client.AGReadQ(group.Start, group.Length) } else if key == "I" { reader, err = client.AGReadI(group.Start, group.Length) } else if key == "V" { reader, err = client.AGReadV(group.Start, group.Length) } else if key == "M" { reader, err = client.AGReadM(group.Start, group.Length) } } if err != nil { log.Println("抓取DB错误:", key, group.Start, group.End) for _, elem := range group.ElemMap { log.Println("集合DB错误:", elem.Addr) } return } if reader == nil { continue } //获取元素数据 for _, elem := range group.ElemMap { offset := elem.Index1 - group.Start if offset < 0 { continue } value, readErr := reader.Read(elem.Typ, offset, elem.Index2) if readErr != nil { log.Println(readErr.Error()) continue } dataMap[elem.Code] = value } } d.putData(dataMap) return }
地址解析的大概代码
type S7Elem struct { Addr string `json:"a"` Typ string `json:"t"` Code string Key1 string Key2 string Index1 int Index2 int } type TagGroup struct { Start int End int Length int ElemMap []*S7Elem } type TagCache struct { Groups map[string]*TagGroup Tags []string Sets map[string]string } func NewTagCache() *TagCache { return &TagCache{ Groups: make(map[string]*TagGroup), Tags: make([]string, 0), Sets: make(map[string]string), } } func ParseTag(code string, tag *S7Elem) (*S7Elem, error) { tag.Code = code addr := strings.ToUpper(tag.Addr) addr = strings.Replace(addr, " ", "", -1) typ := strings.ToLower(tag.Typ) typ = strings.Replace(typ, " ", "", -1) if addr == "" || typ == "" { return nil, errors.New("PLC:数据为空") } tag.Addr = addr tag.Typ = typ switch area := addr[0:2]; area { case "DB": //input byte dbArray := strings.Split(addr, ".") if len(dbArray) < 2 { return nil, errors.New("Db Area read variable should not be empty") } key1 := dbArray[0] //DB1 key2 := dbArray[1] //000 index2 := 0 //点位数 if len(dbArray) == 3 { index2, _ = strconv.Atoi(dbArray[2]) //位数 } index1 := 0 match, _ := regexp.MatchString("^\\d+$", key2) if len(key2) > 3 { index1, _ = strconv.Atoi(key2[3:]) } else if match { index1, _ = strconv.Atoi(key2) } tag.Key1 = key1 tag.Key2 = key2 tag.Index1 = index1 tag.Index2 = index2 return tag, nil case "VB", "VW", "VD", "MB", "MW", "MD", "IB", "IW", "ID", "QB", "QW", "QD": firstKey := string(addr[2:]) dbArray := strings.Split(firstKey, ".") index2 := 0 index1 := 0 if len(dbArray) == 2 { index1, _ = strconv.Atoi(dbArray[0]) index2, _ = strconv.Atoi(dbArray[1]) } else { index1, _ = strconv.Atoi(firstKey) } key1 := area key2 := addr tag.Key1 = key1 tag.Key2 = key2 tag.Index1 = index1 tag.Index2 = index2 return tag, nil default: switch otherArea := addr[0:1]; otherArea { case "I", "M", "Q", "V": firstKey := string(addr[1:]) dbArray := strings.Split(firstKey, ".") index2 := 0 index1 := 0 if len(dbArray) == 2 { index1, _ = strconv.Atoi(dbArray[0]) index2, _ = strconv.Atoi(dbArray[1]) } else { index1, _ = strconv.Atoi(firstKey) } key1 := otherArea key2 := addr tag.Key1 = key1 tag.Key2 = key2 tag.Index1 = index1 tag.Index2 = index2 return tag, nil default: return nil, errors.New("PLC:数据为空") } } } func (tc *TagCache) AddTag(code string, tag *S7Elem) { tag, _ = ParseTag(code, tag) if tag == nil { return } if _, ok := tc.Sets[tag.Addr]; ok { return } tc.Sets[tag.Addr] = code tc.Tags = append(tc.Tags, tag.Addr) key1 := tag.Key1 if _, ok := tc.Groups[key1]; !ok { elemMap := make([]*S7Elem, 0) tc.Groups[key1] = &TagGroup{ Start: -1, End: 0, Length: 0, ElemMap: elemMap, } } typLen := 1 switch tag.Typ { case "bool", "byte": typLen = 1 break case "word", "int": typLen = 2 break case "dword", "dint", "real": typLen = 4 break } if tc.Groups[key1].Start < 0 || tag.Index1 < tc.Groups[key1].Start { tc.Groups[key1].Start = tag.Index1 } thisEnd := tag.Index1 + typLen if thisEnd > tc.Groups[key1].End { tc.Groups[key1].End = thisEnd } tc.Groups[key1].Length = tc.Groups[key1].End - tc.Groups[key1].Start tc.Groups[key1].ElemMap = append(tc.Groups[key1].ElemMap, tag) }
链接的大概代码:
// loop 循环工作--- func (d *Device) loop() error { defer func() { // 必须要先声明defer,否则不能捕获到panic异常 log.Println(d.Id, "PLC:工作线程已经退出") if err := recover(); err != nil { log.Println(err) // 这里的err其实就是panic传入的内容 } }() //开始链接 client, err := gos7.NewClient(d.DeviceAddr, d.DeviceRack, d.DeviceSlot) if err != nil { log.Println(d.Id, "PLC:设备链接失败,终止任务....", "host:", d.DeviceAddr, "rack:", d.DeviceRack, "slot:", d.DeviceSlot, "error:", err.Error()) return err } defer func() { client.Close() if d.IsRun { d.putOffline() d.IsRun = false } log.Println(d.Id, "PLC:设备断开....") }() //log.Println(d.Id, "PLC:链接设备成功....") for { log.Println("开始抓取数据:", d.DeviceNo) err = d.catchData(client) if err != nil { log.Println(err.Error()) return err } //如果开机 if d.PowerStatus { if d.Sleep < 1 { d.Sleep = 1 } //log.Println("开机轮值(秒):", d.Sleep) time.Sleep(time.Duration(d.Sleep) * time.Second) } else { if d.DieSleep < 5 { d.DieSleep = 5 } //log.Println("关机轮值(秒):", d.DieSleep) time.Sleep(time.Duration(d.DieSleep) * time.Second) } } }
最近有点忙,有什么疑问可以留言,等稍微有空我整理写一个 demo
嗯,这个只是读取库,读取转换需要解析地址:
地址解析的大概代码
链接的大概代码: