HomeForaForum_C#353ffc6f-0415-486d-8154-bb4400069410

C#

administrator ( 11 posts)
1. I refactored a Xamarin BLE starck, and started with the event handler
Original post
9/1/2020 11:48:04 AM

Last edited Tuesday, September 1, 2020 11:59 AM

Gravatar

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 );
    }

Replies to this post

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
Back to threads