Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interfaces #13

Open
wants to merge 9 commits into
base: develop
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
9 changes: 6 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,19 @@ Android 12 and above
Set in your `.appxmanifest` file

```xml
<DeviceCapability Name="bluetooth" />
<DeviceCapability Name="bluetooth"/>
<DeviceCapability Name="location"/>
```

### iOS

```xml
<key>UIBackgroundModes</key>
<array>
<!-- for connecting to devices (client) -->
<!-- For connecting to devices (client) -->
<string>bluetooth-central</string>

<!-- for server configurations if needed -->
<!-- For server configurations (if needed) -->
<string>bluetooth-peripheral</string>
</array>

Expand All @@ -68,3 +69,5 @@ Set in your `.appxmanifest` file
### Linux

_Coming soon._

Until then check out the [Plugin.BlueZ](https://github.com/SuessLabs/Plugin.BlueZ) NuGet package for .NET Linux Bluetooth LE.
33 changes: 27 additions & 6 deletions source/Cross.BluetoothLe/Cross.BluetoothLe.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,41 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageId>Cross.BluetoothLe</PackageId>
<PackageTags>BluetoothLe xamarin mac ios android uwp wpf netcore dotnet tizen tvos watchos</PackageTags>
<Authors>Suess Labs</Authors>
<Copyright>Copyright © 2022 Xeno Innovations, Inc.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Description>Cross-platform Bluetooth Low Energy library, based on Plugin.BLE, for Xamarin.iOS, Xamarin.Android, Mac, UWP(Preview), .Net Core 3.x, Net5.x and .Net Framework 4.6.1+(Preview - Windows 10 only - WPF and Windows.Forms), TVOS(Preview) and WatchOS(Preview), Tizen(coming soon)</Description>
<AssemblyName>Cross.BluetoothLe</AssemblyName>
<SignAssembly>False</SignAssembly>
<RepositoryUrl>https://github.com/SuessLabs/Cross.BluetoothLe</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/SuessLabs/Cross.BluetoothLe</PackageProjectUrl>
<PackageReadmeFile>readme.md</PackageReadmeFile>
<PackageReleaseNotes>
[1.1]
- Drop
- Reintroduced interfaces for cleaner dependency injection

[1.0]
- Added NET 5.x support
- Update windows API to 10.0.19041
</PackageReleaseNotes>
<PackageReadmeFile>readme.md</PackageReadmeFile>
<PackageTags>BluetoothLe xamarin mac ios android uwp wpf netcore dotnet tizen tvos watchos</PackageTags>
<Copyright>Copyright © 2022 Xeno Innovations, Inc.</Copyright>
</PackageReleaseNotes>
</PropertyGroup>

<!--<PropertyGroup>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-ios'))">10.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-tvos'))">10.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-maccatalyst'))">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-macos'))">10.14</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-android'))">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-windows10'))">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$(TargetFramework.Contains('-windows10'))">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>-->

<PropertyGroup Condition=" '$(Configuration)'=='Debug' ">
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)'=='Release' And '$(OS)' == 'Windows_NT' ">
<!-- sourcelink: Declare that the Repository URL can be published to NuSpec -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand All @@ -44,9 +56,11 @@
<!-- sourcelink: Include PDB in the built .nupkg -->
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>

<ItemGroup Condition=" '$(Configuration)'=='Release' And '$(OS)' == 'Windows_NT' ">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\readme.md" Pack="true" PackagePath="\" />
<Compile Include="**\*.shared.cs" />
Expand All @@ -68,7 +82,11 @@
<PropertyGroup Condition=" $(TargetFramework.StartsWith('net5.0-windows10')) ">
<UseWPF>true</UseWPF>
</PropertyGroup>


<PropertyGroup Condition=" $(TargetFramework.StartsWith('net6.0-windows10')) ">
<UseWPF>true</UseWPF>
</PropertyGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('netcoreapp')) ">
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.17763.1000" />
<Compile Include="**\*.netcore.cs" />
Expand Down Expand Up @@ -115,4 +133,7 @@
<Compile Include="**\*.tizen.cs" />
<Compile Include="**\*.tizen.*.cs" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Platform\Base\IDevice.shared.cs" />
</ItemGroup>
</Project>
12 changes: 5 additions & 7 deletions source/Cross.BluetoothLe/Platform/Android/Adapter.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,16 @@ protected void DisconnectDeviceNative(Device device)
((Device)device).Disconnect();
}

public async Task<Device> ConnectToKnownDeviceAsync(Guid deviceGuid, ConnectParameters connectParameters = default(ConnectParameters), CancellationToken cancellationToken = default(CancellationToken), bool dontThrowExceptionOnNotFound = false)
public async Task<Device> ConnectToKnownDeviceAsync(
Guid deviceGuid,
ConnectParameters connectParameters = default(ConnectParameters),
CancellationToken cancellationToken = default(CancellationToken))
{
var macBytes = deviceGuid.ToByteArray().Skip(10).Take(6).ToArray();
var nativeDevice = _bluetoothAdapter.GetRemoteDevice(macBytes);

if (nativeDevice == null)
{
if (dontThrowExceptionOnNotFound == true)
return null;

if (nativeDevice is null)
throw new DeviceNotFoundException(deviceGuid);
}

var device = new Device(this, nativeDevice, null, 0, new byte[] { });

Expand Down
11 changes: 6 additions & 5 deletions source/Cross.BluetoothLe/Platform/Base/Adapter.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Cross.BluetoothLe
{
public partial class Adapter // : IAdapter
public partial class Adapter //// : IAdapter
{
private CancellationTokenSource _scanCancellationTokenSource;
private volatile bool _isScanning;
Expand All @@ -29,13 +29,18 @@ public partial class Adapter // : IAdapter

public event EventHandler ScanTimeoutElapsed;

public Adapter()
{
}

public bool IsScanning
{
get => _isScanning;
private set => _isScanning = value;
}

public int ScanTimeout { get; set; } = 10000;

public ScanMode ScanMode { get; set; } = ScanMode.LowPower;

protected ConcurrentDictionary<Guid, Device> DiscoveredDevicesRegistry { get; } = new ConcurrentDictionary<Guid, Device>();
Expand Down Expand Up @@ -238,9 +243,5 @@ public void HandleConnectionFail(Device device, string errorMessage)
ErrorMessage = errorMessage
});
}

public Adapter()
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,88 +2,74 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.BluetoothLe.EventArgs;
using Cross.BluetoothLe.EventArgs;

namespace Cross.BluetoothLe
{
/// <summary>
/// The bluetooth LE Adapter.
/// </summary>
/// <summary>The bluetooth LE Adapter.</summary>
public interface IAdapter
{
/// <summary>
/// Occurs when the adapter receives an advertisement.
/// </summary>
/// <summary>Occurs when the adapter receives an advertisement.</summary>
event EventHandler<DeviceEventArgs> DeviceAdvertised;

/// <summary>
/// Occurs when the adapter receives an advertisement for the first time of the current scan run.
/// This means once per every <see cref="StartScanningForDevicesAsync(Guid[], Func&lt;Device, bool&gt;, CancellationToken)"/> call.
/// Occurs when the adapter receives an advertisement for the first time of the current scan run.
/// This means once per every <see cref="StartScanningForDevicesAsync(Guid[], Func&lt;Device, bool&gt;, CancellationToken)"/> call.
/// </summary>
event EventHandler<DeviceEventArgs> DeviceDiscovered;
/// <summary>
/// Occurs when a device has been connected.
/// </summary>

/// <summary>Occurs when a device has been connected.</summary>
event EventHandler<DeviceEventArgs> DeviceConnected;
/// <summary>
/// Occurs when a device has been disconnected. This occurs on intended disconnects after <see cref="DisconnectDeviceAsync"/>.
/// </summary>

/// <summary>Occurs when a device has been disconnected. This occurs on intended disconnects after <see cref="DisconnectDeviceAsync"/>.</summary>
event EventHandler<DeviceEventArgs> DeviceDisconnected;
/// <summary>
/// Occurs when a device has been disconnected. This occurs on unintended disconnects (e.g. when the device exploded).
/// </summary>

/// <summary>Occurs when a device has been disconnected. This occurs on unintended disconnects (e.g. when the device exploded).</summary>
event EventHandler<DeviceErrorEventArgs> DeviceConnectionLost;
/// <summary>
/// Occurs when the scan has been stopped due the timeout after <see cref="ScanTimeout"/> ms.
/// </summary>

/// <summary>Occurs when the scan has been stopped due the timeout after <see cref="ScanTimeout"/> ms.</summary>
event EventHandler ScanTimeoutElapsed;

/// <summary>
/// Indicates, if the adapter is scanning for devices.
/// </summary>
/// <summary>Indicates, if the adapter is scanning for devices.</summary>
bool IsScanning { get; }

/// <summary>
/// Timeout for Ble scanning. Default is 10000.
/// </summary>
/// <summary>Timeout for Ble scanning. Default is 10000.</summary>
int ScanTimeout { get; set; }

/// <summary>
/// Specifies the scanning mode. Must be set before calling StartScanningForDevicesAsync().
/// Changing it while scanning, will have no change the current scan behavior.
/// Default: <see cref="ScanMode.LowPower"/>
/// Specifies the scanning mode. Must be set before calling StartScanningForDevicesAsync().
/// Changing it while scanning, will have no change the current scan behavior.
/// Default: <see cref="ScanMode.LowPower"/>
/// </summary>
ScanMode ScanMode { get; set; }

/// <summary>
/// List of last discovered devices.
/// </summary>
/// <summary>List of last discovered devices.</summary>
IReadOnlyList<Device> DiscoveredDevices { get; }

/// <summary>
/// List of currently connected devices.
/// </summary>
/// <summary>List of currently connected devices.</summary>
IReadOnlyList<Device> ConnectedDevices { get; }
////IReadOnlyList<IDevice> ConnectedDevices { get; }

/// <summary>
/// Starts scanning for BLE devices that fulfill the <paramref name="deviceFilter"/>.
/// DeviceDiscovered will only be called, if <paramref name="deviceFilter"/> returns <c>true</c> for the discovered device.
/// Starts scanning for BLE devices that fulfill the <paramref name="deviceFilter"/>.
/// DeviceDiscovered will only be called, if <paramref name="deviceFilter"/> returns <c>true</c> for the discovered device.
/// </summary>
/// <param name="serviceUuids">Requested service Ids. The default is null.</param>
/// <param name="deviceFilter">Function that filters the devices. The default is a function that returns true.</param>
/// <param name="allowDuplicatesKey"> iOS only: If true, filtering is disabled and a discovery event is generated each time the central receives an advertising packet from the peripheral.
/// Disabling this filtering can have an adverse effect on battery life and should be used only if necessary.
/// If false, multiple discoveries of the same peripheral are coalesced into a single discovery event.
/// If the key is not specified, the default value is false.
/// For android, key is ignored.</param>
/// <param name="allowDuplicatesKey"> iOS only: If true, filtering is disabled and a discovery event is generated each time the central receives an advertising packet from the peripheral.
/// Disabling this filtering can have an adverse effect on battery life and should be used only if necessary.
/// If false, multiple discoveries of the same peripheral are coalesced into a single discovery event.
/// If the key is not specified, the default value is false.
/// For android, key is ignored.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is None.</param>
/// <returns>A task that represents the asynchronous read operation. The Task will finish after the scan has ended.</returns>
Task StartScanningForDevicesAsync(Guid[] serviceUuids = null, Func<Device, bool> deviceFilter = null, bool allowDuplicatesKey = false, CancellationToken cancellationToken = default);

/// <summary>
/// Stops scanning for BLE devices.
/// </summary>
////Task ScanStartAsync(Guid[] serviceUuids = null, Func<Device, bool> deviceFilter = null, bool allowDuplicatesKey = false, CancellationToken cancellationToken = default);

/// <summary>Stops scanning for BLE devices.</summary>
/// <returns>A task that represents the asynchronous read operation. The Task will finish after the scan has ended.</returns>
Task StopScanningForDevicesAsync();
////Task ScanStopAsync();

/// <summary>
/// Connects to the <paramref name="device"/>.
Expand All @@ -95,35 +81,35 @@ public interface IAdapter
/// <exception cref="DeviceConnectionException">Thrown if the device connection fails.</exception>
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="device"/> is null.</exception>
Task ConnectToDeviceAsync(Device device, ConnectParameters connectParameters = default, CancellationToken cancellationToken = default);
////Task ConnectAsync(IDevice device, ConnectParameters connectParameters = default, CancellationToken cancellationToken = default);

/// <summary>
/// Disconnects from the <paramref name="device"/>.
/// </summary>
/// <summary>Disconnects from the <paramref name="device"/>.</summary>
/// <param name="device">Device to connect from.</param>
/// <returns>A task that represents the asynchronous read operation. The Task will finish after the device has been disconnected successfuly.</returns>
Task DisconnectDeviceAsync(Device device);
////Task DisconnectAsync(Device device);

/// <summary>
/// Connects to a device with a known GUID without scanning and if in range. Does not scan for devices.
/// </summary>
/// <summary>Connects to a device with a known GUID without scanning and if in range. Does not scan for devices.</summary>
/// <param name="deviceGuid"></param>
/// <param name="connectParameters">Connection parameters. Contains platform specific parameters needed to achieved connection. The default value is None.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is None.</param>
/// <returns></returns>
Task<Device> ConnectToKnownDeviceAsync(Guid deviceGuid, ConnectParameters connectParameters = default, CancellationToken cancellationToken = default);
////Task<IDevice> ConnectAsync(Guid deviceGuid, ConnectParameters connectParameters = default, CancellationToken cancellationToken = default);

/// <summary>
/// Returns all BLE devices connected to the system. For android the implementations uses getConnectedDevices(GATT) & getBondedDevices()
/// and for ios the implementation uses get retrieveConnectedPeripherals(services)
/// https://developer.apple.com/reference/corebluetooth/cbcentralmanager/1518924-retrieveconnectedperipherals
///
/// For android this function merges the functionality of thw following API calls:
/// https://developer.android.com/reference/android/bluetooth/BluetoothManager.html#getConnectedDevices(int)
/// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getBondedDevices()
/// In order to use the device in the app you have to first call ConnectAsync.
/// Returns all BLE devices connected to the system. For android the implementations uses getConnectedDevices(GATT) & getBondedDevices()
/// and for ios the implementation uses get retrieveConnectedPeripherals(services)
/// https://developer.apple.com/reference/corebluetooth/cbcentralmanager/1518924-retrieveconnectedperipherals
///
/// For android this function merges the functionality of thw following API calls:
/// https://developer.android.com/reference/android/bluetooth/BluetoothManager.html#getConnectedDevices(int)
/// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getBondedDevices()
/// In order to use the device in the app you have to first call ConnectAsync.
/// </summary>
/// <param name="services">IMPORTANT: Only considered by iOS due to platform limitations. Filters devices by advertised services. SET THIS VALUE FOR ANY RESULTS</param>
/// <returns>List of Devices connected to the OS. In case of no devices the list is empty.</returns>
IReadOnlyList<Device> GetSystemConnectedOrPairedDevices(Guid[] services = null);
////IReadOnlyList<Device> GetKnownDevices(Guid[] services = null);
}
}
Loading