Skip to content
This repository has been archived by the owner on Jun 19, 2024. It is now read-only.

Provide access to the RSSI value on device discovery #52

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand All @@ -135,6 +149,7 @@ public void DisconnectDevice (IDevice device)
((Device) device).Disconnect();
}


}
}

Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ public void Write (byte[] data)
Console.WriteLine(".....Write");
}

public async Task<bool> WriteAsync (byte[] data)
{

var tcs = new TaskCompletionSource<bool> ();

EventHandler<CharacteristicReadEventArgs> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<IService> ();
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 {

}

};
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Android.Bluetooth;
using System.Diagnostics;

namespace Robotics.Mobile.Core.Bluetooth.LE
{
Expand All @@ -10,6 +11,7 @@ public class GattCallback : BluetoothGattCallback
public event EventHandler<DeviceConnectionEventArgs> DeviceDisconnected = delegate {};
public event EventHandler<ServicesDiscoveredEventArgs> ServicesDiscovered = delegate {};
public event EventHandler<CharacteristicReadEventArgs> CharacteristicValueUpdated = delegate {};
public event EventHandler<CharacteristicReadEventArgs> CharacteristicValueWritten = delegate {};

protected Adapter _adapter;

Expand Down Expand Up @@ -70,21 +72,34 @@ 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)
{
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) }
);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
<ItemGroup>
<AndroidResource Include="Resources\values\Strings.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<ItemGroup>
<Folder Include="Bluetooth\" />
<Folder Include="Bluetooth\LE\" />
Expand All @@ -68,4 +67,5 @@
<Name>Robotics.Mobile.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 });
}

}
};

Expand Down Expand Up @@ -112,6 +158,7 @@ protected Adapter ()
});
};


}

public void StartScanningForDevices ()
Expand Down Expand Up @@ -203,6 +250,52 @@ protected bool ContainsDevice(IEnumerable<IDevice> list, CBPeripheral device)
}
return false;
}

Dictionary<string, object> Clean (NSDictionary dict)
{
var result = new Dictionary<string, object> ();

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;
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,27 @@ public void Write (byte[] data)
return;
}

public async Task<bool> WriteAsync (byte[] data)
{
var tcs = new TaskCompletionSource<bool> ();

EventHandler<CBCharacteristicEventArgs> 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
Expand Down Expand Up @@ -187,8 +208,6 @@ public static Guid CharacteristicUuidToGuid ( CBUUID uuid)
}
return Guid.ParseExact (id, "d");
}


}
}

Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -68,6 +69,10 @@ public Device (CBPeripheral nativeDevice)
}
}
};

_name = localName == null ? _nativeDevice.Name : localName.ToString();


}

public override Guid ID {
Expand All @@ -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;
Expand Down
Loading