272 lines
8.4 KiB
C#
272 lines
8.4 KiB
C#
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;
|
|
}
|
|
}
|
|
|
|
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 (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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|