public void Run() { //string serviceUUID="713d0000-503e-4c75-ba94-3148f18d941e"; //string charVendorName = "713D0001-503E-4C75-BA94-3148F18D941E"; //string charRead = "713D0002-503E-4C75-BA94-3148F18D941E";//rx //string charWrite = "713D0003-503E-4C75-BA94-3148F18D941E";//tx //string charAck = "713D0004-503E-4C75-BA94-3148F18D941E"; //string charVersion = "713D0005-503E-4C75-BA94-3148F18D941E"; //string clientCharacteristic = "00002902-0000-1000-8000-00805f9b34fb"; System.Console.WriteLine("Starting Blend Micro Bootstrap"); string Service = "org.bluez"; //Important!: there is a flaw in dbus-sharp such that you can only register one interface //at each path, so we have to put these at 2 seperate paths, otherwise I'd probably just put them //both at root var agentPath = new ObjectPath("/agent"); var gattProfilePath = new ObjectPath("/gattprofiles"); var blueZPath = new ObjectPath("/org/bluez"); //get a copy of the object manager so we can browse the "tree" of bluetooth items var manager = GetObject <org.freedesktop.DBus.ObjectManager> (Service, ObjectPath.Root); //register these events so we can tell when things are added/removed (eg: discovery) manager.InterfacesAdded += (p, i) => { System.Console.WriteLine(p + " Discovered"); }; manager.InterfacesRemoved += (p, i) => { System.Console.WriteLine(p + " Lost"); }; System.Console.WriteLine("Registring agent"); //get the agent manager so we can register our agent var agentManager = GetObject <AgentManager1> (Service, blueZPath); var agent = new DemoAgent(); GattManager1 gattManager = null; //register our agent and make it the default _system.Register(agentPath, agent); agentManager.RegisterAgent(agentPath, "KeyboardDisplay"); agentManager.RequestDefaultAgent(agentPath); var devices = new List <Device1> (); try { System.Console.WriteLine("Fetching objects"); //get the bluetooth object tree var managedObjects = manager.GetManagedObjects(); //find our adapter ObjectPath adapterPath = null; foreach (var obj in managedObjects.Keys) { System.Console.WriteLine("Checking " + obj); if (managedObjects [obj].ContainsKey(typeof(LEAdvertisingManager1).DBusInterfaceName())) { System.Console.WriteLine("Adapter found at" + obj + " that supports LE"); adapterPath = obj; break; } } if (adapterPath == null) { System.Console.WriteLine("Couldn't find adapter that supports LE"); return; } //get a dbus proxy to the adapter var adapter = GetObject <Adapter1> (Service, adapterPath); gattManager = GetObject <GattManager1>(Service, adapterPath); var gattProfile = new BlendGattProfile(); _system.Register(gattProfilePath, gattProfile); gattManager.RegisterApplication(gattProfilePath, new Dictionary <string, object>()); System.Console.WriteLine("Registered gatt profile"); //assume discovery for ble //scan for any new devices System.Console.WriteLine("Starting LE Discovery..."); var discoveryProperties = new Dictionary <string, object>(); discoveryProperties["Transport"] = "le"; adapter.SetDiscoveryFilter(discoveryProperties); 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. System.Console.WriteLine("Discovery complete, refreshing"); managedObjects = manager.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("MrGibbs")) { System.Console.WriteLine("Device " + name + " at " + obj); var device = _system.GetObject <Device1> (Service, obj); var uuids = device.UUIDs; foreach (var uuid in device.UUIDs) { System.Console.WriteLine("\tUUID: " + uuid); } devices.Add(device); } } } } } var readCharPath = new ObjectPath("/org/bluez/hci0/dev_F6_58_7F_09_5D_E6/service000c/char000f"); var readChar = GetObject <GattCharacteristic1>(Service, readCharPath); var properties = GetObject <Properties>(Service, readCharPath); properties.PropertiesChanged += new PropertiesChangedHandler( new Action <string, IDictionary <string, object>, string[]>((@interface, changed, invalidated) => { System.Console.WriteLine("Properties Changed on " + @interface); if (changed != null) { foreach (var prop in changed.Keys) { if (changed[prop] is byte[]) { foreach (var b in ((byte[])changed[prop])) { System.Console.Write(b + ","); } System.Console.WriteLine(""); } else { System.Console.WriteLine("{0}={1}", prop, changed[prop]); } } } if (invalidated != null) { foreach (var prop in invalidated) { System.Console.WriteLine(prop + " Invalidated"); } } })); foreach (var device in devices) { System.Console.WriteLine("Connecting to " + device.Name); device.Connect(); System.Console.WriteLine("\tConnected"); } readChar.StartNotify(); System.Threading.Thread.Sleep(10000); readChar.StopNotify(); System.Threading.Thread.Sleep(500); } finally { if (devices != null) { foreach (var device in devices) { System.Console.WriteLine("Disconnecting " + device.Name); device.Disconnect(); System.Console.WriteLine("\tDisconnected"); } } agentManager.UnregisterAgent(agentPath); gattManager.UnregisterApplication(gattProfilePath); } }
public void Run(bool doDiscovery, string adapterName) { var devices = new List <Pebble> (); string Service = "org.bluez"; //Important!: there is a flaw in dbus-sharp such that you can only register one interface //at each path, so we have to put these at 2 seperate paths, otherwise I'd probably just put them //both at root var agentPath = new ObjectPath("/agent"); var profilePath = new ObjectPath("/profiles"); var blueZPath = new ObjectPath("/org/bluez"); //still don't really understand this. The pebble advertises this uuid, //and this is what works, but all my reading tells me that the uuid for the //serial service should be the 2nd one string pebbleSerialUUID = "00000000-deca-fade-deca-deafdecacaff"; //string serialServiceUUID = "00001101-0000-1000-8000-00805F9B34FB"; //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)1; //get a proxy for the profile manager so we can register our profile var profileManager = GetObject <ProfileManager1> (Service, blueZPath); //create and register our profile var profile = new DemoProfile(); _system.Register(profilePath, profile); profileManager.RegisterProfile(profilePath , pebbleSerialUUID , properties); System.Console.WriteLine("Registered profile with BlueZ"); //get a copy of the object manager so we can browse the "tree" of bluetooth items var manager = GetObject <org.freedesktop.DBus.ObjectManager> (Service, ObjectPath.Root); //register these events so we can tell when things are added/removed (eg: discovery) manager.InterfacesAdded += (p, i) => { System.Console.WriteLine(p + " Discovered"); }; manager.InterfacesRemoved += (p, i) => { System.Console.WriteLine(p + " Lost"); }; //get the agent manager so we can register our agent var agentManager = GetObject <AgentManager1> (Service, blueZPath); var agent = new DemoAgent(); //register our agent and make it the default _system.Register(agentPath, agent); agentManager.RegisterAgent(agentPath, "KeyboardDisplay"); agentManager.RequestDefaultAgent(agentPath); try { //get the bluetooth object tree var managedObjects = manager.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)) { System.Console.WriteLine("Adapter found at" + obj); adapterPath = obj; break; } } } if (adapterPath == null) { System.Console.WriteLine("Couldn't find adapter " + adapterName); return; } //get a dbus proxy to the adapter var adapter = GetObject <Adapter1> (Service, adapterPath); if (doDiscovery) { //scan for any new devices System.Console.WriteLine("Starting Discovery..."); 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 = manager.GetManagedObjects(); } foreach (var obj in managedObjects.Keys) { if (obj.ToString().StartsWith(adapterPath.ToString())) { if (managedObjects [obj].ContainsKey(typeof(Device1).DBusInterfaceName())) { var managedObject = managedObjects [obj]; var name = (string)managedObject[typeof(Device1).DBusInterfaceName()]["Name"]; if (name.StartsWith("Pebble")) { System.Console.WriteLine("Device " + name + " at " + obj); var device = _system.GetObject <Device1> (Service, obj); devices.Add(new Pebble() { Name = name, Device = device, Path = obj }); if (!device.Paired) { System.Console.WriteLine(name + " not paired, attempting to pair"); device.Pair(); System.Console.WriteLine("Paired"); } if (!device.Trusted) { System.Console.WriteLine(name + " not trust, attempting to trust"); device.Trusted = true; System.Console.WriteLine("Trusted"); } } } } } profile.NewConnectionAction = (path, fd, props) => { var pebble = devices.Single(x => x.Path == path); System.Console.WriteLine("Received FD " + fd + " for " + pebble.Name); fd.SetBlocking(); System.Console.WriteLine(props.Count + " properties"); foreach (var k in props.Keys) { System.Console.WriteLine(k + ":" + props[k]); } pebble.FileDescriptor = fd; pebble.Stream = fd.OpenAsStream(true); System.Console.WriteLine("Saying Hello..."); var pebbleHello = PebbleHello(); pebble.Stream.Write(pebbleHello, 0, pebbleHello.Length); pebble.Stream.Flush(); }; foreach (var device in devices) { try{ System.Console.WriteLine("Attempting Connection to " + device.Name); System.Console.WriteLine("Paired:" + device.Device.Paired.ToString()); System.Console.WriteLine("Trusted:" + device.Device.Trusted.ToString()); System.Console.WriteLine("UUIDs:"); foreach (var uuid in device.Device.UUIDs) { System.Console.WriteLine(uuid); } System.Console.WriteLine("Connecting..."); device.Device.ConnectProfile(pebbleSerialUUID); System.Console.WriteLine("Connected"); } catch (Exception ex) { System.Console.WriteLine("Bootstrap handler"); System.Console.WriteLine(ex.Message); System.Console.WriteLine(ex.StackTrace); } } while (true) { byte[] buffer = new byte[72]; foreach (var pebble in devices) { int count = pebble.Stream.Read(buffer, 0, 72); System.Console.WriteLine("Received data from " + pebble.Name); string read = System.Text.ASCIIEncoding.ASCII.GetString(buffer); System.Console.WriteLine(read); } } } finally { foreach (var pebble in devices) { System.Console.WriteLine("Shutting down " + pebble.Name); try{ System.Console.WriteLine("Closing FD"); pebble.FileDescriptor.Close(); }catch {} try{ System.Console.WriteLine("Disconnecting"); pebble.Device.Disconnect(); }catch {} } agentManager.UnregisterAgent(agentPath); profileManager.UnregisterProfile(profilePath); } }