Skip to content

Movesense .NET SDK for Xamarin Android and Xamarin iOS

License

Notifications You must be signed in to change notification settings

tentom/MovesenseDotNet

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Movesense.Net

Movesense .NET SDK for Xamarin Android and Xamarin iOS. Xamarin Forms supported for both shared project and shared library configurations.

NEW RELEASE Movesense.Net V2.68 June 2022

  • Latest MDS Libraries supported in this release. v1.68.0 of the Android and iOS MDS Libraries are wrapped by this plugin. Install Plugin.Movesense v2.68.0 or later from NuGet to get this update.
  • [v2.68.0] MdsLib 1.68.0 libraries
  • [v2.44.0] Mdslib 1.44.0 libraries
  • [v2.0.5] 64 bit targets fully supported.
  • [v2.0.5] Adds new method GetDetailedTimeAsync. Fixes issues with SetTime and modificationTimestamp in GetLogEntries.

Movesense.Net V2.0 API. V2.0 of Movesense.Net introduced a slightly different API. You now get an IMovesenseDevice object back from a call to ConnectMdsAsync and you use this object thereafter to invoke other Movesense.Net operations. The old API has been deprecated, as it relied on the device name to identify the target but which proved unreliable as device names may change. V1.x Movesense.Net API is still supported and still fully operational, although code that calls to V1.x methods are flagged with 'Deprecated' compiler warnings.

IMPORTANT SETUP FOR ANDROID PROJECTS for Plugin.Movesense v1.7.2.1 and later The latest version of the Android Mds library requires java8 features that are not supported by Xamarin tools in Visual Studio 2017. You must use Visual Studio 2019 and make edits to the Xamarin.Android project file to successfully build your Xamarin Android project with this version of Plugin.Movesense. See the Building Android Projects instructions in the Setup for Android projects instructions below.

Movesense Plugin Developer Guide

The Xamarin .NET API for Movesense is available on NuGet as a Plugin. If you search in NuGet Package manager for Movesense, you will see three packages available:

  • Plugin.Movesense - this is the package you should reference in your project. It has the full .NET API for programming for connectivity to Movesense devices, and also includes the MovesenseBindingAndroid and MovesenseBindingiOS packages which are the C# bindings around the native Android Mdslib.aar and iOS libmds.a libraries

  • MovesenseBindingAndroid - this package is the C# binding around the native Android Mdslib.aar library. You do not need to reference this package separately as it is configured as a dependency of the Plugin.Movesense package.

  • MovesenseBindingiOS - this package is the C# binding around the native iOS libmds.a library. You do not need to reference this package separately as it is configured as a dependency of the Plugin.Movesense package.

    Image of NuGet Package Manager

    The only one you need to add to your projects is the Plugin.Movesense package, the binding projects are defined as dependencies in the Plugin.Movesense package so will be installed automatically. Add the Plugin.Movesense package to all your projects: to the Xamarin Android and Xamarin iOS projects and also, if you are using it, to the .NET Standard project containing your shared code.

Using the Movesense Plugin in your Xamarin App

To use the Movesense Plugin in your own app:

  • Create your Xamarin Android, Xamarin iOS or Xamarin Forms project
  • Add reference to the Plugin.Movesense NuGet package to your Xamarin Android and Xamarin iOS projects and - if you are using Xamarin Forms configured with common code in a class library - to your .NET Standard class library contining your shared code.

Setup for Android projects

  • For bluetooth connectivity, you will need to request the ACCESS_COARSE_LOCATION, BLUETOOTH and BLUETOOTH_ADMIN permissions. Check these on the Project Properties - Android manifest settings page. You will also need to request permissions from the user - see topic Bluetooth Connections below for information on programming connectivity to devices.

  • Before you make any calls to the Movesense Plugin library, you must initialize it with the current Android Activity. For example, add a MainApplication.cs file to your project and add code similar to this:

    [Application]
    public class MainApplication : Application, Application.IActivityLifecycleCallbacks
    {
        public MainApplication(IntPtr handle, JniHandleOwnership transer) :base(handle, transer)
        {
        }

        ...

        public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
        {
            // Initialize the MdsLib
            Plugin.Movesense.CrossMovesense.Current.Activity = activity;
        }

        ...
    }

