func interfaceProperties(s *dbus.Signal) Properties {
	var dict map[string]Properties
	err := dbus.Store(s.Body[1:2], &dict)
	if err != nil {
		log.Print(err)
		return nil
	}
	return dict[deviceInterface]
}
If the InterfacesAdded signal contains deviceInterface,
return the corresponding properties, otherwise nil.
See http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
package ble
import (
	"fmt"
	"log"
	"time"
	"github.com/godbus/dbus"
)
func (conn *Connection) addMatch(rule string) error {
	return conn.bus.BusObject().Call(
		"org.freedesktop.DBus.AddMatch",
		0,
		rule,
	).Err
}
func (conn *Connection) removeMatch(rule string) error {
	return conn.bus.BusObject().Call(
		"org.freedesktop.DBus.RemoveMatch",
		0,
		rule,
	).Err
}
type DiscoveryTimeoutError []string
func (e DiscoveryTimeoutError) Error() string {
	return fmt.Sprintf("discovery timeout %v", []string(e))
}
func (adapter *blob) Discover(timeout time.Duration, uuids ...string) error {
	conn := adapter.conn
	signals := make(chan *dbus.Signal)
	defer close(signals)
	conn.bus.Signal(signals)
	defer conn.bus.RemoveSignal(signals)
	rule := "type='signal',interface='org.freedesktop.DBus.ObjectManager',member='InterfacesAdded'"
	err := adapter.conn.addMatch(rule)
	if err != nil {
		return err
	}
	defer func() { _ = conn.removeMatch(rule) }()
	err = adapter.SetDiscoveryFilter(uuids...)
	if err != nil {
		return err
	}
	err = adapter.StartDiscovery()
	if err != nil {
		return err
	}
	defer func() { _ = adapter.StopDiscovery() }()
	var t <-chan time.Time
	if timeout != 0 {
		t = time.After(timeout)
	}
	return adapter.discoverLoop(uuids, signals, t)
}
func (adapter *blob) discoverLoop(uuids []string, signals <-chan *dbus.Signal, timeout <-chan time.Time) error {
	for {
		select {
		case s := <-signals:
			switch s.Name {
			case interfacesAdded:
				if adapter.discoveryComplete(s, uuids) {
					return nil
				}
			default:
				log.Printf("%s: unexpected signal %s", adapter.Name(), s.Name)
			}
		case <-timeout:
			return DiscoveryTimeoutError(uuids)
		}
	}
}
func (adapter *blob) discoveryComplete(s *dbus.Signal, uuids []string) bool {
	props := interfaceProperties(s)
	if props == nil {
		log.Printf("%s: skipping signal %s with no device interface", adapter.Name(), s.Name)
		return false
	}
	name, ok := props["Name"].Value().(string)
	if !ok {
		name = "[unknown]"
	}
	services, ok := props["UUIDs"].Value().([]string)
	if !ok {
		services = nil
	}
	if !uuidsInclude(services, uuids) {
		log.Printf("%s: skipping signal for device %s without matching UUIDs", adapter.Name(), name)
		log.Printf("%s: wanted %v, got %v", adapter.Name(), uuids, services)
		return false
	}
	log.Printf("%s: discovered %s", adapter.Name(), name)
	return true
}