Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 21.14 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using System.Threading;
  4. using System.Diagnostics;
  5. using System.Threading.Tasks;
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using Plugin.BLE;
  9. using Plugin.BLE.Abstractions;
  10. using Plugin.BLE.Abstractions.Contracts;
  11. using MvvmCross.Platform;
  12. using Leaware.MvvmCross.Logger;
  13. using Leaware.MvvmCross.TranslatePlugin;
  14. using AgrippaHMS.DataAccess;
  15.  
  16. namespace AgrippaHMS.Core
  17. {
  18.     public class BleScanner
  19.     {
  20.         #region Const
  21.         private const int CONNECTING_TIMEOUT = 30000;
  22.         public readonly static int SCANNING_DURATION = 30000; //30 sek
  23.         #endregion
  24.  
  25.         #region Fields [public]
  26.         public List<CurrentSensorTemperaturesData> TemperatureData = new List<CurrentSensorTemperaturesData>();
  27.         #endregion
  28.  
  29.         #region Fields [private]
  30.         private bool readStoredDataMode;
  31.         private string deviceAddress;
  32.         private readonly IBluetoothLE bluetoothLE;
  33.         private List<IDevice> devices = new List<IDevice>();
  34.         #endregion
  35.  
  36.         #region Properties
  37.         private ITranslatePlugin translate;
  38.         public ITranslatePlugin Translate
  39.         {
  40.             get
  41.             {
  42.                 if (translate == null)
  43.                 {
  44.                     translate = Mvx.Resolve<ITranslatePlugin>();
  45.                 }
  46.                 return translate;
  47.             }
  48.         }
  49.  
  50.         private ObservableCollection<BluetoothSensorDevice> collection;
  51.         public ObservableCollection<BluetoothSensorDevice> Collection
  52.         {
  53.             get
  54.             {
  55.                 if (collection == null)
  56.                 {
  57.                     collection = new ObservableCollection<BluetoothSensorDevice>();
  58.                 }
  59.  
  60.                 return collection;
  61.             }
  62.             set
  63.             {
  64.                 collection = value;
  65.             }
  66.         }
  67.  
  68.         private IBleScannerService bleScannerService;
  69.         private IBleScannerService BleScannerService
  70.         {
  71.             get
  72.             {
  73.                 if (bleScannerService == null)
  74.                 {
  75.                     bleScannerService = Mvx.Resolve<IBleScannerService>();
  76.                 }
  77.  
  78.                 return bleScannerService;
  79.             }
  80.         }
  81.  
  82.         public IAdapter Adapter { get; set; }
  83.  
  84.         public Action OnDeviceUpdate
  85.         {
  86.             get;
  87.             set;
  88.         }
  89.  
  90.         public Action OnDeviceConnectionFailure
  91.         {
  92.             get;
  93.             set;
  94.         }
  95.  
  96.         public Action OnReadFailure
  97.         {
  98.             get;
  99.             set;
  100.         }
  101.  
  102.         public Action<string> OnConnectionProgressChange
  103.         {
  104.             get;
  105.             set;
  106.         }
  107.         #endregion
  108.  
  109.         #region Cnt
  110.         public BleScanner()
  111.         {
  112.             bluetoothLE = CrossBluetoothLE.Current;
  113.             Adapter = CrossBluetoothLE.Current.Adapter;
  114.         }
  115.         #endregion
  116.  
  117.         #region Methods [public]
  118.         public async Task ScanForDevices()
  119.         {
  120.             Adapter.DeviceDiscovered -= Adapter_DeviceDiscovered;
  121.  
  122.             Adapter.DeviceAdvertised -= Adapter_DeviceAdvertised;
  123.  
  124.             Adapter.DeviceDiscovered += Adapter_DeviceDiscovered;
  125.  
  126.             Adapter.DeviceAdvertised += Adapter_DeviceAdvertised;
  127.  
  128.             Adapter.ScanTimeout = SCANNING_DURATION;
  129.  
  130.             await Adapter.StartScanningForDevicesAsync();
  131.         }
  132.  
  133.         public async Task<List<CurrentSensorTemperaturesData>> ReadStoredDataFromDevice(string address, CancellationTokenSource cts = null)
  134.         {
  135.             TemperatureData = new List<CurrentSensorTemperaturesData>();
  136.  
  137.             var deviceToConnect = devices.Where(dev => BleScannerService.GetAdressFromDevice(dev) == address).FirstOrDefault();
  138.             var isConnectingFinished = default(bool);
  139.             var isInitialSetupCompleted = default(bool);
  140.  
  141.             var configService = default(IService);
  142.             var temperatureService = default(IService);
  143.  
  144.             var contentCharacteristic = default(ICharacteristic);
  145.             var temperatureEnableCharacteristic = default(ICharacteristic);
  146.             var configCharacteristic = default(ICharacteristic);
  147.             var numberOfBytesCharacteristic = default(ICharacteristic);
  148.  
  149.             if (!cts.IsCancellationRequested)
  150.             {
  151.                 OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceProgress"));
  152.             }
  153.  
  154.             if (deviceToConnect != null)
  155.             {
  156.                 try
  157.                 {
  158.                     deviceAddress = BleScannerService.GetAdressFromDevice(deviceToConnect);
  159.  
  160.                     var ct = default(CancellationToken);
  161.  
  162.                     if (cts != null)
  163.                     {
  164.                         ct = cts.Token;
  165.                     }
  166.  
  167.                     var ctTimeout = new CancellationTokenSource().Token;
  168.  
  169.                     Task.Run(async () =>
  170.                     {
  171.                         await Task.Delay(CONNECTING_TIMEOUT);
  172.  
  173.                         if (!isConnectingFinished)
  174.                         {
  175.                             ctTimeout.ThrowIfCancellationRequested();
  176.                         }
  177.                     });
  178.  
  179.                     await Adapter.ConnectToDeviceAsync(deviceToConnect, ConnectParameters.None, ctTimeout);
  180.  
  181.                     if (!cts.IsCancellationRequested)
  182.                     {
  183.                         OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceFinishedProgress"));
  184.                     }
  185.  
  186.                     isConnectingFinished = true;
  187.  
  188.                     //get configuration service
  189.                     configService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.CONFIGURATION_SERVICE));
  190.  
  191.                     //get temperature/humidity service
  192.                     temperatureService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_SERVICE));
  193.  
  194.                     //get advertisement config characteristic
  195.                     configCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.CONFIG_REGISTER));
  196.  
  197.                     //get temperature enable/disable characteristic
  198.                     temperatureEnableCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_ENABLE));
  199.  
  200.                     //get content of flash characteristic
  201.                     contentCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.CONTENT_OF_FLASH));
  202.  
  203.                     //get number of bytes characteristic
  204.                     numberOfBytesCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.NUMBER_OF_BYTES));
  205.  
  206.                     //disable temperature/humidity characteristic
  207.                     await temperatureEnableCharacteristic.WriteAsync(new byte[] { 0x00 });
  208.  
  209.                     isInitialSetupCompleted = true;
  210.  
  211.                     byte[] record = default(byte[]);
  212.  
  213.                     if (!cts.IsCancellationRequested)
  214.                     {
  215.                         OnConnectionProgressChange?.Invoke(Translate.GetText("BeginReadingDataProgress"));
  216.                     }
  217.  
  218.                     int numberOfReadings = default(int);
  219.  
  220.                     try
  221.                     {
  222.                         var numberOfBytes = await numberOfBytesCharacteristic.ReadAsync();
  223.                         var numberOfBytesInt = BitConverter.ToInt32(numberOfBytes, 0);
  224.                         numberOfReadings = numberOfBytesInt / 8;
  225.                     }
  226.                     catch (Exception ex)
  227.                     {
  228.                         Debug.WriteLine($"BLE Sensor Error: {ex.Message}");
  229.                         Logger.Instance.Error($"BLE Sensor Error: {ex.Message}");
  230.                     }
  231.  
  232.                     int i = 0;
  233.  
  234.                     do
  235.                     {
  236.                         if (cts.IsCancellationRequested)
  237.                         {
  238.                             break;
  239.                         }
  240.  
  241.                         List<byte[]> data = new List<byte[]>();
  242.  
  243.                         record = default(byte[]);
  244.                         record = await contentCharacteristic.ReadAsync();
  245.  
  246.                         if (record != null)
  247.                         {
  248.                             if (record.Length > 8)
  249.                             {
  250.                                 var byteArray1 = new byte[8];
  251.                                 Array.Copy(record, 0, byteArray1, 0, 8);
  252.                                 data.Add(byteArray1);
  253.  
  254.                                 var byteArray2 = new byte[8];
  255.                                 Array.Copy(record, 8, byteArray2, 0, 8);
  256.                                 data.Add(byteArray2);
  257.                             }
  258.                             else
  259.                             {
  260.                                 data.Add(record);
  261.                             }
  262.  
  263.                             foreach (var word in data)
  264.                             {
  265.                                 var dateTimeBytes = new byte[4];
  266.                                 var humidityBytes = new byte[2];
  267.                                 var temperatureBytes = new byte[2];
  268.  
  269.                                 Array.Copy(word, 0, dateTimeBytes, 0, 4);
  270.                                 Array.Copy(word, 4, temperatureBytes, 0, 2);
  271.                                 Array.Copy(word, 6, humidityBytes, 0, 2);
  272.  
  273.                                 double timeStamp = BitConverter.ToInt32(dateTimeBytes, 0);
  274.  
  275.                                 var currentSensorTemperaturesData = default(CurrentSensorTemperaturesData);
  276.  
  277.                                 currentSensorTemperaturesData = new CurrentSensorTemperaturesData()
  278.                                 {
  279.                                     CreatedDate = BleBitConverter.UtcTimeStampToDateTime(timeStamp),
  280.                                     Humidity = Convert.ToSingle(BleBitConverter.Humidity(humidityBytes)),
  281.                                     Temperature = Convert.ToSingle(BleBitConverter.Temperature(temperatureBytes))
  282.                                 };
  283.  
  284.                                 if (TemperatureData.Count > 0)
  285.                                 {
  286.                                     var prevousItem = TemperatureData.LastOrDefault();
  287.  
  288.                                     if (prevousItem.CreatedDate.Equals(currentSensorTemperaturesData.CreatedDate) || prevousItem.CreatedDate > currentSensorTemperaturesData.CreatedDate)
  289.                                     {
  290.                                         record = null;
  291.                                         break;
  292.                                     }
  293.                                     else
  294.                                     {
  295.                                         TemperatureData.Add(currentSensorTemperaturesData);
  296.                                     }
  297.                                 }
  298.                                 else
  299.                                 {
  300.                                     TemperatureData.Add(currentSensorTemperaturesData);
  301.                                 }
  302.  
  303.                                 i++;
  304.  
  305.                                 if (!cts.IsCancellationRequested)
  306.                                 {
  307.                                     OnConnectionProgressChange?.Invoke(Translate.GetText("ReadNoProgress", i, numberOfReadings));
  308.                                 }
  309.                             }
  310.                         }
  311.                     }
  312.                     while (record != null);
  313.  
  314.                     if (!cts.IsCancellationRequested)
  315.                     {
  316.                         OnConnectionProgressChange?.Invoke(Translate.GetText("ReadingFinishedProgress"));
  317.                     }
  318.  
  319.                     if (TemperatureData != null && TemperatureData.Count <= 1)
  320.                     {
  321.                         if (!cts.IsCancellationRequested)
  322.                         {
  323.                             OnReadFailure?.Invoke();
  324.                         }
  325.                     }
  326.                 }
  327.                 catch (Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException ex)
  328.                 {
  329.                     //iOS is getting here when there is no more data to receive
  330.                     if (!cts.IsCancellationRequested)
  331.                     {
  332.                         OnConnectionProgressChange?.Invoke(Translate.GetText("ReadingFinishedProgress"));
  333.                     }
  334.  
  335.                     if (TemperatureData != null && TemperatureData.Count <= 1)
  336.                     {
  337.                         if (!cts.IsCancellationRequested)
  338.                         {
  339.                             OnReadFailure?.Invoke();
  340.                         }
  341.                     }
  342.  
  343.                     Debug.WriteLine(ex);
  344.                 }
  345.                 catch (NullReferenceException ex)
  346.                 {
  347.                     Debug.WriteLine(ex);
  348.                     OnDeviceConnectionFailure?.Invoke();
  349.                 }
  350.                 catch (Exception ex)
  351.                 {
  352.                     if (!cts.IsCancellationRequested)
  353.                     {
  354.                         System.Diagnostics.Debug.WriteLine(ex);
  355.                         OnDeviceConnectionFailure?.Invoke();
  356.                     }
  357.                 }
  358.                 finally
  359.                 {
  360.                     Task.Run(async() =>
  361.                     {
  362.                         if (isInitialSetupCompleted)
  363.                         {
  364.                             if (cts.IsCancellationRequested)
  365.                             {
  366.                                 await configCharacteristic.WriteAsync(new byte[] { 0x0D });
  367.                             }
  368.                             else
  369.                             {
  370.                                 await configCharacteristic.WriteAsync(new byte[] { 0x0F });
  371.                             }
  372.  
  373.                             await Task.Delay(3000);
  374.  
  375.                             await temperatureEnableCharacteristic.WriteAsync(new byte[] { 0x01 });
  376.                         }
  377.  
  378.                         await Adapter.DisconnectDeviceAsync(deviceToConnect);
  379.                     });
  380.                 }
  381.             }
  382.  
  383.             return TemperatureData;
  384.         }
  385.  
  386.         public async Task WakeUpBleDevice(string address, CancellationTokenSource cts = null)
  387.         {
  388.             var deviceToConnect = devices.Where(dev => BleScannerService.GetAdressFromDevice(dev) == address).FirstOrDefault();
  389.  
  390.             if (deviceToConnect != null)
  391.             {
  392.                 try
  393.                 {
  394.                     bool isConnectingFinished = default(bool);
  395.                     deviceAddress = BleScannerService.GetAdressFromDevice(deviceToConnect);
  396.  
  397.                     var ct = cts.Token;
  398.  
  399.                     Task.Run(async () =>
  400.                     {
  401.                         await Task.Delay(CONNECTING_TIMEOUT);
  402.  
  403.                         if (!isConnectingFinished)
  404.                         {
  405.                             ct.ThrowIfCancellationRequested();
  406.                         }
  407.                     });
  408.  
  409.                     OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceProgress"));
  410.  
  411.                     await Adapter.ConnectToDeviceAsync(deviceToConnect, ConnectParameters.None, ct);
  412.  
  413.                     OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceFinishedProgress"));
  414.  
  415.                     isConnectingFinished = true;
  416.  
  417.                     OnConnectionProgressChange?.Invoke(Translate.GetText("ConfiguringDeviceProgress"));
  418.  
  419.                     var configService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.CONFIGURATION_SERVICE), ct);
  420.                     var temperatureService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_SERVICE), ct);
  421.  
  422.                     //Disable temperature/humidity sensor
  423.                     var temperatureSensorEnableCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_ENABLE));
  424.                     await temperatureSensorEnableCharacteristic.WriteAsync(new byte[] { 0x00 }, ct);
  425.  
  426.                     //Set time
  427.                     var setDateTimeCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.CURRENT_DATETIME));
  428.                     var epoch = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
  429.                     var epochInt = (int)epoch;
  430.                     await setDateTimeCharacteristic.WriteAsync(BitConverter.GetBytes(epochInt), ct);
  431.  
  432.                     // Setting advertising interval
  433.                     var setAdvertisingDurationCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.DESCOVERABLE_INTERVAL));
  434.                     await setAdvertisingDurationCharacteristic.WriteAsync(new byte[] { 0x01 }, ct);
  435.  
  436.                     // Setting temperature/humidity sensor update interval
  437.                     var setTemperatureUpdateSensorItervalCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_INTERVAL));
  438.                     await setTemperatureUpdateSensorItervalCharacteristic.WriteAsync(new byte[] { 0x1E }, ct);
  439.  
  440.                     //Enable temperature/humidity sensor
  441.                     await temperatureSensorEnableCharacteristic.WriteAsync(new byte[] { 0x01 }, ct);
  442.  
  443.                     // Setting advertising
  444.                     var setAdvertisingService = await configService.GetCharacteristicAsync(new Guid(GattAttributes.CONFIG_REGISTER));
  445.                     await setAdvertisingService.WriteAsync(new byte[] { 0x0F }, ct);
  446.  
  447.                     OnConnectionProgressChange?.Invoke(Translate.GetText("ConfiguringDeviceFinishedProgress"));
  448.                 }
  449.                 catch (Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException ex)
  450.                 {
  451.                     if (!cts.IsCancellationRequested)
  452.                     {
  453.                         OnReadFailure?.Invoke();
  454.                         System.Diagnostics.Debug.WriteLine(ex);
  455.                     }
  456.                 }
  457.                 catch (Exception ex)
  458.                 {
  459.                     if (!cts.IsCancellationRequested)
  460.                     {
  461.                         OnDeviceConnectionFailure?.Invoke();
  462.                         System.Diagnostics.Debug.WriteLine(ex);
  463.                     }
  464.                 }
  465.                 finally
  466.                 {
  467.                     await Adapter.DisconnectDeviceAsync(deviceToConnect);
  468.                 }
  469.             }
  470.         }
  471.  
  472.         public async Task StopScaning()
  473.         {
  474.             await Adapter.StopScanningForDevicesAsync();
  475.         }
  476.  
  477.         public void SortList()
  478.         {
  479.             Collection = new ObservableCollection<BluetoothSensorDevice>(Collection.OrderByDescending(i => i.Rssi));
  480.         }
  481.         #endregion
  482.  
  483.         #region Methods [private]
  484.         private void Adapter_DeviceDiscovered(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
  485.         {
  486.             try
  487.             {
  488.                 var device = e.Device;
  489.  
  490.                 if (BleScannerService.CheckIfDeviceTypeIsLe(device))
  491.                 {
  492.                     var knownDevice = Collection.Where(dev => dev.Address == BleScannerService.GetAdressFromDevice(device)).FirstOrDefault();
  493.  
  494.                     if (knownDevice == null)
  495.                     {
  496.                         var newItem = BleScannerService.ReadOrUpdateAdvertisementsData(device);
  497.                         Collection.Add(newItem);
  498.                         devices.Add(device);
  499.  
  500.                         OnDeviceUpdate?.Invoke();
  501.                     }
  502.                 }
  503.             }
  504.             catch(Exception ex)
  505.             {
  506.                 Debug.WriteLine($"BLE Sensor Error: {ex.Message}");
  507.                 Logger.Instance.Error($"BLE Sensor Error: {ex.Message}");
  508.                 Utils.Logger.Instance.SendLog($"BLE Sensor Error: {ex.Message}", null, LogType.Error);
  509.             }
  510.         }
  511.  
  512.         private async void Adapter_DeviceAdvertised(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
  513.         {
  514.             try
  515.             {
  516.                 var device = e.Device;
  517.                 var knownDevice = Collection.Where(dev => dev.Address == BleScannerService.GetAdressFromDevice(device)).FirstOrDefault();
  518.  
  519.                 if (knownDevice != null)
  520.                 {
  521.                     var updatedData = BleScannerService.ReadOrUpdateAdvertisementsData(device);
  522.  
  523.                     knownDevice.Rssi = updatedData.Rssi;
  524.                     knownDevice.Temperature = updatedData.Temperature;
  525.                     knownDevice.Humidity = updatedData.Humidity;
  526.  
  527.                     OnDeviceUpdate?.Invoke();
  528.                 }
  529.             }
  530.             catch (Exception ex)
  531.             {
  532.                 Debug.WriteLine($"BLE Sensor Error: {ex.Message}");
  533.                 Logger.Instance.Error($"BLE Sensor Error: {ex.Message}");
  534.                 Utils.Logger.Instance.SendLog($"BLE Sensor Error: {ex.Message}", null, LogType.Error);
  535.             }
  536.         }
  537.         #endregion
  538.     }
  539. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement