PSCommSimpleAndroid.cs

mail@pastecode.io avatar
unknown
css
2 years ago
16 kB
7
Indexable
Never
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using PalmSens.Comm;
using PalmSens.Devices;
using PalmSens.Core.Simplified.Data;
using System.Threading.Tasks;

namespace PalmSens.Core.Simplified.Android
{
    public class PSCommSimpleAndroid : View, IPlatform
    {
        public PSCommSimpleAndroid(Context context, IAttributeSet attrs) :
            base(context, attrs)
        {
            Initialize();
            _context = context;
        }

        public PSCommSimpleAndroid(Context context, IAttributeSet attrs, int defStyle) :
            base(context, attrs, defStyle)
        {
            Initialize();
        }

        private void Initialize()
        {
            this.Visibility = ViewStates.Gone;
            PalmSens.PSAndroid.Utils.CoreDependencies.Init(Context);
            InitAsyncFunctionality(System.Environment.ProcessorCount); //Initiate the asynchronous functions in the SDK
            _psCommSimple = new PSCommSimple(this);
            _deviceHandler = new DeviceHandler();
        }

        #region Properties
        /// <summary>
        /// Instance of the platform independent PSCommSimple class that manages measurements and manual control
        /// </summary>
        private PSCommSimple _psCommSimple;

        /// <summary>
        /// The context
        /// </summary>
        private Context _context;

        public Context CurrentContext
        {
            get
            {
                return _context;
            }
            set
            {
                _context = value;
                _deviceHandler.Context = _context;
            }
        }

        /// <summary>
        /// The device handler class which handles the connection to the device
        /// </summary>
        private DeviceHandler _deviceHandler;

        /// <summary>
        /// Gets the CommManager for the current connection.
        /// </summary>
        /// <value>
        /// The CommManager, null when there is no active connection to a device.
        /// </value>
        public CommManager Comm { get { return _psCommSimple.Comm; } }

        /// <summary>
        /// Gets a value indicating whether <see cref="PSCommSimple"/> is connected to a device.
        /// </summary>
        /// <value>
        ///   <c>true</c> if connected; otherwise, <c>false</c>.
        /// </value>
        public bool Connected { get { return _psCommSimple.Connected; } }

        /// <summary>
        /// Gets the connected device type.
        /// </summary>
        /// <value>
        /// The connected device type.
        /// </value>
        public enumDeviceType ConnectedDevice { get { return _psCommSimple.ConnectedDevice; } }

        /// <summary>
        /// Gets the state of the connected device.
        /// </summary>
        /// <value>
        /// The state of the device.
        /// </value>
        public CommManager.DeviceState DeviceState { get { return _psCommSimple.DeviceState; } }

        /// <summary>
        /// Gets a value indicating whether [cell is on].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [cell is on]; otherwise, <c>false</c>.
        /// </value>
        public bool CellOn { get { return _psCommSimple.IsCellOn; } }

        /// <summary>
        /// Gets the capabilities of the connected device.
        /// </summary>
        /// <value>
        /// The device capabilities.
        /// </value>
        public DeviceCapabilities Capabilities { get { return _psCommSimple.Capabilities; } }

