Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Linq;
- using System.Threading;
- using System.Diagnostics;
- using System.Threading.Tasks;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using Plugin.BLE;
- using Plugin.BLE.Abstractions;
- using Plugin.BLE.Abstractions.Contracts;
- using MvvmCross.Platform;
- using Leaware.MvvmCross.Logger;
- using Leaware.MvvmCross.TranslatePlugin;
- using AgrippaHMS.DataAccess;
- namespace AgrippaHMS.Core
- {
- public class BleScanner
- {
- #region Const
- private const int CONNECTING_TIMEOUT = 30000;
- public readonly static int SCANNING_DURATION = 30000; //30 sek
- #endregion
- #region Fields [public]
- public List<CurrentSensorTemperaturesData> TemperatureData = new List<CurrentSensorTemperaturesData>();
- #endregion
- #region Fields [private]
- private bool readStoredDataMode;
- private string deviceAddress;
- private readonly IBluetoothLE bluetoothLE;
- private List<IDevice> devices = new List<IDevice>();
- #endregion
- #region Properties
- private ITranslatePlugin translate;
- public ITranslatePlugin Translate
- {
- get
- {
- if (translate == null)
- {
- translate = Mvx.Resolve<ITranslatePlugin>();
- }
- return translate;
- }
- }
- private ObservableCollection<BluetoothSensorDevice> collection;
- public ObservableCollection<BluetoothSensorDevice> Collection
- {
- get
- {
- if (collection == null)
- {
- collection = new ObservableCollection<BluetoothSensorDevice>();
- }
- return collection;
- }
- set
- {
- collection = value;
- }
- }
- private IBleScannerService bleScannerService;
- private IBleScannerService BleScannerService
- {
- get
- {
- if (bleScannerService == null)
- {
- bleScannerService = Mvx.Resolve<IBleScannerService>();
- }
- return bleScannerService;
- }
- }
- public IAdapter Adapter { get; set; }
- public Action OnDeviceUpdate
- {
- get;
- set;
- }
- public Action OnDeviceConnectionFailure
- {
- get;
- set;
- }
- public Action OnReadFailure
- {
- get;
- set;
- }
- public Action<string> OnConnectionProgressChange
- {
- get;
- set;
- }
- #endregion
- #region Cnt
- public BleScanner()
- {
- bluetoothLE = CrossBluetoothLE.Current;
- Adapter = CrossBluetoothLE.Current.Adapter;
- }
- #endregion
- #region Methods [public]
- public async Task ScanForDevices()
- {
- Adapter.DeviceDiscovered -= Adapter_DeviceDiscovered;
- Adapter.DeviceAdvertised -= Adapter_DeviceAdvertised;
- Adapter.DeviceDiscovered += Adapter_DeviceDiscovered;
- Adapter.DeviceAdvertised += Adapter_DeviceAdvertised;
- Adapter.ScanTimeout = SCANNING_DURATION;
- await Adapter.StartScanningForDevicesAsync();
- }
- public async Task<List<CurrentSensorTemperaturesData>> ReadStoredDataFromDevice(string address, CancellationTokenSource cts = null)
- {
- TemperatureData = new List<CurrentSensorTemperaturesData>();
- var deviceToConnect = devices.Where(dev => BleScannerService.GetAdressFromDevice(dev) == address).FirstOrDefault();
- var isConnectingFinished = default(bool);
- var isInitialSetupCompleted = default(bool);
- var configService = default(IService);
- var temperatureService = default(IService);
- var contentCharacteristic = default(ICharacteristic);
- var temperatureEnableCharacteristic = default(ICharacteristic);
- var configCharacteristic = default(ICharacteristic);
- var numberOfBytesCharacteristic = default(ICharacteristic);
- if (!cts.IsCancellationRequested)
- {
- OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceProgress"));
- }
- if (deviceToConnect != null)
- {
- try
- {
- deviceAddress = BleScannerService.GetAdressFromDevice(deviceToConnect);
- var ct = default(CancellationToken);
- if (cts != null)
- {
- ct = cts.Token;
- }
- var ctTimeout = new CancellationTokenSource().Token;
- Task.Run(async () =>
- {
- await Task.Delay(CONNECTING_TIMEOUT);
- if (!isConnectingFinished)
- {
- ctTimeout.ThrowIfCancellationRequested();
- }
- });
- await Adapter.ConnectToDeviceAsync(deviceToConnect, ConnectParameters.None, ctTimeout);
- if (!cts.IsCancellationRequested)
- {
- OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceFinishedProgress"));
- }
- isConnectingFinished = true;
- //get configuration service
- configService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.CONFIGURATION_SERVICE));
- //get temperature/humidity service
- temperatureService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_SERVICE));
- //get advertisement config characteristic
- configCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.CONFIG_REGISTER));
- //get temperature enable/disable characteristic
- temperatureEnableCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_ENABLE));
- //get content of flash characteristic
- contentCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.CONTENT_OF_FLASH));
- //get number of bytes characteristic
- numberOfBytesCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.NUMBER_OF_BYTES));
- //disable temperature/humidity characteristic
- await temperatureEnableCharacteristic.WriteAsync(new byte[] { 0x00 });
- isInitialSetupCompleted = true;
- byte[] record = default(byte[]);
- if (!cts.IsCancellationRequested)
- {
- OnConnectionProgressChange?.Invoke(Translate.GetText("BeginReadingDataProgress"));
- }
- int numberOfReadings = default(int);
- try
- {
- var numberOfBytes = await numberOfBytesCharacteristic.ReadAsync();
- var numberOfBytesInt = BitConverter.ToInt32(numberOfBytes, 0);
- numberOfReadings = numberOfBytesInt / 8;
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"BLE Sensor Error: {ex.Message}");
- Logger.Instance.Error($"BLE Sensor Error: {ex.Message}");
- }
- int i = 0;
- do
- {
- if (cts.IsCancellationRequested)
- {
- break;
- }
- List<byte[]> data = new List<byte[]>();
- record = default(byte[]);
- record = await contentCharacteristic.ReadAsync();
- if (record != null)
- {
- if (record.Length > 8)
- {
- var byteArray1 = new byte[8];
- Array.Copy(record, 0, byteArray1, 0, 8);
- data.Add(byteArray1);
- var byteArray2 = new byte[8];
- Array.Copy(record, 8, byteArray2, 0, 8);
- data.Add(byteArray2);
- }
- else
- {
- data.Add(record);
- }
- foreach (var word in data)
- {
- var dateTimeBytes = new byte[4];
- var humidityBytes = new byte[2];
- var temperatureBytes = new byte[2];
- Array.Copy(word, 0, dateTimeBytes, 0, 4);
- Array.Copy(word, 4, temperatureBytes, 0, 2);
- Array.Copy(word, 6, humidityBytes, 0, 2);
- double timeStamp = BitConverter.ToInt32(dateTimeBytes, 0);
- var currentSensorTemperaturesData = default(CurrentSensorTemperaturesData);
- currentSensorTemperaturesData = new CurrentSensorTemperaturesData()
- {
- CreatedDate = BleBitConverter.UtcTimeStampToDateTime(timeStamp),
- Humidity = Convert.ToSingle(BleBitConverter.Humidity(humidityBytes)),
- Temperature = Convert.ToSingle(BleBitConverter.Temperature(temperatureBytes))
- };
- if (TemperatureData.Count > 0)
- {
- var prevousItem = TemperatureData.LastOrDefault();
- if (prevousItem.CreatedDate.Equals(currentSensorTemperaturesData.CreatedDate) || prevousItem.CreatedDate > currentSensorTemperaturesData.CreatedDate)
- {
- record = null;
- break;
- }
- else
- {
- TemperatureData.Add(currentSensorTemperaturesData);
- }
- }
- else
- {
- TemperatureData.Add(currentSensorTemperaturesData);
- }
- i++;
- if (!cts.IsCancellationRequested)
- {
- OnConnectionProgressChange?.Invoke(Translate.GetText("ReadNoProgress", i, numberOfReadings));
- }
- }
- }
- }
- while (record != null);
- if (!cts.IsCancellationRequested)
- {
- OnConnectionProgressChange?.Invoke(Translate.GetText("ReadingFinishedProgress"));
- }
- if (TemperatureData != null && TemperatureData.Count <= 1)
- {
- if (!cts.IsCancellationRequested)
- {
- OnReadFailure?.Invoke();
- }
- }
- }
- catch (Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException ex)
- {
- //iOS is getting here when there is no more data to receive
- if (!cts.IsCancellationRequested)
- {
- OnConnectionProgressChange?.Invoke(Translate.GetText("ReadingFinishedProgress"));
- }
- if (TemperatureData != null && TemperatureData.Count <= 1)
- {
- if (!cts.IsCancellationRequested)
- {
- OnReadFailure?.Invoke();
- }
- }
- Debug.WriteLine(ex);
- }
- catch (NullReferenceException ex)
- {
- Debug.WriteLine(ex);
- OnDeviceConnectionFailure?.Invoke();
- }
- catch (Exception ex)
- {
- if (!cts.IsCancellationRequested)
- {
- System.Diagnostics.Debug.WriteLine(ex);
- OnDeviceConnectionFailure?.Invoke();
- }
- }
- finally
- {
- Task.Run(async() =>
- {
- if (isInitialSetupCompleted)
- {
- if (cts.IsCancellationRequested)
- {
- await configCharacteristic.WriteAsync(new byte[] { 0x0D });
- }
- else
- {
- await configCharacteristic.WriteAsync(new byte[] { 0x0F });
- }
- await Task.Delay(3000);
- await temperatureEnableCharacteristic.WriteAsync(new byte[] { 0x01 });
- }
- await Adapter.DisconnectDeviceAsync(deviceToConnect);
- });
- }
- }
- return TemperatureData;
- }
- public async Task WakeUpBleDevice(string address, CancellationTokenSource cts = null)
- {
- var deviceToConnect = devices.Where(dev => BleScannerService.GetAdressFromDevice(dev) == address).FirstOrDefault();
- if (deviceToConnect != null)
- {
- try
- {
- bool isConnectingFinished = default(bool);
- deviceAddress = BleScannerService.GetAdressFromDevice(deviceToConnect);
- var ct = cts.Token;
- Task.Run(async () =>
- {
- await Task.Delay(CONNECTING_TIMEOUT);
- if (!isConnectingFinished)
- {
- ct.ThrowIfCancellationRequested();
- }
- });
- OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceProgress"));
- await Adapter.ConnectToDeviceAsync(deviceToConnect, ConnectParameters.None, ct);
- OnConnectionProgressChange?.Invoke(Translate.GetText("ConnectingToDeviceFinishedProgress"));
- isConnectingFinished = true;
- OnConnectionProgressChange?.Invoke(Translate.GetText("ConfiguringDeviceProgress"));
- var configService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.CONFIGURATION_SERVICE), ct);
- var temperatureService = await deviceToConnect.GetServiceAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_SERVICE), ct);
- //Disable temperature/humidity sensor
- var temperatureSensorEnableCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_ENABLE));
- await temperatureSensorEnableCharacteristic.WriteAsync(new byte[] { 0x00 }, ct);
- //Set time
- var setDateTimeCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.CURRENT_DATETIME));
- var epoch = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
- var epochInt = (int)epoch;
- await setDateTimeCharacteristic.WriteAsync(BitConverter.GetBytes(epochInt), ct);
- // Setting advertising interval
- var setAdvertisingDurationCharacteristic = await configService.GetCharacteristicAsync(new Guid(GattAttributes.DESCOVERABLE_INTERVAL));
- await setAdvertisingDurationCharacteristic.WriteAsync(new byte[] { 0x01 }, ct);
- // Setting temperature/humidity sensor update interval
- var setTemperatureUpdateSensorItervalCharacteristic = await temperatureService.GetCharacteristicAsync(new Guid(GattAttributes.HUM_TEMP_SENSOR_INTERVAL));
- await setTemperatureUpdateSensorItervalCharacteristic.WriteAsync(new byte[] { 0x1E }, ct);
- //Enable temperature/humidity sensor
- await temperatureSensorEnableCharacteristic.WriteAsync(new byte[] { 0x01 }, ct);
- // Setting advertising
- var setAdvertisingService = await configService.GetCharacteristicAsync(new Guid(GattAttributes.CONFIG_REGISTER));
- await setAdvertisingService.WriteAsync(new byte[] { 0x0F }, ct);
- OnConnectionProgressChange?.Invoke(Translate.GetText("ConfiguringDeviceFinishedProgress"));
- }
- catch (Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException ex)
- {
- if (!cts.IsCancellationRequested)
- {
- OnReadFailure?.Invoke();
- System.Diagnostics.Debug.WriteLine(ex);
- }
- }
- catch (Exception ex)
- {
- if (!cts.IsCancellationRequested)
- {
- OnDeviceConnectionFailure?.Invoke();
- System.Diagnostics.Debug.WriteLine(ex);
- }
- }
- finally
- {
- await Adapter.DisconnectDeviceAsync(deviceToConnect);
- }
- }
- }
- public async Task StopScaning()
- {
- await Adapter.StopScanningForDevicesAsync();
- }
- public void SortList()
- {
- Collection = new ObservableCollection<BluetoothSensorDevice>(Collection.OrderByDescending(i => i.Rssi));
- }
- #endregion
- #region Methods [private]
- private void Adapter_DeviceDiscovered(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
- {
- try
- {
- var device = e.Device;
- if (BleScannerService.CheckIfDeviceTypeIsLe(device))
- {
- var knownDevice = Collection.Where(dev => dev.Address == BleScannerService.GetAdressFromDevice(device)).FirstOrDefault();
- if (knownDevice == null)
- {
- var newItem = BleScannerService.ReadOrUpdateAdvertisementsData(device);
- Collection.Add(newItem);
- devices.Add(device);
- OnDeviceUpdate?.Invoke();
- }
- }
- }
- catch(Exception ex)
- {
- Debug.WriteLine($"BLE Sensor Error: {ex.Message}");
- Logger.Instance.Error($"BLE Sensor Error: {ex.Message}");
- Utils.Logger.Instance.SendLog($"BLE Sensor Error: {ex.Message}", null, LogType.Error);
- }
- }
- private async void Adapter_DeviceAdvertised(object sender, Plugin.BLE.Abstractions.EventArgs.DeviceEventArgs e)
- {
- try
- {
- var device = e.Device;
- var knownDevice = Collection.Where(dev => dev.Address == BleScannerService.GetAdressFromDevice(device)).FirstOrDefault();
- if (knownDevice != null)
- {
- var updatedData = BleScannerService.ReadOrUpdateAdvertisementsData(device);
- knownDevice.Rssi = updatedData.Rssi;
- knownDevice.Temperature = updatedData.Temperature;
- knownDevice.Humidity = updatedData.Humidity;
- OnDeviceUpdate?.Invoke();
- }
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"BLE Sensor Error: {ex.Message}");
- Logger.Instance.Error($"BLE Sensor Error: {ex.Message}");
- Utils.Logger.Instance.SendLog($"BLE Sensor Error: {ex.Message}", null, LogType.Error);
- }
- }
- #endregion
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement