diff --git a/src/Linux.Bluetooth/Device.cs b/src/Linux.Bluetooth/Device.cs index cfd93b1..334b470 100644 --- a/src/Linux.Bluetooth/Device.cs +++ b/src/Linux.Bluetooth/Device.cs @@ -16,6 +16,7 @@ public class Device : IDevice1, IDisposable { private const string DeviceConnected = "Connected"; private const string DeviceServicesResolved = "ServicesResolved"; + private const string DeviceRSSI = "RSSI"; private IDevice1 _proxy; private IDisposable _propertyWatcher; @@ -64,6 +65,16 @@ public event DeviceEventHandlerAsync Connected public event DeviceEventHandlerAsync Disconnected; + /// Raised when the device's RSSI property changes, carrying the new value in dBm. + public event EventHandler? RSSIChanged; + + /// + /// Raised for every Device1 property change, carrying the raw . Covers + /// properties without a dedicated typed event (e.g. ManufacturerData, TxPower). Note that changes also + /// covered by a typed event (Connected, ServicesResolved, RSSI) are delivered on both. + /// + public event EventHandler? PropertyChanged; + public event DeviceEventHandlerAsync ServicesResolved { add @@ -244,8 +255,16 @@ private void OnPropertyChanges(PropertyChanges changes) OnResolved?.Invoke(this, new BlueZEventArgs()); break; + + case DeviceRSSI: + if (pair.Value is short sRSSI) + RSSIChanged?.Invoke(this, sRSSI); + + break; } } + + PropertyChanged?.Invoke(this, changes); } } } diff --git a/src/Linux.Bluetooth/Extensions/WatchableExtensions.cs b/src/Linux.Bluetooth/Extensions/WatchableExtensions.cs index 8dd2a81..5887802 100644 --- a/src/Linux.Bluetooth/Extensions/WatchableExtensions.cs +++ b/src/Linux.Bluetooth/Extensions/WatchableExtensions.cs @@ -17,7 +17,7 @@ public static class WatchableExtensions /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IAdapter1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /// Wait for AdvertisingManager's Property and specified value to resolve. /// Type of value. @@ -28,7 +28,7 @@ public static Task WaitForPropertyValueAsync(this IAdapter1 obj, string prope /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this ILEAdvertisingManager1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /// Wait for Device's Property and specified value to resolve. /// Type of value. @@ -39,7 +39,7 @@ public static Task WaitForPropertyValueAsync(this ILEAdvertisingManager1 obj, /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IDevice1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /// Wait for Battery's Property and specified value to resolve. /// Type of value. @@ -50,7 +50,7 @@ public static Task WaitForPropertyValueAsync(this IDevice1 obj, string proper /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IBattery1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /* /// Wait for GattService's Property and specified value to resolve. @@ -62,7 +62,7 @@ public static Task WaitForPropertyValueAsync(this IBattery1 obj, string prope /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IGattService1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /// Wait for GattCharacteristic's Property and specified value to resolve. /// Type of value. @@ -73,7 +73,7 @@ public static Task WaitForPropertyValueAsync(this IGattService1 obj, string p /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IGattCharacteristic1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /// Wait for GattDescriptor's Property and specified value to resolve. /// Type of value. @@ -84,7 +84,7 @@ public static Task WaitForPropertyValueAsync(this IGattCharacteristic1 obj, s /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IGattDescriptor1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); */ /// Wait for MediaControl's Property and specified value to resolve. @@ -96,7 +96,7 @@ public static Task WaitForPropertyValueAsync(this IGattDescriptor1 obj, strin /// Task or exception. /// On timeout a is thrown. public static Task WaitForPropertyValueAsync(this IMediaControl1 obj, string propertyName, T value, TimeSpan timeout) - => WaitForPropertyValueInternalAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); + => WaitForPropertyValueAsync(obj.GetAsync, obj.WatchPropertiesAsync, propertyName, value, timeout); /// /// Wait for watchable objects property and specified value to resolve. @@ -110,10 +110,13 @@ public static Task WaitForPropertyValueAsync(this IMediaControl1 obj, string /// TimeSpan to wait for. /// Task or exception. /// On timeout a is thrown. - private static async Task WaitForPropertyValueInternalAsync( + public static async Task WaitForPropertyValueAsync( Func> getAsync, - Func, Task> watchPropertiesAsync, - string propertyName, T value, TimeSpan timeout) + Func, + Task> watchPropertiesAsync, + string propertyName, + T value, + TimeSpan timeout) { // TODO: Change to Task versus throwing an error. var (watchTask, watcher) = WaitForPropertyValueInternal(watchPropertiesAsync, propertyName, value);