Building Android Projects

Plugin.Movesense v1.7.2 and later wraps versions of the native Mdslib.aar library for Android which require java8 features that are not supported by Xamarin tools in Visual Studio 2017.

To build your Xamarin Android project successfully using Plugin.Movesense v1.7.2 or later, you must:

  • Install Visual Studio 2019 and use this to develop your app.
  • You must edit your project csproj file for your Android client project and add the following to enable the Android D8 compiler for the native code generation step:
  <PropertyGroup> 
    <AndroidDexTool>d8</AndroidDexTool>
  </PropertyGroup>

Setup for iOS projects

As you are using Bluetooth peripherals, you will need to add the following to your Info.plist:

  <key>UIBackgroundModes</key>
  <array>
    <!--for connecting to devices (client)-->
    <string>bluetooth-central</string>
  </array>

  <!--To add a description to the Bluetooth request message (on iOS 10+, deprecated)-->
  <key>NSBluetoothPeripheralUsageDescription</key>
  <string>Access Movesense sensor</string>

  <!--Description of the Bluetooth request message (required on iOS 13)-->
  <key>NSBluetoothAlwaysUsageDescription</key>
  <string>Access Movesense sensor</string>

Programming the Movesense .NET API

  • Access the Movesense API anywhere in your code by getting the Plugin.Movesense.CrossMovesense.Current property:

    var mds = Plugin.Movesense.CrossMovesense.Current;
  • To connect to a Movesense device, you must first discover a Movesense device and find out its Uuid (unique identifier). You must add this code youself as Bluetooth device discovery is not a feature provided by the Movesense Plugin, although once you have found a device, the Mdslib will make the Bluetooth connection when you call the ConnectMdsAsync method. See topic Bluetooth Device Discovery below for hints on how to do this.

  • After you have discovered the Uuid of a Movesense device, you must connect to it using the MdsLib, passing the Uuid of the device. Connect like this:

    // Make the Mds connection
    var movesenseDevice = await Plugin.Movesense.CrossMovesense.Current.ConnectMdsAsync(sensor.Uuid);

    and disconnect using one of these options:

    // Disconnect from Mds - method #1
    await Plugin.Movesense.CrossMovesense.Current.DisconnectMdsAsync(sensor.Uuid);
    
    // ALTERNATIVE: Disconnect from Mds
    await movesenseDevice.DisconnectMdsAsync();

    NOTE: In the Movesense.Net V2 API, all Movesense APIs apart from ConnectMdsAsync, ApiCallAsync and ApiSubscriptionAsync are methods of the IMovesenseDevice object that you get back from a call to ConnectMdsAsync. In The V1.x API, all device-centric methods were available on the top-level IMovesense object and required that you pass the device name as the first argument, for example Movesense 174430000051. The V1.x API has been deprecated for the simple reason that device names can chnage so this is not a reliable way of addressing a device. The V1.x methods are still supported in V2.0 although are marked as Deprecated so you will get compiler warnings if you try to use them.

  • The ConnectMdsAsync method returns an IMovesenseDevice object. Use this object to make calls to the device.

    For example, to get device info:

    var info = await movesenseDevice.GetDeviceInfoAsync();
    await DisplayAlert("Success", $"Communicated with device {sensor.Name}, firmware version is: {info.DeviceInfo.Sw}", "OK");
  • To subscribe to notifications from the builtin sensors such as the accelerometer, call the appropriate method, passing a reference to a callback function that MdsLib calls to notify data.

    For example, to subscribe to Accelerometer readings:

    var subscription = await movesenseDevice.SubscribeAccelerometerAsync( (d) =>
                        {
                            PlotData(d.Data.Timestamp, d.Data.AccData[0].X, d.Data.AccData[0].Y, d.Data.AccData[0].Z);
                        },
                        26);

    To drop the subscription, simply call the Unsubscribe method of the subscription object:

    subscription.Unsubscribe();
  • To get Device connection and disconnection events, subscribe to these events on the ConnectionLIstener object:

    • DeviceConnected - Bluetooth LE connection has succeeded
    • DeviceConnectionComplete - connection to the Movesense Mdslib Whiteboard is complete and the device is ready for use
    • Device disconnected - device has disconnected

    Example:

      Plugin.Movesense.CrossMovesense.Current.ConnectionListener.DeviceDisconnected += async (s, a) =>
          {
              await DisplayAlert("Disconnection", $"Device {a.Serial} disconnected", "OK");
          };

    Note:

    • You will receive events for all devices, so if your application connects to multiple sensors, you must examine the MdsConnectionListenerEventArgs to determine which device is affected.
    • When a device disconnects, you may receive multiple DeviceDisconnected events.
    • If you try to use an IMovesenseDevice object when the device is disconnected, the call will return an exception.
    • After a device disconnects, MdsLib will continuously try to reconnect. If the connection is remade, you will get a DeviceConnectionComplete event. It is the responsibility of the application code to resubscribe to any sensor subscriptions after the device is reconnected.

