// DiscoverCharacteristics finds all the characteristics within a service. [Vol 3, Part G, 4.6.1] // If filter is specified, only filtered characteristics are returned. func (cln *Client) DiscoverCharacteristics(cs []ble.UUID, s *ble.Service) ([]*ble.Characteristic, error) { rsp := cln.conn.sendReq(62, xpc.Dict{ "kCBMsgArgDeviceUUID": cln.id, "kCBMsgArgServiceStartHandle": s.Handle, "kCBMsgArgServiceEndHandle": s.EndHandle, "kCBMsgArgUUIDs": uuidSlice(cs), }) if rsp.err() != nil { return nil, rsp.err() } for _, xcs := range rsp.characteristics() { xc := msg(xcs.(xpc.Dict)) s.Characteristics = append(s.Characteristics, &ble.Characteristic{ UUID: ble.MustParse(xc.uuid()), Property: ble.Property(xc.characteristicProperties()), Handle: uint16(xc.characteristicHandle()), ValueHandle: uint16(xc.characteristicValueHandle()), }) } return s.Characteristics, nil }
// DiscoverCharacteristics finds all the characteristics within a service. [Vol 3, Part G, 4.6.1] // If filter is specified, only filtered characteristics are returned. func (p *Client) DiscoverCharacteristics(filter []ble.UUID, s *ble.Service) ([]*ble.Characteristic, error) { p.Lock() defer p.Unlock() start := s.Handle var lastChar *ble.Characteristic for start <= s.EndHandle { length, b, err := p.ac.ReadByType(start, s.EndHandle, ble.CharacteristicUUID) if err == ble.ErrAttrNotFound { break } else if err != nil { return nil, err } for len(b) != 0 { h := binary.LittleEndian.Uint16(b[:2]) p := ble.Property(b[2]) vh := binary.LittleEndian.Uint16(b[3:5]) u := ble.UUID(b[5:length]) c := &ble.Characteristic{ UUID: u, Property: p, Handle: h, ValueHandle: vh, EndHandle: s.EndHandle, } if filter == nil || ble.Contains(filter, u) { s.Characteristics = append(s.Characteristics, c) } if lastChar != nil { lastChar.EndHandle = c.Handle - 1 } lastChar = c start = vh + 1 b = b[length:] } } return s.Characteristics, nil }