private void OnCharacteristicValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { try { using (Stream s = args.CharacteristicValue.AsStream()) { using (BinaryReader br = new BinaryReader(s)) { LineSensorData lsd = CreateLineSensorData(br); DeviceSentDataEvent?.Invoke(this, lsd); } } } catch (Exception e) { this.logger.Error(e, "unexpected exception while receiving data from BLE device"); } }
private async Task <LineSensorReading> getLineSensorData(double currentPosition, int numberOfSamples, CancellationToken token) { bool callbackIsCalled = false; Semaphore semaphore = new Semaphore(0, 1); List <ushort[]> sensorValues = new List <ushort[]>(); DeviceSentDataEvent callback = (source, data) => { callbackIsCalled = true; if (token.IsCancellationRequested) { try { semaphore.Release(); } catch (SemaphoreFullException) { // ignore as callback might get called multiple times after being cancelled } } else if ((data.CurrentStatus & LineSensorStatus.LSS_OK_FLAG_NEW_DATA_AVAILABLE) == LineSensorStatus.LSS_OK_FLAG_NEW_DATA_AVAILABLE && (data.CurrentStatus & LineSensorStatus.LSS_ERROR) == 0) { lock (sensorValues) { if (sensorValues.Count >= numberOfSamples) { semaphore.Release(); } else { sensorValues.Add(data.SensorValues); } } } }; this.wirelessLineSensor.DeviceSentDataEvent += callback; try { // make sure we purge all old events before starting to receive new ones while (callbackIsCalled) { callbackIsCalled = false; await Task.Delay(500).ConfigureAwait(false); } bool success = false; for (int i = 0; i < START_QUERYING_LINE_SENSOR_RETRIES_COUNT && !token.IsCancellationRequested; ++i) { if (await this.wirelessLineSensor.StartQueryingLineSensor().ConfigureAwait(false)) { success = true; break; } await Task.Delay(100).ConfigureAwait(false); } if (!success) { throw new InvalidOperationException("failed to start querying line sensor, wireless device might have disconnected or powered down"); } #if DEBUG if (!semaphore.WaitOne()) #else if (!semaphore.WaitOne(TIMEOUT_TO_QUERY_LINE_SENSOR_MILLISECONDS)) #endif { throw new TimeoutException("querying line sensor timed out"); } for (int i = 0; i < STOP_QUERYING_LINE_SENSOR_RETRIES_COUNT && !token.IsCancellationRequested; ++i) { if (await this.wirelessLineSensor.StopQueryingLineSensor().ConfigureAwait(false)) { token.ThrowIfCancellationRequested(); if (sensorValues.Count < numberOfSamples) { throw new InvalidOperationException($"for some reason we collected {sensorValues.Count} sensor values which is less than {numberOfSamples} sensor values "); } else if (sensorValues.Count > numberOfSamples) { sensorValues = sensorValues.GetRange(0, numberOfSamples); } return(new LineSensorReading { Position = currentPosition, SensorValues = sensorValues }); } await Task.Delay(100).ConfigureAwait(false); } throw new InvalidOperationException("failed to stop querying line sensor, wireless device might have disconnected or powered down"); } finally { this.wirelessLineSensor.DeviceSentDataEvent -= callback; } }