Пример #1
0
        public IList <Pebble> Detect(string adapterName, bool doDiscovery, bool pairDiscovered, bool unpairFailed)
        {
            //these properties are defined by bluez in /doc/profile-api.txt
            //but it turns out the defaults work just fine
            var properties = new Dictionary <string, object> ();

            //properties ["AutoConnect"] = true;
            //properties ["Name"] = "Serial Port";
            //properties ["Service"] = pebbleSerialUUID;
            //properties ["Role"] = "client";
            //properties ["PSM"] = (ushort)1;
            //properties ["RequireAuthentication"] = false;
            //properties ["RequireAuthorization"] = false;
            //properties ["Channel"] = (ushort)0;

            //get a proxy for the profile manager so we can register our profile
            _profileManager = _connection.System.GetObject <ProfileManager1> (BlueZPath.Service, BlueZPath.Root);
            //create and register our profile
            _profile = new PebbleProfile();
            _connection.System.Register(ProfilePath, _profile);
            _profileManager.RegisterProfile(ProfilePath, PebbleSerialUUID, properties);
            _profile.NewConnectionAction = (path, fd, props) => {
                if (_pebbles [path].Pebble == null)
                {
                    //new connection
                    //System.Console.WriteLine("Connected to " + path);
                    _pebbles [path].FileDescriptor = fd;
                    _pebbles [path].FileDescriptor.SetBlocking();
                    var stream = _pebbles [path].FileDescriptor.OpenAsStream(true);
                    _pebbles [path].Stream = stream;
                    var blueZPebble = new BlueZ5Pebble(new PebbleBluetoothConnection(stream), _pebbles[path].Device, _pebbles [path].Name);
                    _pebbles [path].Pebble = blueZPebble;
                }
                else
                {
                    //reconnect
                    //if the descriptor is new, close the old one and replace it
                    if (fd.FD != _pebbles [path].FileDescriptor.FD)
                    {
                        //dispose of the old fd
                        _pebbles [path].FileDescriptor.Close();
                        _pebbles [path].FileDescriptor.Dispose();

                        //setup the new fd
                        _pebbles [path].FileDescriptor = fd;
                        _pebbles [path].FileDescriptor.SetBlocking();
                        var stream = _pebbles [path].FileDescriptor.OpenAsStream(true);
                        _pebbles [path].Stream = stream;
                    }
                    ((PebbleBluetoothConnection)_pebbles [path].Pebble.Connection).Reconnect(_pebbles [path].Stream);
                }
            };

            //get a copy of the object manager so we can browse the "tree" of bluetooth items
            _objectManager = _connection.System.GetObject <org.freedesktop.DBus.ObjectManager> (BlueZPath.Service, ObjectPath.Root);
            //register these events so we can tell when things are added/removed (eg: discovery)
            //_objectManager .InterfacesAdded += (p, i) => {
            //System.Console.WriteLine ("Discovered "+p);
            //};
            //_objectManager .InterfacesRemoved += (p, i) => {
            //System.Console.WriteLine ("Lost" + p);
            //};

            //get the agent manager so we can register our agent
            _agentManager = _connection.System.GetObject <AgentManager1> (BlueZPath.Service, BlueZPath.Root);
            _agent        = new PebbleAgent();
            //register our agent and make it the default
            _connection.System.Register(AgentPath, _agent);
            _agentManager.RegisterAgent(AgentPath, "KeyboardDisplay");
            _agentManager.RequestDefaultAgent(AgentPath);

            //get the bluetooth object tree
            var managedObjects = _objectManager.GetManagedObjects();
            //find our adapter
            ObjectPath adapterPath = null;

            foreach (var obj in managedObjects.Keys)
            {
                if (managedObjects [obj].ContainsKey(typeof(Adapter1).DBusInterfaceName()))
                {
                    if (string.IsNullOrEmpty(adapterName) || obj.ToString().EndsWith(adapterName))
                    {
                        adapterPath = obj;
                        break;
                    }
                }
            }

            if (adapterPath == null)
            {
                throw new ArgumentException("Could not find bluetooth adapter");
            }

            //get a dbus proxy to the adapter
            _adapter = _connection.System.GetObject <Adapter1> (BlueZPath.Service, BlueZPath.Adapter(adapterName));

            if (doDiscovery)
            {
                System.Console.WriteLine("Starting Discovery...");
                //scan for any new devices
                _adapter.StartDiscovery();
                Thread.Sleep(5000);                //totally arbitrary constant, the best kind
                //Thread.Sleep ((int)adapter.DiscoverableTimeout * 1000);

                //refresh the object graph to get any devices that were discovered
                //arguably we should do this in the objectmanager added/removed events and skip the full
                //refresh, but I'm lazy.
                managedObjects = _objectManager.GetManagedObjects();
            }

            foreach (var obj in managedObjects.Keys)
            {
                if (obj.ToString().StartsWith(adapterPath.ToString()))
                {
                    if (managedObjects [obj].ContainsKey(typeof(Device1).DBusInterfaceName()))
                    {
                        var managedObject = managedObjects [obj];
                        if (managedObject [typeof(Device1).DBusInterfaceName()].ContainsKey("Name"))
                        {
                            var name = (string)managedObject [typeof(Device1).DBusInterfaceName()] ["Name"];
                            if (name.StartsWith("Pebble") && !name.Contains(" LE "))
                            {
                                var device = _connection.System.GetObject <Device1> (BlueZPath.Service, obj);
                                //we also check for the UUID because that's how we tell the
                                //LE address from the regular address

                                try
                                {
                                    System.Console.WriteLine("Attempting connection to " + obj);
                                    if (!device.Paired && pairDiscovered)
                                    {
                                        device.Pair();
                                    }
                                    if (!device.Trusted && pairDiscovered)
                                    {
                                        device.Trusted = true;
                                    }
                                    _pebbles [obj] = new DiscoveredPebble()
                                    {
                                        Name = name, Device = device
                                    };

                                    try
                                    {
                                        device.ConnectProfile(PebbleSerialUUID);
                                    }
                                    catch (Exception ex)
                                    {
                                        if (unpairFailed)
                                        {
                                            //this prevents us from falling into a failing loop
                                            //if the pebble has unpaired but bluez has not

                                            System.Console.WriteLine("Failed to connect to " + obj + ", attempting to re-pair");
                                            //if we can't connect then try to re-pair then reconnect
                                            _adapter.RemoveDevice(obj);

                                            if (pairDiscovered)
                                            {
                                                //re-discover
                                                if (!_adapter.Discovering)
                                                {
                                                    _adapter.StartDiscovery();
                                                }
                                                System.Threading.Thread.Sleep(10000);
                                                //re-pair
                                                device.Pair();
                                                device.Trusted = true;
                                                //re-connect
                                                device.ConnectProfile(PebbleSerialUUID);
                                            }
                                        }
                                        else
                                        {
                                            throw;
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    System.Console.WriteLine("Failed to connect to " + obj + " " + ex.Message);
                                    //we don't need to do anything, it simply won't be added to the collection if we can't connect to it
                                }
                            }
                        }
                        //if it doesn't have the Name Property we can safely assume it is not a pebble
                    }
                }
            }
            //wait for devices to connect
            Thread.Sleep(2000);

            var results = _pebbles.Values.Where(x => x.Pebble != null).Select(x => (Pebble)x.Pebble).ToList();

            return(results);
        }
Пример #2
0
        public override void Load()
        {
            Kernel.Bind <DBusConnection> ()
            .ToSelf()
            .InSingletonScope();

            Kernel.Bind <Adapter1> ()
            .ToMethod(x => {
                var adapterName = ConfigurationHelper.ReadStringAppSetting("BtAdapterName", "hci0");
                var connection  = x.Kernel.Get <DBusConnection> ();
                var adapter     = connection.System.GetObject <Adapter1>(BlueZPath.Service, BlueZPath.Adapter(adapterName));
                return(adapter);
            }).InSingletonScope();

            //we default to true so that it works "out of the box", but once your devices are paired you
            //could turn discovery off to speed up startup time
            var doDiscovery   = ConfigurationHelper.ReadBoolAppSetting("BtEnableDiscovery", true);
            var discoveryWait = ConfigurationHelper.ReadIntAppSetting("BtDiscoveryWait", 5);

            //HACK: very odd to be doing this sort of work in a DI module, but I don't have a better place right now
            if (doDiscovery)
            {
                StartDiscovery(discoveryWait);
            }
        }