        /// <summary>
        /// Gets or sets a value indicating whether to enable devices connected via bluetooth.
        /// </summary>
        /// <value>
        ///   <c>true</c> Enable scan for devices over bluetooth; Disable scan for devices over bluetooth <c>false</c>.
        /// </value>
        public bool EnableBluetooth
        {
            get { return _deviceHandler.EnableBluetooth; }
            set { _deviceHandler.EnableBluetooth = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether to enable devices connected via usb.
        /// </summary>
        /// <value>
        ///   <c>true</c> if [enable usb]; otherwise, <c>false</c>.
        /// </value>
        public bool EnableUSB
        {
            get { return _deviceHandler.EnableUSB; }
            set { _deviceHandler.EnableUSB= value; }
        }

        /// <summary>
        /// Determines whether [the specified method] is compatible with the device.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <returns>
        ///   <c>true</c> if the method is valid; otherwise, <c>false</c>.
        /// </returns>
        public bool IsValidMethod(Method method)
        {
            return _psCommSimple.IsValidMethod(method);
        }
        #endregion

        #region Functions        
        /// <summary>
        /// Required initialization for using the async functionalities of the PalmSens SDK.
        /// The amount of simultaneous operations will be limited to prevent performance issues.
        /// When possible it will leave one core free for the UI.
        /// </summary>
        /// <param name="nCores">The number of CPU cores.</param>
        /// <summary>
        /// Try and pause or resume the measurement.
        /// </summary>
        /// <param name="measurement">The measurement to try and pause or resume.</param>
        /// <returns>A true if the measurement has been toggled between pause and resume</returns>
        public bool TryPauseResume(Measurement measurement)
        {
            return _psCommSimple.TryPauseResume(measurement);
        }

        /// <summary>
        /// Try and pause or resume the measurement.
        /// </summary>
        /// <param name="measurement">The measurement to try and pause or resume.</param>
        /// <returns>A true if the measurement has been toggled between pause and resume</returns>
        public Task<bool> TryPauseResumeAsync(Measurement measurement)
        {
            return _psCommSimple.TryPauseResumeAsync(measurement);
        }
        private void InitAsyncFunctionality(int nCores)
        {
            SynchronizationContextRemover.Init(nCores > 1 ? nCores - 1 : 1);
        }
        ///<summary>
        ///Export
        public static IEnumerable<(double x, double y)> ExportData(SimpleCurve curve)
        {
            var xValues = curve.XAxisValues;
            var yValues = curve.YAxisValues;
            for (int i = 0; i < xValues.Length; i++)
            {
                yield return ValueTuple.Create(xValues[i], yValues[i]);
            }
        }


        /// <summary>
        /// Returns an array of connected devices.
        /// </summary>
        /// <param name="timeOut">Discovery time out in milliseconds.</param>
        /// <returns></returns>
        /// <value>
        /// The connected devices.
        /// </value>
        public async Task<Device[]> GetConnectedDevices(int timeOut = 20000) { return await _deviceHandler.ScanDevicesAsync(timeOut); }

        /// <summary>
        /// Connects to the specified device.
        /// </summary>
        /// <param name="device">The device.</param>
        public async Task Connect(Device device)
        {
            _psCommSimple.Comm = await _deviceHandler.Connect(device);
        }
        
        /// <summary>
        /// Disconnects from the connected device.
        /// </summary>
        public async Task Disconnect()
        {
            await _psCommSimple.DisconnectAsync();
        }

        /// <summary>
        /// Turns the cell on.
        /// </summary>
        public async Task TurnCellOn()
        {
            await _psCommSimple.TurnCellOnAsync();
        }

        /// <summary>
        /// Turns the cell off.
        /// </summary>
        public async Task TurnCellOff()
        {
            await _psCommSimple.TurnCellOffAsync();
        }

        /// <summary>
        /// Sets the cell potential.
        /// </summary>
        /// <param name="potential">The potential.</param>
        public async Task SetCellPotential(float potential)
        {
            await _psCommSimple.SetCellPotentialAsync(potential);
        }

        /// <summary>
        /// Reads the cell potential.
        /// </summary>
        /// <returns>The potential (V).</returns>
        public async Task<float> ReadCellPotential()
        {
            return await _psCommSimple.ReadCellPotentialAsync();
        }

        /// <summary>
        /// Sets the cell current.
        /// </summary>
        /// <param name="current">The current.</param>
        public async Task SetCellCurrent(float current)
        {
            await _psCommSimple.SetCellCurrentAsync(current);
        }

        /// <summary>
        /// Reads the cell current.
        /// </summary>
        /// <returns>The current (µA).</returns>
        public async Task<float> ReadCellCurrent()
        {
            return await _psCommSimple.ReadCellCurrentAsync();
        }

        /// <summary>
        /// Sets the current range.
        /// </summary>
        /// <param name="currentRange">The current range.</param>
        public async Task SetCurrentRange(CurrentRange currentRange)
        {
            await _psCommSimple.SetCurrentRangeAsync(currentRange);
        }

        /// <summary>
        /// Runs a measurement as specified in the method on the connected device.
        /// </summary>
        /// <param name="method">The method containing the measurement parameters.</param>
        /// <param name="muxChannel">The mux channel to measure on.</param>
        /// <returns>
        /// A SimpleMeasurement instance containing all the data related to the measurement.
        /// </returns>
        /// <exception cref="System.NullReferenceException">Not connected to a device.</exception>
        /// <exception cref="System.ArgumentException">Method is incompatible with the connected device.</exception>
        /// <exception cref="System.Exception">Could not start measurement.</exception>
        public async Task<SimpleMeasurement> Measure(Method method, int muxChannel)
        {
            return await _psCommSimple.MeasureAsync(method, muxChannel);
        }

        /// <summary>
        /// Runs a measurement as specified in the method on the connected device.
        /// </summary>
        /// <param name="method">The method containing the measurement parameters.</param>
        /// <returns>A SimpleMeasurement instance containing all the data related to the measurement.</returns>
        public async Task<SimpleMeasurement> Measure(Method method)
        {
            return await _psCommSimple.MeasureAsync(method);
        }

        /// <summary>
        /// Aborts the current active measurement.
        /// </summary>
        public async Task AbortMeasurement()
        {
            await _psCommSimple.AbortMeasurementAsync();
        }

        /// <summary>
        /// Validates whether the specified method is compatible with the capabilities of the connected device.
        /// </summary>
        /// <param name="method">The method containing the measurement parameters.</param>
        /// <param name="isValidMethod">if set to <c>true</c> [is valid method].</param>
        /// <param name="errors">The errors.</param>
        /// <exception cref="System.NullReferenceException">Not connected to a device.</exception>
        /// <exception cref="System.ArgumentNullException">The specified method cannot be null.</exception>
        public void ValidateMethod(Method method, out bool isValidMethod, out List<string> errors)
        {
            _psCommSimple.ValidateMethod(method, out isValidMethod, out errors);
        }
        #endregion

        #region Platform interface
        Handler mainHandler = new Handler(Looper.MainLooper);

        /// <summary>
        /// Invokes event to UI thread if required.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        /// <exception cref="System.NullReferenceException">Parent control not set.</exception>
        public bool InvokeIfRequired(Delegate method, params object[] args)
        {
            if (Looper.MyLooper() != Looper.MainLooper)//Check if event needs to be cast to the UI thread
            {
                mainHandler.Post(() => method.DynamicInvoke(args)); //Recast event to UI thread                
                return true;
            }
            return false;
        }

        /// <summary>
        /// Disconnects from device with the specified CommManager. 
        /// Warning use the platform independent method Disconnect() instead.
        /// Otherwise the generic PSCommSimple does not unsubscribe from the CommManager correctly
        /// which may result in it not being released from the memory.
        /// </summary>
        /// <param name="comm">The comm.</param>
        public void Disconnect(CommManager comm)
        {
            _deviceHandler.Disconnect(comm);
        }
        #endregion

        #region events
        /// <summary>
        /// Occurs when a device status package is received, these packages are not sent during a measurement.
        /// </summary>
        public event StatusEventHandler ReceiveStatus
        {
            add { _psCommSimple.ReceiveStatus += value; }
            remove { _psCommSimple.ReceiveStatus -= value; }
        }

        /// <summary>
        /// Occurs at the start of a new measurement.
        /// </summary>
        public event EventHandler MeasurementStarted
        {
            add { _psCommSimple.MeasurementStarted += value; }
            remove { _psCommSimple.MeasurementStarted -= value; }
        }

        /// <summary>
        /// Occurs when a measurement has ended.
        /// </summary>
        public event EventHandler MeasurementEnded
        {
            add { _psCommSimple.MeasurementEnded += value; }
            remove { _psCommSimple.MeasurementEnded -= value; }
        }

        /// <summary>
        /// Occurs when a new [SimpleCurve starts receiving data].
        /// </summary>
        public event PSCommSimple.SimpleCurveStartReceivingDataHandler SimpleCurveStartReceivingData
        {
            add { _psCommSimple.SimpleCurveStartReceivingData += value; }
            remove { _psCommSimple.SimpleCurveStartReceivingData -= value; }
        }

        /// <summary>
        /// Occurs when the devive's [state changed].
        /// </summary>
        public event CommManager.StatusChangedEventHandler StateChanged
        {
            add { _psCommSimple.StateChanged += value; }
            remove { _psCommSimple.StateChanged -= value; }
        }

        /// <summary>
        /// Occurs when a device is [disconnected].
        /// </summary>
        public event DisconnectedEventHandler Disconnected
        {
            add { _psCommSimple.Disconnected += value; }
            remove { _psCommSimple.Disconnected -= value; }
        }
        #endregion
    }
}