Skip to content

Commit 0e990e3

Browse files
authored
Changes to allow scanning and connections to work together. (#41)
1 parent c13dc8f commit 0e990e3

File tree

6 files changed

+46
-30
lines changed

6 files changed

+46
-30
lines changed

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ This library is based on the Windows.Devices.Bluetooth UWP class library but sim
2020
The original .Net assembly depended on Windows.Storage.Streams for DataReader & DataWriter; this library has simplified inbuilt versions.
2121
So references to IBuffer in .Net UWP examples should now use Buffer instead.
2222

23-
We have also added an extension to this assembly allowing extra services to be added with no restriction on type.
23+
We have also added an extension to this assembly allowing extra services to be added to ServiceProvider with no restriction on type.
2424

2525
## Firmware versions
2626

2727
Bluetooth is currently only supported on ESP32 devices with following firmware.
2828

2929
- ESP32_BLE_REV0
3030
- ESP32_BLE_REV3
31+
- M5Core2
3132

3233
This restriction is due to IRAM memory space in the firmware image.
3334
With revision 1 of ESP32 devices, the PSRAM implementation requires a large number of PSRAM fixes which greatly reduces the
@@ -51,9 +52,10 @@ A number of Bluetooth LE samples are available in the [nanoFramework samples rep
5152

5253
This implementation supports a cut down version of the Gatt Server and Gatt Client implementation.
5354

54-
The device can either run as a Server, Client or Watcher, but not at the same time.
55+
The device can either run as a Server or Client, but not at the same time.
5556
For example if you start a Watcher to look for advertisements from Server devices you will not
56-
be able to connect to those devices until the Watcher has been stopped.
57+
be able to connect to those devices until the Watcher has been stopped. But you can recieve data from connected
58+
devices while Watcher is scanning.
5759

5860
For more information see relevant sections: -
5961

@@ -343,7 +345,7 @@ RSSI filter
343345

344346
## Creating a device and connecting to device.
345347

346-
To communicate with a device a BluetoothLEDevice class needs to be created using the devices bluetooth address.
348+
To communicate with a device a BluetoothLEDevice class needs to be created using the devices bluetooth address and type.
347349
This can be the bluetooth address from the BluetoothLEAdvertisementWatcher event or using a hard coded address.
348350

349351
In this case from the Watcher advertisement received event.
@@ -352,11 +354,12 @@ BluetoothLEDevice device = BluetoothLEDevice.FromBluetoothAddress(args.Bluetooth
352354
```
353355
There are no specific connection methods but a connection will be made automatically when you query the device
354356
for its services. The ConnectionStatusChanged event can used to detect a change in connection status and an attempt to
355-
reconnect can be done by query the devices services again. Avoid doing this in the event it self as it can block other
357+
reconnect can be done by a query to the devices services again. Avoid doing this in the event, as it can block other
356358
events being fired during the connection.
357359

358-
To go back to Watching for advertisements all connected devices need to be closed or disposed. This
359-
will put the stack in to an idle state so the Watching can be started.
360+
You can go back to Watching for advertisements with the restriction that you can't connect to newly found devcies until the Watching is stopped.
361+
You can still communication with connected devices while the Watcher is running. Best way is to collect all found devices in a table until Watcher is
362+
stopped then connect to all found devices. See [Central 2 sample](https://github.com/nanoframework/Samples/tree/main/samples/Bluetooth/Central2)
360363
361364
The Close() method is not exposed in the desktop version but it has been implemented in this version
362365
to give better control over the connection.

nanoFramework.Device.Bluetooth/BluetoothLEAdvertisementWatcher.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,8 @@ public BluetoothLEAdvertisementWatcher(BluetoothLEAdvertisementFilter advertisem
6868
/// </summary>
6969
public void Start()
7070
{
71-
if (BluetoothNanoDevice.RunMode != BluetoothNanoDevice.Mode.NotRunning)
72-
{
73-
throw new InvalidOperationException("Wrong state");
74-
}
75-
76-
// Set new run mode.
77-
BluetoothNanoDevice.RunMode = BluetoothNanoDevice.Mode.Scanning;
71+
// Check and set mode
72+
BluetoothNanoDevice.CheckMode(BluetoothNanoDevice.Mode.Client);
7873

7974
_status = BluetoothLEAdvertisementWatcherStatus.Started;
8075
_scanResults = new Hashtable();
@@ -97,7 +92,7 @@ public void Stop()
9792

9893
_status = BluetoothLEAdvertisementWatcherStatus.Stopped;
9994

100-
BluetoothNanoDevice.RunMode = BluetoothNanoDevice.Mode.NotRunning;
95+
BluetoothLEDevice.IdleOnLastConnection();
10196
}
10297

10398
/// <summary>

nanoFramework.Device.Bluetooth/BluetoothLEDevice.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ private ushort GetConnectingHandle
7272

7373
private GattCommunicationStatus ConnectDeviceIfNotConnected()
7474
{
75+
// Check and set mode, throw exception if wrong state
76+
BluetoothNanoDevice.CheckMode(BluetoothNanoDevice.Mode.Client);
77+
7578
GattCommunicationStatus status = GattCommunicationStatus.Unreachable;
7679

7780
if (_connectionStatus == BluetoothConnectionStatus.Disconnected)
@@ -399,6 +402,15 @@ internal GattWriteResult WriteAttributeValueWithResult(ushort attributeHandle, B
399402
return new GattWriteResult(status, (byte)result);
400403
}
401404

405+
internal static void IdleOnLastConnection()
406+
{
407+
if (GattServiceProvider._bluetoothEventManager.LeDeviceCount == 0)
408+
{
409+
// Reset run mode
410+
BluetoothNanoDevice.RunMode = BluetoothNanoDevice.Mode.NotRunning;
411+
}
412+
}
413+
402414
/// <summary>
403415
/// Central event handler from native code.
404416
/// </summary>
@@ -435,12 +447,9 @@ internal void OnEvent(BluetoothEventCentral btEvent)
435447
// Remove device from event handler
436448
GattServiceProvider._bluetoothEventManager.RemoveLeDevice(this);
437449

438-
if (GattServiceProvider._bluetoothEventManager.LeDeviceCount == 0)
439-
{
440-
// Last active device, close down stack
441-
//Debug.WriteLine("# Last active LE device");
442-
NativeDispose(_connectionHandle);
443-
}
450+
NativeDispose(_connectionHandle);
451+
452+
IdleOnLastConnection();
444453

445454
break;
446455

@@ -596,6 +605,7 @@ protected virtual void Dispose(bool disposing)
596605
// Make sure we are removed from event listener
597606
GattServiceProvider._bluetoothEventManager.RemoveLeDevice(this);
598607

608+
IdleOnLastConnection();
599609
}
600610
}
601611

nanoFramework.Device.Bluetooth/BluetoothNanoDevice.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
// As we can't run both Server or Central/Client at same time
1010
//
1111

12+
using System;
1213
using System.Runtime.CompilerServices;
1314

1415
namespace nanoFramework.Device.Bluetooth
1516
{
1617
internal static class BluetoothNanoDevice
1718
{
18-
internal enum Mode { NotRunning, Server, Scanning, Central };
19+
internal enum Mode { NotRunning, Server, Client };
1920

2021
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
2122
private static string _deviceName = "";
@@ -30,6 +31,18 @@ static BluetoothNanoDevice()
3031

3132
internal static string DeviceName { get => _deviceName; set => _deviceName = value; }
3233

34+
internal static void CheckMode(Mode expectedMode)
35+
{
36+
if (BluetoothNanoDevice.RunMode != expectedMode &&
37+
BluetoothNanoDevice.RunMode != Mode.NotRunning)
38+
{
39+
throw new InvalidOperationException("Wrong state");
40+
}
41+
42+
// Set new run mode.
43+
BluetoothNanoDevice.RunMode = expectedMode;
44+
}
45+
3346
/// <summary>
3447
/// Get/Set the current mode of the device.
3548
/// </summary>

nanoFramework.Device.Bluetooth/GenericAttributeProfile/GattServiceProvider.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,11 @@ public void StartAdvertising()
9595
/// <param name="parameters">The advertising parameters.</param>
9696
public void StartAdvertising(GattServiceProviderAdvertisingParameters parameters)
9797
{
98-
if (BluetoothNanoDevice.RunMode != BluetoothNanoDevice.Mode.NotRunning)
99-
{
100-
throw new InvalidOperationException("Wrong state");
101-
}
98+
// Check and switch to server mode
99+
BluetoothNanoDevice.CheckMode(BluetoothNanoDevice.Mode.Server);
102100

103101
BluetoothNanoDevice.DeviceName = parameters.DeviceName;
104102

105-
// Switch to client/server mode
106-
BluetoothNanoDevice.RunMode = BluetoothNanoDevice.Mode.Server;
107-
108103
// Save parameters
109104
_isConnectable = parameters.IsConnectable;
110105
_isDiscoverable = parameters.IsDiscoverable;

nanoFramework.Device.Bluetooth/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
////////////////////////////////////////////////////////////////
1919
// update this whenever the native assembly signature changes //
20-
[assembly: AssemblyNativeVersion("100.0.1.0")]
20+
[assembly: AssemblyNativeVersion("100.0.2.0")]
2121
////////////////////////////////////////////////////////////////
2222

2323

0 commit comments

Comments
 (0)