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; using UnityEngine; using Assets.Scripts.Devices.Ble.Extension; namespace Assets.Scripts.Devices.Ble.Characteristic { public class CyclingSpeedCadenceMeasurement : ICharacteristic { private CyclingSpeedCadenceMeasurement.IUpdate _currentUpdate; private CyclingSpeedCadenceMeasurement.IUpdate _previousUpdate = new CyclingSpeedCadenceMeasurement.NullUpdate(); private const byte MaxNoEvents = (byte)4; private byte _noCadenceEventCount; private byte _noSpeedEventCount; public Guid Uuid => ServiceUuids.Characteristics.CscMeasurement; public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.CyclingSpeedCadence).IdGuid; public bool IsOptional => false; public double Speed { get; private set; } public int Cadence { get; private set; } public double WheelCircumference { private get; set; } public CyclingSpeedCadenceMeasurement(double wheelCircumference) { this.WheelCircumference = wheelCircumference; } public void HandleAttributeReceived(byte[] data) { //throw new NotImplementedException(); //Debug.Log(string.Join(",", data)); this._currentUpdate = new CyclingSpeedCadenceMeasurement.Update(data); this.HandleCadenceUpdate(); this.HandleSpeedUpdate(); this._previousUpdate = this._currentUpdate; } private void HandleCadenceUpdate() { if (this._currentUpdate.HasCadence && (int)this._currentUpdate.CadenceEventCount != (int)this._previousUpdate.CadenceEventCount) { this._noCadenceEventCount = (byte)0; if (this.CadenceTimeDifference() <= 0) return; this.Cadence = this.CalculateCadence(); } else { this._noCadenceEventCount = (byte)((uint)this._noCadenceEventCount + 1U); if ((int)this._noCadenceEventCount < 4) return; this.Cadence = 0; } Debug.Log("踏频值:" + this.Cadence); } private void HandleSpeedUpdate() { if (this._currentUpdate.HasSpeed && (int)this._currentUpdate.SpeedEventCount != (int)this._previousUpdate.SpeedEventCount) { this._noSpeedEventCount = (byte)0; double num = this.CalculateSpeed(); if (num >= 150.0) return; this.Speed = num; } else { this._noSpeedEventCount = (byte)((uint)this._noSpeedEventCount + 1U); if ((int)this._noSpeedEventCount < 4) return; this.Speed = 0.0; } } private int CalculateCadence() { int num = this.CadenceEventDifference() * 61440 / this.CadenceTimeDifference(); if (num > (int)byte.MaxValue) return 0; //return (int)byte.MaxValue; if (num < 0) return 0; return num; } private int CadenceTimeDifference() { if ((int)this._currentUpdate.CadenceTime1024 > (int)this._previousUpdate.CadenceTime1024) return (int)this._currentUpdate.CadenceTime1024 - (int)this._previousUpdate.CadenceTime1024; return (int)ushort.MaxValue - (int)this._previousUpdate.CadenceTime1024 + (int)this._currentUpdate.CadenceTime1024 + 1; } private int CadenceEventDifference() { if ((int)this._currentUpdate.CadenceEventCount > (int)this._previousUpdate.CadenceEventCount) return (int)this._currentUpdate.CadenceEventCount - (int)this._previousUpdate.CadenceEventCount; return (int)ushort.MaxValue - (int)this._previousUpdate.CadenceEventCount + (int)this._currentUpdate.CadenceEventCount + 1; } private double CalculateSpeed() { double num = (double)(ulong)(this.WheelCircumference / 10.0 * 36864.0 * (double)this.SpeedEventDifference() / (double)this.SpeedTimeDifference()) / 1000.0; if (num >= 0.0) return num; return 0.0; } private int SpeedTimeDifference() { if ((int)this._currentUpdate.SpeedTime1024 > (int)this._previousUpdate.SpeedTime1024) return (int)this._currentUpdate.SpeedTime1024 - (int)this._previousUpdate.SpeedTime1024; return (int)ushort.MaxValue - (int)this._previousUpdate.SpeedTime1024 + (int)this._currentUpdate.SpeedTime1024 + 1; } private uint SpeedEventDifference() { if (this._currentUpdate.SpeedEventCount > this._previousUpdate.SpeedEventCount) return this._currentUpdate.SpeedEventCount - this._previousUpdate.SpeedEventCount; return (uint)(-1 - (int)this._previousUpdate.SpeedEventCount + (int)this._currentUpdate.SpeedEventCount + 1); } public void SetUnavailable() { //throw new NotImplementedException(); } private interface IUpdate { bool HasCadence { get; } bool HasSpeed { get; } uint SpeedEventCount { get; } ushort SpeedTime1024 { get; } ushort CadenceEventCount { get; } ushort CadenceTime1024 { get; } } private class Update : CyclingSpeedCadenceMeasurement.IUpdate { private static readonly byte WheelRevolutionsFlagBit = (byte)0; private static readonly byte CrankRevolutionsFlagBit = (byte)1; private readonly byte[] _data; private byte Flags { get { return this._data[0]; } } public bool HasCadence { get { return PrimitiveExtensions.IsBitSet(this.Flags, (int)CyclingSpeedCadenceMeasurement.Update.CrankRevolutionsFlagBit); } } public bool HasSpeed { get { return PrimitiveExtensions.IsBitSet(this.Flags, (int)CyclingSpeedCadenceMeasurement.Update.WheelRevolutionsFlagBit); } } public uint SpeedEventCount { get { return BitConvertHelper.ToUInt32(this._data, 1); } } public ushort SpeedTime1024 { get { return BitConvertHelper.ToUInt16(this._data, 5); } } public ushort CadenceEventCount { get { return BitConvertHelper.ToUInt16(this._data, this.HasSpeed ? 7 : 1); } } public ushort CadenceTime1024 { get { return BitConvertHelper.ToUInt16(this._data, this.HasSpeed ? 9 : 3); } } public Update(byte[] data) { this._data = data; } } private class NullUpdate : CyclingSpeedCadenceMeasurement.IUpdate { public bool HasCadence { get { return false; } } public bool HasSpeed { get { return false; } } public uint SpeedEventCount { get { return 0U; } } public ushort SpeedTime1024 { get { return (ushort)0; } } public ushort CadenceEventCount { get { return (ushort)0; } } public ushort CadenceTime1024 { get { return (ushort)0; } } } } }