Last edited Tuesday, September 1, 2020 11:59 AM
So, there is a pattern to BLE and the interactions with the service. I have created an event driven handler for BLE in Xamarin, and it all starts with the TaskBuilder:
public static class TaskBuilder
{
#region Public Methods
public static Task<TReturn> FromEvent<TReturn, TEventHandler>(
Action execute,
Func<Action<TReturn>, Action<Exception>, TEventHandler> getCompleteHandler,
Action<TEventHandler> subscribeComplete,
Action<TEventHandler> unsubscribeComplete,
CancellationToken token = default( CancellationToken ) )
{
return FromEvent<TReturn, TEventHandler, object>(
execute, getCompleteHandler, subscribeComplete, unsubscribeComplete,
getRejectHandler: reject => null,
subscribeReject: handler => { },
unsubscribeReject: handler => { },
token: token );
}
public static async Task<TReturn> FromEvent<TReturn, TEventHandler, TRejectHandler>(
Action execute,
Func<Action<TReturn>, Action<Exception>, TEventHandler> getCompleteHandler,
Action<TEventHandler> subscribeComplete,
Action<TEventHandler> unsubscribeComplete,
Func<Action<Exception>, TRejectHandler> getRejectHandler,
Action<TRejectHandler> subscribeReject,
Action<TRejectHandler> unsubscribeReject,
CancellationToken token = default( CancellationToken ) )
{
TaskCompletionSource<TReturn> taskCompletionSource = new TaskCompletionSource<TReturn>( );
Action<TReturn> complete = arguments => taskCompletionSource.TrySetResult( arguments );
Action<Exception> completeException = ex => taskCompletionSource.TrySetException( ex );
Action<Exception> reject = exception => taskCompletionSource.TrySetException( exception );
TEventHandler handler = getCompleteHandler( complete, completeException );
TRejectHandler rejectHandler = getRejectHandler( reject );
try
{
subscribeComplete( handler );
subscribeReject( rejectHandler );
using ( token.Register( ( ) => taskCompletionSource.TrySetCanceled( ), false ) )
{
execute( );
return await taskCompletionSource.Task;
}
}
finally
{
unsubscribeReject( rejectHandler );
unsubscribeComplete( handler );
}
}
#endregion Public Methods
}
The TaskBuilder is used like this:
protected override async Task<byte[]> ReadNativeAsync( ICharacteristicReadRequest characteristicReadRequest, CancellationToken cancellationToken )
{
LoggingService.Trace( $"Reading data for characteristic {Name}" );
return await TaskBuilder.FromEvent<byte[], EventHandler<GattCharacteristicReadCallbackEventArgs>, EventHandler>(
execute: ReadInternal,
getCompleteHandler: ( complete, reject ) => ( ( sender, args ) =>
{
if ( args.Characteristic.Uuid == _nativeCharacteristic.Uuid )
{
CharacteristicReadEventArgs characteristicReadEventArgs = new CharacteristicReadEventArgs( characteristicReadRequest );
OnCharacteristicRead( characteristicReadEventArgs );
complete( args.Characteristic.GetValue( ) );
}
} ),
subscribeComplete: handler => _gattCallback.GattCharacteristicRead += handler,
unsubscribeComplete: handler => _gattCallback.GattCharacteristicRead -= handler,
getRejectHandler: reject => ( ( sender, args ) =>
{
reject( new Exception( $"Device disconnected while reading characteristic {Name}." ) );
} ),
subscribeReject: handler => _gattCallback.GattConnectionInterrupted += handler,
unsubscribeReject: handler => _gattCallback.GattConnectionInterrupted -= handler );
}
0 replies | Author | Created On | Post Number |
---|---|---|---|
I refactored a Xamarin BLE starck, and started with the event handler | administrator | 9/1/2020 11:48:04 AM | OP |