diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Adapter.cs b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Adapter.cs index 62d9010..15156b8 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Adapter.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Adapter.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using Android.Bluetooth; using System.Threading.Tasks; +using Robotics.Mobile.Core.Bluetooth; +using System.Linq; namespace Robotics.Mobile.Core.Bluetooth.LE { @@ -61,7 +63,7 @@ public Adapter () } //TODO: scan for specific service type eg. HeartRateMonitor - public async void StartScanningForDevices (Guid serviceUuid) + public void StartScanningForDevices (Guid serviceUuid) { StartScanningForDevices (); // throw new NotImplementedException ("Not implemented on Android yet, look at _adapter.StartLeScan() overload"); @@ -105,11 +107,23 @@ public void OnLeScan (BluetoothDevice bleDevice, int rssi, byte[] scanRecord) // } Device device = new Device (bleDevice, null, null, rssi); - if (!DeviceExistsInDiscoveredList (bleDevice)) + if (!DeviceExistsInDiscoveredList (bleDevice)) { + this._discoveredDevices.Add (device); - // TODO: in the cross platform API, cache the RSSI - // TODO: shouldn't i only raise this if it's not already in the list? - this.DeviceDiscovered (this, new DeviceDiscoveredEventArgs { Device = device }); + + var parsedRecords = scanRecord; + + try { + + parsedRecords = scanRecord.Skip (34).Take (7).ToArray(); + + } catch (Exception) { + + } + + + this.DeviceDiscovered (this, new DeviceDiscoveredEventArgs { Device = device, RSSI = rssi, ScanRecords = parsedRecords }); + } } protected bool DeviceExistsInDiscoveredList(BluetoothDevice device) @@ -135,6 +149,7 @@ public void DisconnectDevice (IDevice device) ((Device) device).Disconnect(); } + } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Characteristic.cs b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Characteristic.cs index ecbe337..8592107 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Characteristic.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Characteristic.cs @@ -117,6 +117,27 @@ public void Write (byte[] data) Console.WriteLine(".....Write"); } + public async Task WriteAsync (byte[] data) + { + + var tcs = new TaskCompletionSource (); + + EventHandler writeSuccess = (sender, e) => tcs.TrySetResult(true); + + this._gattCallback.CharacteristicValueWritten += writeSuccess; + + Write (data); + + //timeout : 3 secondes + Task.Delay (3000).ContinueWith(t => tcs.TrySetResult(false)); + + var result = await tcs.Task; + + this._gattCallback.CharacteristicValueWritten -= writeSuccess; + + return result; + + } // HACK: UNTESTED - this API has only been tested on iOS diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Device.cs b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Device.cs index 0e8cb5a..84a7ff9 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Device.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/Device.cs @@ -34,12 +34,21 @@ public Device (BluetoothDevice nativeDevice, BluetoothGatt gatt, // when the services are discovered on the gatt callback, cache them here if (this._gattCallback != null) { this._gattCallback.ServicesDiscovered += (s, e) => { - var services = this._gatt.Services; this._services = new List (); - foreach (var item in services) { - this._services.Add (new Service (item, this._gatt, this._gattCallback)); - } - this.ServicesDiscovered (this, e); + + try{ + + var services = this._gatt.Services; + + foreach (var item in services) { + this._services.Add (new Service (item, this._gatt, this._gattCallback)); + } + this.ServicesDiscovered (this, e); + + } catch { + + } + }; } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/GattCallback.cs b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/GattCallback.cs index 8f6d8a6..dc9db0b 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/GattCallback.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Bluetooth/LE/GattCallback.cs @@ -1,5 +1,6 @@ using System; using Android.Bluetooth; +using System.Diagnostics; namespace Robotics.Mobile.Core.Bluetooth.LE { @@ -10,6 +11,7 @@ public class GattCallback : BluetoothGattCallback public event EventHandler DeviceDisconnected = delegate {}; public event EventHandler ServicesDiscovered = delegate {}; public event EventHandler CharacteristicValueUpdated = delegate {}; + public event EventHandler CharacteristicValueWritten = delegate {}; protected Adapter _adapter; @@ -70,10 +72,11 @@ public override void OnCharacteristicRead (BluetoothGatt gatt, BluetoothGattChar base.OnCharacteristicRead (gatt, characteristic, status); Console.WriteLine ("OnCharacteristicRead: " + characteristic.GetStringValue (0)); + var f = new CharacteristicReadEventArgs () { + Characteristic = new Characteristic (characteristic, gatt, this)}; + Debug.WriteLine ("OnCharacteristicRead" + f); - this.CharacteristicValueUpdated (this, new CharacteristicReadEventArgs () { - Characteristic = new Characteristic (characteristic, gatt, this) } - ); + this.CharacteristicValueUpdated (this, f); } public override void OnCharacteristicChanged (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) @@ -81,10 +84,22 @@ public override void OnCharacteristicChanged (BluetoothGatt gatt, BluetoothGattC base.OnCharacteristicChanged (gatt, characteristic); Console.WriteLine ("OnCharacteristicChanged: " + characteristic.GetStringValue (0)); + var f = new CharacteristicReadEventArgs () { + Characteristic = new Characteristic (characteristic, gatt, this)}; + Debug.WriteLine ("OnCharacteristicChanged" + f); - this.CharacteristicValueUpdated (this, new CharacteristicReadEventArgs () { - Characteristic = new Characteristic (characteristic, gatt, this) } - ); + this.CharacteristicValueUpdated (this, f); + } + + public override void OnCharacteristicWrite (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, GattStatus status) + { + base.OnCharacteristicWrite (gatt, characteristic, status); + + if (null != this.CharacteristicValueWritten) { + this.CharacteristicValueWritten(this, new CharacteristicReadEventArgs () { + Characteristic = new Characteristic (characteristic, gatt, this) } + ); + } } } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Robotics.Mobile.Core.Droid.csproj b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Robotics.Mobile.Core.Droid.csproj index 21019a3..753fc99 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Robotics.Mobile.Core.Droid.csproj +++ b/Source/Platform Stacks/Robotics.Mobile.Core.Droid/Robotics.Mobile.Core.Droid.csproj @@ -57,7 +57,6 @@ - @@ -68,4 +67,5 @@ Robotics.Mobile.Core + \ No newline at end of file diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Adapter.cs b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Adapter.cs index b3d4ebf..3079bdd 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Adapter.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Adapter.cs @@ -3,11 +3,16 @@ using System.Threading.Tasks; using System.Threading; using System.Diagnostics; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; #if __UNIFIED__ using CoreBluetooth; using CoreFoundation; +using Foundation; #else +using MonoTouch.Foundation; using MonoTouch.CoreBluetooth; using MonoTouch.CoreFoundation; #endif @@ -57,16 +62,57 @@ static Adapter () _current = new Adapter (); } - protected Adapter () + public Adapter () { this._central = new CBCentralManager (DispatchQueue.CurrentQueue); _central.DiscoveredPeripheral += (object sender, CBDiscoveredPeripheralEventArgs e) => { Console.WriteLine ("DiscoveredPeripheral: " + e.Peripheral.Name); - Device d = new Device(e.Peripheral); + + NSString localName = null; + + try { + localName = e.AdvertisementData[CBAdvertisement.DataLocalNameKey] as NSString; + } catch { + localName = new NSString(e.Peripheral.Name); + } + + Device d = new Device(e.Peripheral, localName); + if(!ContainsDevice(this._discoveredDevices, e.Peripheral ) ){ - this._discoveredDevices.Add (d); - this.DeviceDiscovered(this, new DeviceDiscoveredEventArgs() { Device = d }); + + byte[] scanRecord = null; + + + try { + + Console.WriteLine ("ScanRecords: " + e.AdvertisementData.ToString()); + + NSError error = null; + + var soft = Clean(e.AdvertisementData); + + Console.WriteLine ("ScanRecords cleaned: " + soft.ToString()); + + var binFormatter = new BinaryFormatter(); + var mStream = new MemoryStream(); + binFormatter.Serialize(mStream, soft); + + //This gives you the byte array. + + + + scanRecord = mStream.ToArray(); + + } catch (Exception exception) + { + Console.WriteLine ("ScanRecords to byte[] failed"); + } + finally { + this._discoveredDevices.Add (d); + this.DeviceDiscovered(this, new DeviceDiscoveredEventArgs() { Device = d, RSSI = (int)e.RSSI, ScanRecords = scanRecord }); + } + } }; @@ -112,6 +158,7 @@ protected Adapter () }); }; + } public void StartScanningForDevices () @@ -203,6 +250,52 @@ protected bool ContainsDevice(IEnumerable list, CBPeripheral device) } return false; } + + Dictionary Clean (NSDictionary dict) + { + var result = new Dictionary (); + + foreach (var item in dict.Keys) { + + var obj = dict [item]; + + // Si la clef est de type CBUUID, on utilisera l'id en NSString a la place + var itemAsCBUUID = item as CBUUID; + var key = itemAsCBUUID == null ? item.Description : itemAsCBUUID.Uuid; + + // La valeur doit etre transformée + object value = null; + + if (obj as NSDictionary != null) // Cas d'un NSDictionary... Recursivité + { + value = Clean (obj as NSDictionary); + } + else if (obj as NSData != null) // Cas d'un NSDictionary... Stringify + { + var data = obj as NSData; + + var networkBites = data.ToArray (); + + var str = BitConverter.ToString(networkBites).Replace("-",""); + + value = str; + + } + else if (obj as NSNull != null) // Cas d'un NSNull, on skip + { + // Do not... + + } else // Sinon on remet l'objet sous format string + { + value = obj.Description; + } + + result.Add (key, value); + + } + + return result; + } } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Characteristic.cs b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Characteristic.cs index 9829e74..7198356 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Characteristic.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Characteristic.cs @@ -130,6 +130,27 @@ public void Write (byte[] data) return; } + public async Task WriteAsync (byte[] data) + { + var tcs = new TaskCompletionSource (); + + EventHandler wroteCharacteristicValue = (sender, e) => tcs.TrySetResult(true); + + _parentDevice.WroteCharacteristicValue += wroteCharacteristicValue; + + Write (data); + + //timeout : 3 secondes + Task.Delay (3000).ContinueWith(t => tcs.TrySetResult(false)); + + var result = await tcs.Task; + + _parentDevice.WroteCharacteristicValue -= wroteCharacteristicValue; + + return result; + + } + public void StartUpdates () { // TODO: should be bool RequestValue? compare iOS API for commonality @@ -187,8 +208,6 @@ public static Guid CharacteristicUuidToGuid ( CBUUID uuid) } return Guid.ParseExact (id, "d"); } - - } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Device.cs b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Device.cs index e06ff84..5c9ddac 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Device.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Bluetooth/LE/Device.cs @@ -16,8 +16,9 @@ public class Device : DeviceBase public override event EventHandler ServicesDiscovered = delegate {}; protected CBPeripheral _nativeDevice; + - public Device (CBPeripheral nativeDevice) + public Device (CBPeripheral nativeDevice, NSString localName = null) { this._nativeDevice = nativeDevice; @@ -68,6 +69,10 @@ public Device (CBPeripheral nativeDevice) } } }; + + _name = localName == null ? _nativeDevice.Name : localName.ToString(); + + } public override Guid ID { @@ -82,12 +87,14 @@ public override Guid ID { } } + string _name; public override string Name { get { - return this._nativeDevice.Name; + return _name; } } + public override int Rssi { get { return this._rssi; diff --git a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Robotics.Mobile.Core.iOS.csproj b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Robotics.Mobile.Core.iOS.csproj index 646e1c9..526597c 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Robotics.Mobile.Core.iOS.csproj +++ b/Source/Platform Stacks/Robotics.Mobile.Core.iOS/Robotics.Mobile.Core.iOS.csproj @@ -41,7 +41,6 @@ - diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/AdElement.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/AdElement.cs new file mode 100644 index 0000000..163cb8c --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/AdElement.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment +{ + + + public class AdElement + { + private static char hexDigit(int v,int shift) { + int v1 = ( v >> shift ) & 0xF; + return hexDigits[v1]; + } + + public static String hex8(int v) { + return ""+ + hexDigit(v,4)+ + hexDigit(v,0); + } + + public static String hex16(int v) { + return ""+hexDigit(v,12)+ + hexDigit(v,8)+ + hexDigit(v,4)+ + hexDigit(v,0); + } + + public static String hex32(int v) { + return ""+hexDigit(v,28)+ + hexDigit(v,24)+ + hexDigit(v,20)+ + hexDigit(v,16)+ + hexDigit(v,12)+ + hexDigit(v,8)+ + hexDigit(v,4)+ + hexDigit(v,0); + } + + public static String uuid128(int v1,int v2,int v3,int v4) { + int v2h = ( v2 >> 16 ) & 0xFFFF; + int v2l = v2 & 0xFFFF; + int v3h = ( v3 >> 16 ) & 0xFFFF; + return ""+ + hex32(v1)+ + "-"+ + hex16(v2h)+ + "-"+ + hex16(v2l)+ + "-"+ + hex16(v3h)+ + "-"+ + hexDigit(v3,12)+ + hexDigit(v3,8)+ + hexDigit(v3,4)+ + hexDigit(v3,0)+ + hexDigit(v4,28)+ + hexDigit(v4,24)+ + hexDigit(v4,20)+ + hexDigit(v4,16)+ + hexDigit(v4,12)+ + hexDigit(v4,8)+ + hexDigit(v4,4)+ + hexDigit(v4,0); + } + + private static String hexDigits = "0123456789ABCDEF"; + } +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/AdParser.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/AdParser.cs new file mode 100644 index 0000000..4f6667c --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/AdParser.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment +{ + public static class AdParser + { + public static List ParseAdData (byte[] data) + { + int pos=0; + List result = new List(); + int dlen = data.Length; + while((pos+1) < dlen) { + int bpos = pos; + int blen = ((int)data[pos]) & 0xFF; + if( blen == 0 ) + break; + if( bpos+blen > dlen ) + break; + ++pos; + int type = ((int)data[pos]) & 0xFF; + ++pos; + int len = blen - 1; + AdElement e = null; + switch( type ) { + // Flags + case 0x01: +// e = new TypeFlags(data,pos); + break; + + // 16-bit UUIDs + case 0x02: + case 0x03: + case 0x14: + e = new Type16BitUUIDs( type,data,pos,len); + break; + // 32-bit UUIDs + case 0x04: + case 0x05: + e = new Type32BitUUIDs( type,data,pos,len); + break; + + // 128-bit UUIDs + case 0x06: + case 0x07: + case 0x15: + e = new Type128BitUUIDs( type,data,pos,len); + break; + + // Local name (short and long) + case 0x08: + case 0x09: + e = new TypeString(type,data,pos,len); + break; + + // TX Power Level + case 0x0A: +// e = new TypeTXPowerLevel(data,pos); + break; + + // Various not interpreted indicators (byte dump) + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + e = new TypeByteDump(type,data,pos,len); + break; + + // OOB Flags + case 0x11: +// e = new TypeSecOOBFlags(data,pos); + break; + + // Slave Connection Interval Range + case 0x12: +// e = new TypeSlaveConnectionIntervalRange(data,pos,len); + break; + + // Service data + case 0x16: +// e = new TypeServiceData(data,pos,len); + break; + + case 0xFF: +// e = new TypeManufacturerData(data,pos,len); + break; + + default: +// e = new TypeUnknown(type,data,pos,len); + break; + } + result.Add(e); + pos = bpos + blen+1; + } + return result; + } + + } +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type128BitUUIDs.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type128BitUUIDs.cs new file mode 100644 index 0000000..1de9963 --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type128BitUUIDs.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using Beerendonk.Java; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment +{ + public class Type128BitUUIDs : AdElement + { + public Type128BitUUIDs( int type, byte[] data, int pos, int len) { + this.Type = type; + int items = len / 16; + Uuids = new Uuid[items]; + int ptr = pos; + for( int i = 0 ; i < items ; ++i ) { + long vl = ((long)data[ptr]) & 0xFF; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 8; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 16; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 24; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 32; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 40; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 48; + ptr++; + vl |= (((long)data[ptr]) & 0xFF ) << 56; + ptr++; + long vh = ((long)data[ptr]) & 0xFF; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 8; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 16; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 24; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 32; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 40; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 48; + ptr++; + vh |= (((long)data[ptr]) & 0xFF ) << 56; + ptr++; + Uuids[i] = new Uuid(vh,vl); + } + } + + + public int Type { get ; private set ;} + public Uuid[] Uuids { get ; private set ;} + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type16BitUUIDs.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type16BitUUIDs.cs new file mode 100644 index 0000000..09f379e --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type16BitUUIDs.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment +{ + public class Type16BitUUIDs : AdElement + { + public Type16BitUUIDs( int type, byte[] data, int pos, int len) { + this.Type = type; + int items = len / 2; + Uuids = new int[items]; + int ptr = pos; + for( int i = 0 ; i < items ; ++i ) { + int v = ((int)data[ptr]) & 0xFF; + ptr++; + v |= (((int)data[ptr]) & 0xFF ) << 8; + ptr++; + Uuids[i] = v; + } + } + + public int Type { get ; private set ;} + public int[] Uuids { get ; private set ;} + + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type32BitUUIDs.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type32BitUUIDs.cs new file mode 100644 index 0000000..f14f299 --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Type32BitUUIDs.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + + + public class Type32BitUUIDs : AdElement + { + public Type32BitUUIDs( int type, byte[] data, int pos, int len) { + this.Type = type; + int items = len / 4; + Uuids = new int[items]; + int ptr = pos; + for( int i = 0 ; i < items ; ++i ) { + int v = ((int)data[ptr]) & 0xFF; + ptr++; + v |= (((int)data[ptr]) & 0xFF ) << 8; + ptr++; + v |= (((int)data[ptr]) & 0xFF ) << 16; + ptr++; + v |= (((int)data[ptr]) & 0xFF ) << 24; + ptr++; + Uuids[i] = v; + } + } + + + public int Type { get ; private set ;} + public int[] Uuids { get ; private set ;} + + } + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeByteDump.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeByteDump.cs new file mode 100644 index 0000000..fcb0991 --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeByteDump.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + + + public class TypeByteDump : AdElement + { + + public TypeByteDump( int type,byte[] data,int pos,int len) { + this.Type = type; + Value = new byte[len]; + } + + public byte[] Value { get ; private set ; } + public int Type { get ; private set ; } + + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeFlags.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeFlags.cs new file mode 100644 index 0000000..a8be85d --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeFlags.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + public class TypeFlags : AdElement + { + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeManufacturerData.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeManufacturerData.cs new file mode 100644 index 0000000..00fcc46 --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeManufacturerData.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + public class TypeManufacturerData : AdElement + { + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeSecOOBFlags.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeSecOOBFlags.cs new file mode 100644 index 0000000..f12787f --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeSecOOBFlags.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + public class TypeSecOOBFlags : AdElement + { + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeSlaveConnectionIntervalRange.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeSlaveConnectionIntervalRange.cs new file mode 100644 index 0000000..149b9bb --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeSlaveConnectionIntervalRange.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + public class TypeSlaveConnectionIntervalRange : AdElement + { + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeString.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeString.cs new file mode 100644 index 0000000..75f114c --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeString.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + + + public class TypeString : AdElement + { + public TypeString( int type, byte[] data, int pos, int len) { + this.Type = type; + int ptr = pos; + byte[] sb = new byte[len]; + + Value = BitConverter.ToString(sb); + } + + public int Type { get ; private set ; } + public string Value { get ; private set ; } + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeTXPowerLevel.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeTXPowerLevel.cs new file mode 100644 index 0000000..74a137e --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeTXPowerLevel.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment{ + public class TypeTXPowerLevel : AdElement + { + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeUnknown.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeUnknown.cs new file mode 100644 index 0000000..5447a85 --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/TypeUnknown.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Robotics.Mobile.Core.Bluetooth.Advertisment +{ + public class TypeUnknown : AdElement + { + } + + + +} + diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Uuid.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Uuid.cs new file mode 100644 index 0000000..7759b17 --- /dev/null +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/Advertisement/Uuid.cs @@ -0,0 +1,220 @@ +// Copyright © 2014 Rick Beerendonk. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Beerendonk.Java +{ + /// + /// Represents an immutable Java universally unique identifier (UUID). + /// A UUID represents a 128-bit value. + /// + public struct Uuid : IEquatable + { + private readonly long leastSignificantBits; + private readonly long mostSignificantBits; + + /// + /// Constructs a new UUID using the specified data. + /// + /// The most significant 64 bits of the UUID. + /// The least significant 64 bits of the UUID + public Uuid(long mostSignificantBits, long leastSignificantBits) + { + this.mostSignificantBits = mostSignificantBits; + this.leastSignificantBits = leastSignificantBits; + } + + /// + /// The least significant 64 bits of this UUID's 128 bit value. + /// + public long LeastSignificantBits + { + get { return leastSignificantBits; } + } + + /// + /// The most significant 64 bits of this UUID's 128 bit value. + /// + public long MostSignificantBits + { + get { return mostSignificantBits; } + } + + /// + /// Returns a value that indicates whether this instance is equal to a specified + /// object. + /// + /// The object to compare with this instance. + /// true if o is a that has the same value as this instance; otherwise, false. + public override bool Equals(object obj) + { + if (obj == null || !(obj is Uuid)) + { + return false; + } + + Uuid uuid = (Uuid)obj; + + return Equals(uuid); + } + + /// + /// Returns a value that indicates whether this instance and a specified + /// object represent the same value. + /// + /// An object to compare to this instance. + /// true if is equal to this instance; otherwise, false. + public bool Equals(Uuid uuid) + { + return this.mostSignificantBits == uuid.mostSignificantBits && this.leastSignificantBits == uuid.leastSignificantBits; + } + + /// + /// Returns the hash code for this instance. + /// + /// The hash code for this instance. + public override int GetHashCode() + { + return ((Guid)this).GetHashCode(); + } + + /// + /// + /// Returns a String object representing this UUID. + /// + /// + /// The UUID string representation is as described by this BNF: + /// + /// + /// UUID = "-" "-" + /// "-" + /// "-" + /// + /// time_low = 4* + /// time_mid = 2* + /// time_high_and_version = 2* + /// variant_and_sequence = 2* + /// node = 6* + /// hexOctet = + /// hexDigit = + /// "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + /// | "a" | "b" | "c" | "d" | "e" | "f" + /// | "A" | "B" | "C" | "D" | "E" | "F" + /// + /// + /// A string representation of this UUID. + public override string ToString() + { + return ((Guid)this).ToString(); + } + + /// Indicates whether the values of two specified objects are equal. + /// true if and are equal; otherwise, false. + /// The first object to compare. + /// The second object to compare. + public static bool operator ==(Uuid a, Uuid b) + { + return a.Equals(b); + } + + /// Indicates whether the values of two specified objects are not equal. + /// true if and are not equal; otherwise, false. + /// The first object to compare. + /// The second object to compare. + public static bool operator !=(Uuid a, Uuid b) + { + return !a.Equals(b); + } + + /// Converts an to a . + /// The value to convert. + /// A that represents the converted . + public static explicit operator Guid(Uuid uuid) + { + if (uuid == default(Uuid)) + { + return default(Guid); + } + + byte[] uuidMostSignificantBytes = BitConverter.GetBytes(uuid.mostSignificantBits); + byte[] uuidLeastSignificantBytes = BitConverter.GetBytes(uuid.leastSignificantBits); + byte[] guidBytes = new byte[16] { + uuidMostSignificantBytes[4], + uuidMostSignificantBytes[5], + uuidMostSignificantBytes[6], + uuidMostSignificantBytes[7], + uuidMostSignificantBytes[2], + uuidMostSignificantBytes[3], + uuidMostSignificantBytes[0], + uuidMostSignificantBytes[1], + uuidLeastSignificantBytes[7], + uuidLeastSignificantBytes[6], + uuidLeastSignificantBytes[5], + uuidLeastSignificantBytes[4], + uuidLeastSignificantBytes[3], + uuidLeastSignificantBytes[2], + uuidLeastSignificantBytes[1], + uuidLeastSignificantBytes[0] + }; + + return new Guid(guidBytes); + } + + /// Converts a to an . + /// The value to convert. + /// An that represents the converted . + public static implicit operator Uuid(Guid value) + { + if (value == default(Guid)) + { + return default(Uuid); + } + + byte[] guidBytes = value.ToByteArray(); + byte[] uuidBytes = new byte[16] { + guidBytes[6], + guidBytes[7], + guidBytes[4], + guidBytes[5], + guidBytes[0], + guidBytes[1], + guidBytes[2], + guidBytes[3], + guidBytes[15], + guidBytes[14], + guidBytes[13], + guidBytes[12], + guidBytes[11], + guidBytes[10], + guidBytes[9], + guidBytes[8] + }; + + return new Uuid(BitConverter.ToInt64(uuidBytes, 0), BitConverter.ToInt64(uuidBytes, 8)); + } + + /// + /// Creates a UUID from the string standard representation as described in the method. + /// + /// A string that specifies a UUID. + /// A UUID with the specified value. + /// input is null. + /// input is not in a recognized format. + public static Uuid FromString(string input) + { + return (Uuid)Guid.Parse(input); + } + } +} \ No newline at end of file diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/CharacteristicReadEventArgs.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/CharacteristicReadEventArgs.cs index c0290b1..d958ed6 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/CharacteristicReadEventArgs.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/CharacteristicReadEventArgs.cs @@ -9,6 +9,24 @@ public class CharacteristicReadEventArgs : EventArgs public CharacteristicReadEventArgs () { } + + public override string ToString () + { + if (this.Characteristic == null) + return string.Format ("[CharacteristicReadEventArgs]"); + string bytes = "["; + if (this.Characteristic != null && this.Characteristic.Value != null) { + foreach (var b in this.Characteristic.Value) { + bytes += b + ","; + } + } + if (bytes.Length > 1) + bytes = bytes.Substring (0, bytes.Length - 1) + "]"; + else + bytes += "]"; + + return string.Format ("[CharacteristicReadEventArgs: Id={0}, bytes:{1}]", this.Characteristic.ID, bytes); + } } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/DeviceDiscoveredEventArgs.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/DeviceDiscoveredEventArgs.cs index 459e4f6..3f0fa9e 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/DeviceDiscoveredEventArgs.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/DeviceDiscoveredEventArgs.cs @@ -4,7 +4,11 @@ namespace Robotics.Mobile.Core.Bluetooth.LE { public class DeviceDiscoveredEventArgs : EventArgs { - public IDevice Device; + public IDevice Device { get ; set ;} + + public int RSSI { get ; set ;} + + public byte[] ScanRecords { get ; set ; } public DeviceDiscoveredEventArgs() : base() {} diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/ICharacteristic.cs b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/ICharacteristic.cs index d60a3dd..140e754 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/ICharacteristic.cs +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Bluetooth/LE/ICharacteristic.cs @@ -33,6 +33,14 @@ public interface ICharacteristic void Write (byte[] data); + /// + /// Write a chunck of data to the property and wait for the device callback before returning + /// + /// returns yes if the write as been succesfully done + /// Data. + /// TODO: Maybe add a timeout + Task WriteAsync(byte[] data); + } } diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/Robotics.Mobile.Core.csproj b/Source/Platform Stacks/Robotics.Mobile.Core/Robotics.Mobile.Core.csproj index b917abc..642644b 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core/Robotics.Mobile.Core.csproj +++ b/Source/Platform Stacks/Robotics.Mobile.Core/Robotics.Mobile.Core.csproj @@ -72,7 +72,7 @@ - ..\packages\Newtonsoft.Json.6.0.5\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll + ..\..\..\..\smartkit-demo\packages\Newtonsoft.Json.7.0.1\lib\portable-net45+wp80+win8+wpa81+dnxcore50\Newtonsoft.Json.dll \ No newline at end of file diff --git a/Source/Platform Stacks/Robotics.Mobile.Core/packages.config b/Source/Platform Stacks/Robotics.Mobile.Core/packages.config index 023f01d..3632fbf 100644 --- a/Source/Platform Stacks/Robotics.Mobile.Core/packages.config +++ b/Source/Platform Stacks/Robotics.Mobile.Core/packages.config @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file