using Assets.Scripts.Ble; using Assets.Scripts.Devices.Ble.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Assets.Scripts.Devices.Ble.Characteristic { public class FtmsIndoorBikeData : ICharacteristic { private readonly ushort? _instantSpeedSubject = new ushort?(); private readonly ushort? _averageSpeedSubject = new ushort?(); private readonly ushort? _instantCadenceSubject = new ushort?(); private readonly ushort? _averageCadenceSubject = (new ushort?()); private readonly uint? _totalDistanceSubject = (new uint?()); private readonly short? _resistanceLevelSubject = (new short?()); private readonly short? _instantPowerSubject = (new short?()); private readonly short? _averagePowerSubject = (new short?()); private readonly ushort? _totalEnergySubject = (new ushort?()); private readonly ushort? _energyPerHourSubject = (new ushort?()); private readonly byte? _energyPerMinuteSubject = (new byte?()); private readonly byte? _heartRateSubject = (new byte?()); private readonly byte? _metabolicEquivalentSubject = (new byte?()); private readonly ushort? _elapsedTimeSubject = (new ushort?()); private readonly ushort? _remainingTimeSubject = (new ushort?()); public short? InstantPower { get { return this._instantPowerSubject; } } public ushort? InstantCadence { get { return this._instantCadenceSubject; } } public ushort? InstantSpeed { get { return this._instantSpeedSubject; } } public Guid Uuid => ServiceUuids.Characteristics.IndoorBikeData; public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.Ftms).IdGuid; public bool IsOptional => false; public void HandleAttributeReceived(byte[] data) { if(data.Length < 2) { return; } List list = new List(); if (!ByteExtensions.IsFlagSetAtPosition(data[0], (byte)0)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousSpeed); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)1)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.AverageSpeed); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)2)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousCadence); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)3)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.AverageCadence); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)4)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.TotalDistance); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)5)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.ResistanceLevel); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)6)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousPower); if (ByteExtensions.IsFlagSetAtPosition(data[0], (byte)7)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.AveragePower); if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)0)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.ExpendedEnergy); if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)1)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.HeartRate); if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)2)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.MetabolicEquivalent); if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)3)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.ElapsedTime); if (ByteExtensions.IsFlagSetAtPosition(data[1], (byte)4)) list.Add(FtmsIndoorBikeData.IndoorBikeDataField.RemainingTime); int offset = 2; foreach (FtmsIndoorBikeData.IndoorBikeDataField field in list) offset += this.ParseField(data, offset, field); } public void SetUnavailable() { //throw new NotImplementedException(); } private int ParseField(byte[] attribute, int offset, FtmsIndoorBikeData.IndoorBikeDataField field) { int fieldSize = FtmsIndoorBikeData.GetFieldSize(field); if (attribute.Length < fieldSize + offset) throw new ArgumentException("attribute"); switch (field) { case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousSpeed: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._instantSpeedSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.AverageSpeed: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._averageSpeedSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousCadence: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._instantCadenceSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.AverageCadence: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._averageCadenceSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.TotalDistance: ICharacteristicExtensions.HandleUint24AttributeValue((ICharacteristic)this, attribute, offset, this._totalDistanceSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.ResistanceLevel: ICharacteristicExtensions.HandleShortAttributeValue((ICharacteristic)this, attribute, offset, this._resistanceLevelSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousPower: ICharacteristicExtensions.HandleShortAttributeValue((ICharacteristic)this, attribute, offset, this._instantPowerSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.AveragePower: ICharacteristicExtensions.HandleShortAttributeValue((ICharacteristic)this, attribute, offset, this._averagePowerSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.ExpendedEnergy: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._totalEnergySubject); ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset + 2, this._energyPerHourSubject); ICharacteristicExtensions.HandleByteAttributeValue((ICharacteristic)this, attribute, offset + 4, this._energyPerMinuteSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.HeartRate: ICharacteristicExtensions.HandleByteAttributeValue((ICharacteristic)this, attribute, offset, this._heartRateSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.MetabolicEquivalent: ICharacteristicExtensions.HandleByteAttributeValue((ICharacteristic)this, attribute, offset, this._metabolicEquivalentSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.ElapsedTime: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._elapsedTimeSubject); break; case FtmsIndoorBikeData.IndoorBikeDataField.RemainingTime: ICharacteristicExtensions.HandleUshortAttributeValue((ICharacteristic)this, attribute, offset, this._remainingTimeSubject); break; } return fieldSize; } private static int GetFieldSize(FtmsIndoorBikeData.IndoorBikeDataField field) { int num = 0; switch (field) { case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousSpeed: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.AverageSpeed: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousCadence: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.AverageCadence: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.TotalDistance: num = 3; break; case FtmsIndoorBikeData.IndoorBikeDataField.ResistanceLevel: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.InstantaneousPower: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.AveragePower: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.ExpendedEnergy: num = 5; break; case FtmsIndoorBikeData.IndoorBikeDataField.HeartRate: num = 1; break; case FtmsIndoorBikeData.IndoorBikeDataField.MetabolicEquivalent: num = 1; break; case FtmsIndoorBikeData.IndoorBikeDataField.ElapsedTime: num = 2; break; case FtmsIndoorBikeData.IndoorBikeDataField.RemainingTime: num = 2; break; } return num; } private enum IndoorBikeDataField { InstantaneousSpeed, AverageSpeed, InstantaneousCadence, AverageCadence, TotalDistance, ResistanceLevel, InstantaneousPower, AveragePower, ExpendedEnergy, HeartRate, MetabolicEquivalent, ElapsedTime, RemainingTime, } } }