code: 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
  }
docs: // DiscoverCharacteristics finds all the characteristics within a service. [Vol 3, Part G, 4.6.1]
  // If filter is specified, only filtered characteristics are returned.