mirror of
https://github.com/inthehand/32feet.git
synced 2026-10-28 22:54:52 +08:00
274 lines
12 KiB
C#
274 lines
12 KiB
C#
//#define PRE_V2_4
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.ComponentModel;
|
|
using System.Threading;
|
|
using InTheHand.Net.Sockets;
|
|
using System.Diagnostics;
|
|
#if NETCF
|
|
using SendOrPostCallback = System.Threading.WaitCallback;
|
|
#endif
|
|
|
|
namespace InTheHand.Net.Bluetooth
|
|
{
|
|
/// <summary>
|
|
/// Provides simple access to asynchronous methods on Bluetooth features, for
|
|
/// instance to background device discovery.
|
|
/// </summary>
|
|
/// -
|
|
/// <example>
|
|
/// <code lang="VB.NET">
|
|
/// Public Sub DiscoDevicesAsync()
|
|
/// Dim bco As New BluetoothComponent()
|
|
/// AddHandler bco.DiscoverDevicesProgress, AddressOf HandleDiscoDevicesProgress
|
|
/// AddHandler bco.DiscoverDevicesComplete, AddressOf HandleDiscoDevicesComplete
|
|
/// bco.DiscoverDevicesAsync(255, True, True, True, False, 99)
|
|
/// End Sub
|
|
///
|
|
/// Private Sub HandleDiscoDevicesProgress(ByVal sender As Object, ByVal e As DiscoverDevicesEventArgs)
|
|
/// Console.WriteLine("DiscoDevicesAsync Progress found {0} devices.", e.Devices.Length)
|
|
/// End Sub
|
|
///
|
|
/// Private Sub HandleDiscoDevicesComplete(ByVal sender As Object, ByVal e As DiscoverDevicesEventArgs)
|
|
/// Debug.Assert(CInt(e.UserState) = 99)
|
|
/// If e.Cancelled Then
|
|
/// Console.WriteLine("DiscoDevicesAsync cancelled.")
|
|
/// ElseIf e.Error IsNot Nothing Then
|
|
/// Console.WriteLine("DiscoDevicesAsync error: {0}.", e.Error.Message)
|
|
/// Else
|
|
/// Console.WriteLine("DiscoDevicesAsync complete found {0} devices.", e.Devices.Length)
|
|
/// End If
|
|
/// End Sub
|
|
/// </code>
|
|
/// </example>
|
|
public class BluetoothComponent : Component
|
|
{
|
|
readonly BluetoothClient m_cli;
|
|
|
|
//----
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="T:InTheHand.Net.Bluetooth.BluetoothComponent"/> class.
|
|
/// </summary>
|
|
public BluetoothComponent()
|
|
: this(new BluetoothClient())
|
|
{
|
|
}
|
|
|
|
//TODO !!!! Add to public stack factory
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="T:InTheHand.Net.Bluetooth.BluetoothComponent"/> class.
|
|
/// </summary>
|
|
/// -
|
|
/// <param name="cli">A <see cref="T:InTheHand.Net.Sockets.BluetoothClient"/>
|
|
/// instance to use to run discovery on. Must be non-null.
|
|
/// </param>
|
|
public BluetoothComponent(BluetoothClient cli)
|
|
{
|
|
if (cli == null) throw new ArgumentNullException("cli");
|
|
m_cli = cli;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Optionally disposes of the managed resources used by the
|
|
/// <see cref="T:InTheHand.Net.Bluetooth.BluetoothComponent"/> class.
|
|
/// </summary>
|
|
/// <param name="disposing"><c>true</c> to release both managed and unmanaged
|
|
/// resources; <c>false</c> to release only unmanaged resources.
|
|
/// </param>
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
try {
|
|
if (disposing) {
|
|
m_cli.Dispose();
|
|
}
|
|
} finally {
|
|
base.Dispose(disposing);
|
|
}
|
|
}
|
|
|
|
//----
|
|
/// <summary>
|
|
/// Occurs when an device discovery operation completes.
|
|
/// </summary>
|
|
/// -
|
|
/// <remarks>
|
|
/// <para>This event is raised at the end of the discovery process
|
|
/// and lists all the discovered devices.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// -
|
|
/// <seealso cref="E:InTheHand.Net.Bluetooth.BluetoothComponent.DiscoverDevicesProgress"/>
|
|
public event EventHandler<DiscoverDevicesEventArgs> DiscoverDevicesComplete;
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="E:InTheHand.Net.Bluetooth.BluetoothComponent.DiscoverDevicesComplete"/> event.
|
|
/// </summary>
|
|
/// <param name="e">A <see cref="T:InTheHand.Net.Bluetooth.DiscoverDevicesEventArgs"/>
|
|
/// object that contains event data.
|
|
/// </param>
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers",
|
|
Justification = "It it /not/ visible!")]
|
|
protected void OnDiscoveryComplete(DiscoverDevicesEventArgs e)
|
|
{
|
|
EventHandler<DiscoverDevicesEventArgs> eh = DiscoverDevicesComplete;
|
|
if (eh != null) {
|
|
eh(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs during an device discovery operation
|
|
/// to show one or more new devices.
|
|
/// </summary>
|
|
/// -
|
|
/// <remarks>
|
|
/// <para>This event is raised for all discovered devices, both the
|
|
/// known devices which are presented first, if requested,
|
|
/// as well as newly discovery device found by the inquiry process,
|
|
/// again if requested.
|
|
/// </para>
|
|
/// <para>Note that any event instance may include one or more devices. Note
|
|
/// also that a particular device may be presented more than one time;
|
|
/// including once from the ‘known’ list, once when a
|
|
/// device is dicovered, and possibly another time when the discovery
|
|
/// process retrieves the new device’s Device Name.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// -
|
|
/// <seealso cref="E:InTheHand.Net.Bluetooth.BluetoothComponent.DiscoverDevicesComplete"/>
|
|
public event EventHandler<DiscoverDevicesEventArgs> DiscoverDevicesProgress;
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="E:InTheHand.Net.Bluetooth.BluetoothComponent.DiscoverDevicesProgress"/> event.
|
|
/// </summary>
|
|
/// <param name="e">A <see cref="T:InTheHand.Net.Bluetooth.DiscoverDevicesEventArgs"/>
|
|
/// object that contains event data.
|
|
/// </param>
|
|
protected void OnDiscoveryProgress(DiscoverDevicesEventArgs e)
|
|
{
|
|
var eh = DiscoverDevicesProgress;
|
|
if (eh != null) {
|
|
eh(this, e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Discovers accessible Bluetooth devices and returns their names and addresses.
|
|
/// This method does not block the calling thread.
|
|
/// </summary>
|
|
/// -
|
|
/// <remarks>
|
|
/// <para>See <see cref="M:InTheHand.Net.Sockets.BluetoothClient.DiscoverDevices(System.Int32,System.Boolean,System.Boolean,System.Boolean,System.Boolean)"/>
|
|
/// for more information.
|
|
/// </para>
|
|
/// <para>The devices are presented in the <see cref="E:InTheHand.Net.Bluetooth.BluetoothComponent.DiscoverDevicesComplete"/>
|
|
/// and <see cref="E:InTheHand.Net.Bluetooth.BluetoothComponent.DiscoverDevicesProgress"/> events.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// -
|
|
/// <param name="maxDevices">The maximum number of devices to get information about.
|
|
/// </param>
|
|
/// <param name="authenticated">True to return previously authenticated/paired devices.
|
|
/// </param>
|
|
/// <param name="remembered">True to return remembered devices.
|
|
/// </param>
|
|
/// <param name="unknown">True to return previously unknown devices.
|
|
/// </param>
|
|
/// <param name="discoverableOnly">True to return only the devices that
|
|
/// are in range, and in discoverable mode. See the remarks section.
|
|
/// </param>
|
|
/// <param name="state">A user-defined object that is passed to the method
|
|
/// invoked when the asynchronous operation completes.
|
|
/// </param>
|
|
/// -
|
|
/// <returns>An array of BluetoothDeviceInfo objects describing the devices discovered.</returns>
|
|
public void DiscoverDevicesAsync(int maxDevices,
|
|
bool authenticated, bool remembered, bool unknown, bool discoverableOnly,
|
|
object state)
|
|
{
|
|
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(state);
|
|
// Provide the remembered devices immediately
|
|
DoRemembered(authenticated, remembered, discoverableOnly, asyncOp);
|
|
//
|
|
#if PRE_V2_4
|
|
if (discoverableOnly)
|
|
throw new ArgumentException("Flag 'discoverableOnly' is not supported in this version.", "discoverableOnly");
|
|
FuncDiscoDevs dlgt = new FuncDiscoDevs(m_cli.DiscoverDevices);
|
|
FuncDiscoDevs exist = Interlocked.CompareExchange(ref m_dlgt, dlgt, null);
|
|
if (exist != null)
|
|
throw new InvalidOperationException("Only support one concurrent operation.");
|
|
dlgt.BeginInvoke(maxDevices,
|
|
authenticated, remembered, unknown, //discoverableOnly,
|
|
HandleDiscoComplete, asyncOp);
|
|
#else
|
|
m_cli.BeginDiscoverDevices(maxDevices,
|
|
authenticated, remembered, unknown, discoverableOnly,
|
|
HandleDiscoComplete, asyncOp,
|
|
HandleDiscoNewDevice, asyncOp);
|
|
#endif
|
|
}
|
|
|
|
private void DoRemembered(bool authenticated, bool remembered, bool discoverableOnly, AsyncOperation asyncOp)
|
|
{
|
|
if ((authenticated || remembered) && !discoverableOnly) {
|
|
var rmbd = m_cli.DiscoverDevices(255, authenticated, remembered, false, false);
|
|
if (rmbd.Length != 0) {
|
|
var e = new DiscoverDevicesEventArgs(rmbd, asyncOp.UserSuppliedState);
|
|
SendOrPostCallback cb = delegate(object args) {
|
|
OnDiscoveryProgress((DiscoverDevicesEventArgs)args);
|
|
};
|
|
asyncOp.Post(cb, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if PRE_V2_4
|
|
delegate BluetoothDeviceInfo[] FuncDiscoDevs(int maxDevices,
|
|
bool authenticated, bool remembered, bool unknown/*, bool discoverableOnly*/);
|
|
FuncDiscoDevs m_dlgt;
|
|
#endif
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
|
|
private void HandleDiscoComplete(IAsyncResult ar)
|
|
{
|
|
AsyncOperation asyncOp = (AsyncOperation)ar.AsyncState;
|
|
DiscoverDevicesEventArgs e;
|
|
try {
|
|
#if PRE_V2_4
|
|
FuncDiscoDevs dlgt = Interlocked.Exchange(ref m_dlgt, null);
|
|
BluetoothDeviceInfo[] arr = dlgt.EndInvoke(ar);
|
|
#else
|
|
BluetoothDeviceInfo[] arr = m_cli.EndDiscoverDevices(ar);
|
|
#endif
|
|
e = new DiscoverDevicesEventArgs(arr, asyncOp.UserSuppliedState);
|
|
} catch (Exception ex) {
|
|
e = new DiscoverDevicesEventArgs(ex, asyncOp.UserSuppliedState);
|
|
// TO-DO ?? Set Cancelled if disposed?
|
|
}
|
|
//
|
|
SendOrPostCallback cb = delegate(object args) {
|
|
OnDiscoveryComplete((DiscoverDevicesEventArgs)args);
|
|
};
|
|
asyncOp.PostOperationCompleted(cb, e);
|
|
}
|
|
|
|
private void HandleDiscoNewDevice(InTheHand.Net.Bluetooth.Factory.IBluetoothDeviceInfo newDevice, object state)
|
|
{
|
|
Debug.WriteLine(DateTime.UtcNow.TimeOfDay.ToString() + ": HandleDiscoNewDevice.");
|
|
AsyncOperation asyncOp = (AsyncOperation)state;
|
|
Debug.Assert(newDevice != null);
|
|
var rslt = new BluetoothDeviceInfo[] { new BluetoothDeviceInfo(newDevice) };
|
|
Debug.Assert(rslt.Length > 0, "NOT rslt.Length > 0");
|
|
var e = new DiscoverDevicesEventArgs(rslt, asyncOp.UserSuppliedState);
|
|
SendOrPostCallback cb = delegate(object args) {
|
|
OnDiscoveryProgress((DiscoverDevicesEventArgs)args);
|
|
};
|
|
asyncOp.Post(cb, e);
|
|
}
|
|
|
|
}
|
|
|
|
}
|