Xamarin Android and Bluetooth LE

I've been through all the discussions on this board regarding getting Bluetooth LE working with Xamarin on an Android. I've tried using MetaWear.CSharp, MetaWear.CSharp.NetStandard, Warble, etc. and have success in Windows 10 with various combinations, however have had no luck getting my Android device using a project built in Xamarin to successfully scan for a MetaWear device.

It looks like it all comes down to Xamarin not having native code to do Bluetooth LE. Other plugins are required (Warble, Aritchie - REACTIVE BluetoothLE Plugin, or others).

I'm looking for a simple project that'll scan for a BLE device (MetaWear), and then correctly communicate w/ the MetaWear device using the standard MetaWear API.

        try
        {
            var metawear = MbientLab.MetaWear.NetStandard.Application.GetMetaWearBoard( [ A MAC ADDRESS ] );
            metawear.InitializeAsync();
        }
        catch (Exception e)
        {
            Console.WriteLine("error: " + e.Message);
        }

Above, I need to find the [A MAC ADDRESS] and have the backend Bluetooth LE objects in place to have the above function work.

I'm missing a piece of the puzzle that connects all this together and have gotten to the point where I'm too deep in this project to see the solution.

Can someone help with a current project built in Visual Studio 2017 using Xamarin to run a program on an Android device (7.1 or higher) that'll get me going?

We currently have a project that uses standard Bluetooth to read sensor data, we want to move to the MetaWear devices.

Thanks
Carlton

Comments

  • Warble and the .NET Standard plugin (which calls Warble undernath) won't work on mobile. Those are desktop only libraries.

    Unfortunately, we don't use or support Xamarin developement. Using BLE is a fairly common use case with their SDK so there is probably third party libraries to provide cross-platform BLE support.

    With that said, if you do find suitable cross platform BLE library, you can plug it into the MetaWear C# SDK in the same way the .NET Standard plugin does it.

  • Warble won't work as Eric correctly points out - however we have it working in android using Xamarin, it requires some work arounds.

    It required writing the interfaces into the SDK - "bluetoothlegatt" & "libraryio"....mentioned here https://github.com/mbientlab/MetaWear-SDK-CSharp

    We also then used a Nuget bluetooth plugin - "plugin.bluetoothle"
    Android is easier than iOS through Xamarin - as it can access the MAC address of the MetaWear, while iOS obscures and does not allow access to the MAC address, it assigns a random UUID.

  • Thanks for the direction. I actually started w/ the MetaWear-SDK-CSharp andBluetoothele Nuget projects but ran into some issues so I opted to try another solution.

    I'm starting over and I'm back to the above in a brand new project. I have a project building and can discover/connect to the device in my BluetoothLeGatt object, however soon after I get a NULL exception deep in the code. I don't think it's directly in my object, but likely something I'm doing that is causing this internal error.

    This works:

        public Task DiscoverServicesAsync()
        {
            CrossBleAdapter.Current.ScanExtra()
                .Subscribe(result =>
                {
                    Console.WriteLine("Device: " + result.Device);
                    Console.WriteLine("Device: " + result.Device.Name);
    
                    if (metawearDevice == null && result.Device.Name != null && result.Device.Name.Contains("Meta"))
                    {
                        metawearDevice = result.Device;
                        CrossBleAdapter.Current.StopScan();
    
                        metawearDevice.Connect();
                    }
                }
                );
    
            return null;
        }
    

    And will show me the Metawear device, connect to it but before I can use it in the UI (attempting to get the ILed), the a NULL exception is thrown.

    Any chance you can share a IBluetoothLeGatt and ILibraryIO object to work with?

    I'm only interested in Android.

    If not, can you point me elsewhere?

    Thanks
    carlton
    at inlinetechnology.com

  • It took some time, but I now have tested three different BLE interfaces. ble.net/ble.net-android by nexussays; Plugin.BLE by Andrian Seceleanu,Sven-Michael Stube; and the plugin.bluetoothle. All available on NuGet.

    In all cases I'm able to talk with the MetaWear device, blink it's LED, and read values from the board. But in all cases after the object is create, the MetaWearBoard doesn't set the flag IsConnected.

    But when I run a test w/ the MetaWear Tutorials (Universal Windows) on Windows 10. IsConnected does change to TRUE.

    Not sure that is a problem - I'll continue to build/test and push ahead w/ my Android project.

  • IsConnected is set to true at the end of the InitializeAsync function:
    https://github.com/mbientlab/MetaWear-SDK-CSharp/blob/1.2.0/MetaWear/Impl/MetaWearBoard.cs#L835

    You'll need to figure out why that line isn't getting reached in your code

  • Thanks for the nudge in the right direction. I'm stepping through the SDK-CSharp code and an exception is getting thrown in the QueryTimeAsync() function in

    https://github.com/mbientlab/MetaWear-SDK-CSharp/blob/1.2.0/MetaWear/Impl/MetaWearBoard.cs#L812

    Which actually fails in Logging.cs

    https://github.com/mbientlab/MetaWear-SDK-CSharp/blob/1.2.0/MetaWear/Impl/Logging.cs#L281

            queryTimeTask = new TimedTask<bool>();
            await queryTimeTask.Execute("Failed to receive current time tick within {0}ms", bridge.TimeForResponse, 
                () => bridge.sendCommand(new byte[] { (byte)LOGGING, Util.setRead(TIME) }));
    

    When I set the time out to a large value (10 seconds)

            await queryTimeTask.Execute("Failed to receive current time tick within {0}ms", 10000, //bridge.TimeForResponse, 
    

    I'll wait 10 seconds and fail even though the code it's calling completes in time. Not sure what I'm missing.

    It does call into my WriteCharacteristicAsync function.

        public async Task WriteCharacteristicAsync(Tuple<Guid, Guid> gattChar, GattCharWriteType writeType, byte[] bytes)
        {
            try
            {
                var characteristic = await GetCharacteristicAsync(gattChar);
                if (characteristic != null)
                {
                    if (writeType == GattCharWriteType.WRITE_WITHOUT_RESPONSE)
                        characteristic.WriteType = CharacteristicWriteType.WithoutResponse;
    
                    await characteristic.WriteAsync(bytes);
    
                    SettingsLog.WriteLog("INF", string.Format("WriteCharacteristic({0}) '{1}' is {2} long", (characteristic != null), gattChar.Item2, bytes.Length));
                }
            }
            catch (Exception ex)
            {
                SettingsLog.WriteLog("EXC", ex.Message);
            }
        }
    

    Am I missing a "Task Complete" flag or something?

  • To resolve I just commented out lines 811/812/813

                //if (persistent.modules.TryGetValue(typeof(ILogging).FullName, out var logging)) {
                //    await (logging as Logging).QueryTimeAsync();
                //}
    

    Not sure what that'll break, but it wasn't working anyway.

    Carlton

Sign In or Register to comment.