Documentation

The Movesense.Net API offers a higher level abstraction above the REST API implemented in the native MDS libraries. It hides much of the low-level coding required to make direct REST-style API calls and offers simple to program methods to interact with most of the REST API.

Movesense .NET API

The Movesense API implements methods for most of the commonly used function in the Movesense API, as shown in the table below. If you need additional functions wrapping, contact us and we will implement in the next release. Alternatively, it is very easy to call functions not already implemented - see the Custom Service Sample] which shows how to call an endpoint on the Movesense Whiteboard. The sample shows how to call the Hello World custom resource, but the same logic applies to any of the core Movesense resources.

Movesense .NET Method Native Movesense API Description
IMovesense methods:
ConnectMdsAsync(System.Guid) Connect to a Movesense device
DisconnectMdsAsync(System.Guid) Disconnect from a Movesense device
IMovesenseDevice methods:
CreateLogEntry() POST /Mem/Logbook/Entries Create a new log entry resource
DeleteLogEntries() DELETE /Mem/Logbook/Entries Deletes the content of the whole Logbook
DisconnectMdsAsync() Disconnect from the Movesense device (alternative to IMovesense.DisconnectMdsAsync(System.Guid)
GetAccInfoAsync() GET /Meas/Acc/Info Get supported sample rates and ranges
GetAppInfoAsync() GET /Info/App Query for app information
GetBatteryLevelAsync() GET /System/Energy/Level Get estimated battery charge level
GetDeviceInfoAsync() GET /Info Query for device information
GetDetailedTimeAsync() GET /Time/Detailed Gets all current time related info in one go. This enables knowledge of RelativeTime and UTC time at the same instance, which is needed in multisensor use cases.
GetGyroInfoAsync() GET /Meas/Gyro/Info Get supported sample rates and ranges
GetIMUInfoAsync() GET /Meas/IMU/Info Get supported sample rates and ranges
GetLedsStateAsync() GET /Component/Leds Get leds in the system and their state (on/off & possible color)
GetLedStateAsync(int) GET /Component/Leds/{LedIndex} Get state of the specific led (on/off & possible color)
GetLogbookDataAsync(int) GET /MDS/Logbook/{serial}>/ByID/{ID}/Data Read SBEM data from a log entry and stream it
GetLogbookDataJsonAsync(int) GET /Mem/Logbook/byId/{LogId}/Data Get data from a Logbook entry as JSON using the MDS Logbook proxy service which takes care of paging and raw data to JSON conversion
GetLogbookDescriptorsAsync(int) GET /Mem/Logbook/byId/{LogId}/Descriptors Read training log descriptors and stream the descriptor file
GetLogEntriesAsync() GET /Mem/Logbook/Entries List Log contents
GetLogEntriesJsonAsync() GET /MDS/Logbook/{serial}>/Entries List Log contents as JSON using the MDS Logbook proxy service which takes care of paging and raw data to JSON conversion
GetLoggerStatusAsync() GET /Mem/DataLogger/State Reads current DataLogger state
GetMagInfoAsync() GET /Meas/Magn/Info Get info about the magnetometer
GetTimeAsync() GET /Time Gets current time in number of microseconds since epoch 1.1.1970 (UTC)
SetLedStateAsync(int, bool, LedColor) PUT /Component/Leds/{LedIndex} Write new state (on/off & color) for specific led
SetLoggerStatusAsync(int) PUT /Mem/DataLogger/State Changes DataLogger to a new state
SetTimeAsync() PUT /Time Sets current time in number of microseconds since epoch 1.1.1970 (UTC)
SetupLoggerAsync() PUT /Mem/DataLogger/Config Writes new DataLogger config to device
SubscribeAccelerometerAsync(Action, int) POST /Meas/Acc/{SampleRate}/Subscription Subscribe to periodic linear acceleration measurements
SubscribeGyrometerAsync(Action, int) POST /Meas/Gyro/{SampleRate}/Subscription Subscribe to periodic gyroscope measurements
SubscribeIMU6Async(Action, int) POST /Meas/IMU6/{SampleRate}/Subscription Subscribe to periodic 6-axis IMU measurements (Acc + Gyro)
SubscribeIMU9Async(Action, int) POST /Meas/IMU9/{SampleRate}/Subscription Subscribe to periodic 9-axis IMU measurements
SubscribeMagnetometerAsync(Action, int) POST /Meas/Magn/{SampleRate}/Subscription Subscribe to periodic magnetometer measurements

See [Movesense.Net Documentation](https://github.com/AndyCW/MovesenseDotNet/tree/master/Docs) for full details of the Movesense.Net API.

Samples

See Samples for sample applications using Movesense.Net.

Calling custom app resources, or REST endpoints not mapped to Movesense.Net methods

If you need to call a custom resource that is exposed by your own app running on a Movesense device, such as the Hello World sample included in the Movesense mobile-device-lib samples this is easily achieved. Simply call the ApiCallAsync method in the Plugin.Movesense API, where T is the return type of the resource (use string to just return the JSON response, or define the return type in your app and pass that whereupon ApiCallAsync will deserialize the JSON for you). The parameters you pass in the call to ApiCallAsync are the IMovesenseDevice object for the device, the type of operation (GET, POST, PUT, DELETE) and the path to the resource. You can use the same technique for REST endpoints not currently mapped to Movesense.Net API methods.

For example for a GET of the Hello World resource:

var helloWorldResponse = await Plugin.Movesense.CrossMovesense.Current.ApiCallAsync<string>(movesenseDevice, Plugin.Movesense.Api.MdsOp.GET, "/Sample/HelloWorld");

You can also use the ApiCallAsync method for operations that do not return a response, and you can use ApiSubscriptionAsync for subscriptions.

See the sample CustomServiceSample for an example.

Bluetooth device discovery

The Movesense Plugin does not manage Bluetooth discovery of Movesense devices. You must implement device discovery yourself. There are a number of different open source packages available to help with this. The samples in this repo use the Plugin.BluetoothLe NuGet package. Read the documentation and look carefully at the sample apps to learn how to integrate this package into your apps.

To scan for Movesense devices using BluetoothLe, use:

IDisposable scan;
CrossBleAdapter.Current.WhenStatusChanged().Subscribe(status =>
    {
        if (status == AdapterStatus.PoweredOn)
        {
            scan = this.BleAdapter.Scan()
            .Subscribe(this.OnScanResult);
        }
    });

Handle discovered devices in your Subscribe callback:

        void OnScanResult(IScanResult result)
        {
            // Only interested in Movesense devices
            if (result.Device.Name != null)
            {
                if (result.Device.Name.StartsWith("Movesense"))
                {
                    // Do something with this device...
                    var sensor = result.Device;
                }
            }
        }

Once you have discovered a device, you can make the MdsLib connection and then communicate with the device, as described in the previous section.

About

Movesense .NET SDK for Xamarin Android and Xamarin iOS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%