实现连接设备界面
This commit is contained in:
1 parent
996f924719
commit
ec7589096f
88 files changed
+11344
-156
No files matched your search
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
@@ -91,6 +92,11 @@ namespace Assets.Scripts.Devices.Ant
|
||||
public bool pairingEnabled;
|
||||
}
|
||||
|
||||
public virtual int Priority
|
||||
{
|
||||
get; protected set;
|
||||
}
|
||||
|
||||
//private readonly Rhino.PowerFun.Services.DeviceService deviceService;
|
||||
//private readonly DeviceDetailService _deviceDetailService;
|
||||
//private readonly AntManufacturerService antManufacturerService;
|
||||
@@ -172,6 +178,7 @@ namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
if (State == DeviceState.Connected || State == DeviceState.Connecting)
|
||||
return;
|
||||
Debug.Log("连接" + this.DeviceNumber);
|
||||
AntConnector.Instance().ConnectDevice(this);
|
||||
}
|
||||
|
||||
@@ -179,6 +186,7 @@ namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
if (State == DeviceState.Disconnected || State == DeviceState.Disconnecting)
|
||||
return;
|
||||
Debug.Log(this.DeviceNumber + "断开连接");
|
||||
AntConnector.Instance().DisconnectDevice(this, save);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,10 +68,10 @@ namespace Assets.Scripts.Devices.Ant
|
||||
//CheckStatus();
|
||||
|
||||
deviceList.Add(new FitDevice());
|
||||
//deviceList.Add(new ds_AntPlus_Power());
|
||||
//deviceList.Add(new ds_AntPlus_Cadence());
|
||||
//deviceList.Add(new ds_AntPlus_HeartRate());
|
||||
//deviceList.Add(new ds_AntPlus_BikeSpdCad());
|
||||
deviceList.Add(new PowerDevice());
|
||||
deviceList.Add(new CadenceDevice());
|
||||
deviceList.Add(new HeartRateDevice());
|
||||
deviceList.Add(new BikeSpdCadDevice());
|
||||
|
||||
var timer = new System.Timers.Timer(1000);
|
||||
timer.AutoReset = true;
|
||||
@@ -322,18 +322,18 @@ namespace Assets.Scripts.Devices.Ant
|
||||
case SensorType.None:
|
||||
break;
|
||||
case SensorType.Cadence:
|
||||
//device = new ds_AntPlus_Cadence();
|
||||
device = new CadenceDevice();
|
||||
break;
|
||||
case SensorType.HeartRate:
|
||||
//device = new ds_AntPlus_HeartRate();
|
||||
device = new HeartRateDevice();
|
||||
break;
|
||||
case SensorType.Power:
|
||||
//device = new ds_AntPlus_Power();
|
||||
device = new PowerDevice();
|
||||
break;
|
||||
case SensorType.Speed:
|
||||
break;
|
||||
case SensorType.SpeedCadence:
|
||||
//device = new ds_AntPlus_BikeSpdCad();
|
||||
device = new BikeSpdCadDevice();
|
||||
break;
|
||||
case SensorType.Trainer:
|
||||
device = new FitDevice();
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
using Assets.Scripts.Devices.Ant.Interfaces;
|
||||
using Assets.Scripts.Devices.Ant.LegacyPages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
public class BikeSpdCadDevice : AbstractAntDevice, ISpeedDevice, ICadenceDevice
|
||||
{
|
||||
public const int MAX_NO_EVENT_STOP_COUNT = 12;
|
||||
public const double DEFAULT_WHEEL_CIRCUMFERENCE_m = 2096; //Average 700cx23mm road tire
|
||||
|
||||
public readonly double wheelCircumfrence_m;
|
||||
|
||||
private RotationData _speedData = new RotationData();
|
||||
private RotationData _cadenceData = new RotationData();
|
||||
|
||||
public BikeSpdCadDevice(double wheelCircumfrence_m = DEFAULT_WHEEL_CIRCUMFERENCE_m)
|
||||
: base("Ant+ Speed&Cadence", racerSportType.Biking, SensorType.SpeedCadence)
|
||||
{
|
||||
Priority = 1;
|
||||
this.wheelCircumfrence_m = wheelCircumfrence_m;
|
||||
}
|
||||
|
||||
public double Speed { get; set; }
|
||||
private int _Cadence;
|
||||
public int Cadence
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Cadence;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Cadence = DeviceValueFilter.Cadence(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
protected override AntChannelProfile getDefaultSearchProfile()
|
||||
{
|
||||
return new AntChannelProfile()
|
||||
{
|
||||
rfOffset = 57,
|
||||
transType = 0,
|
||||
deviceType = 121,
|
||||
deviceNumber = 0,
|
||||
messagePeriod = 8086,
|
||||
pairingEnabled = false,
|
||||
};
|
||||
}
|
||||
|
||||
public override void handleChannelResponse(ANT_Managed_Library.ANT_Response response)
|
||||
{
|
||||
//商品Manufacturer Information
|
||||
if (response.messageContents[1] == 2)
|
||||
{
|
||||
//Console.WriteLine(string.Join(",",response.messageContents));
|
||||
base.ManufacturerId = response.messageContents[2];
|
||||
}
|
||||
if (response.responseID == (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
|
||||
{
|
||||
var dataPayload = response.messageContents.Skip(1).ToArray();
|
||||
|
||||
int newUpdate1 = (int)dataPayload[0] | (int)dataPayload[1] << 8;
|
||||
int newCount1 = (int)dataPayload[2] | (int)dataPayload[3] << 8;
|
||||
int newUpdate2 = (int)dataPayload[4] | (int)dataPayload[5] << 8;
|
||||
int newCount2 = (int)dataPayload[6] | (int)dataPayload[7] << 8;
|
||||
|
||||
var cadence = this._cadenceData.CalculateRpm(now, newUpdate1, newCount1);
|
||||
if (cadence.HasValue)
|
||||
{
|
||||
Cadence = cadence.Value;
|
||||
}
|
||||
var a2 = this._speedData.CalculateRpm(now, newUpdate2, newCount2);
|
||||
if (a2.HasValue)
|
||||
{
|
||||
Speed = DoubleExtensions.CalculateSpeed(a2.Value, this.wheelCircumfrence_m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c53c916c5ea88d42921b701c66a8b2d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
using Assets.Scripts.Devices.Ant.Interfaces;
|
||||
using Assets.Scripts.Devices.Ant.LegacyPages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
public class CadenceDevice : AbstractAntDevice, ICadenceDevice
|
||||
{
|
||||
public const int MAX_NO_EVENT_STOP_COUNT = 12;
|
||||
|
||||
private int _Cadence;
|
||||
public int Cadence
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Cadence;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Cadence = DeviceValueFilter.Cadence(value);
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime _now = DateTime.Now;
|
||||
private RotationData _rotationData = new RotationData();
|
||||
|
||||
public CadenceDevice()
|
||||
: base("Ant+ Cadence", racerSportType.Biking, SensorType.Cadence)
|
||||
{
|
||||
Priority = 2;
|
||||
//if (speedSensor.isInUse)
|
||||
// throw new ArgumentException("Can't use a Speed Sensor that is already in use.");
|
||||
|
||||
//speedSensor.customSourceName = "Spd used by Cad w/Spd";
|
||||
//speedSensor.isInUse = true;
|
||||
//this.speedSensor = speedSensor;
|
||||
//speedSensor.start(newSpeedSensorPacket); //Ensure speed sensor is always running so we can always get the values
|
||||
}
|
||||
|
||||
//public override void start(Action<DataSourcePacket> distanceUpdateHandler)
|
||||
//{
|
||||
// //Reset the speed sensor first so we get back to a zero distance
|
||||
// //speedSensor.stop();
|
||||
// //lastDistance = 0;
|
||||
// //speedSensor.reset();
|
||||
// //speedSensor.start(newSpeedSensorPacket);
|
||||
|
||||
// base.start(distanceUpdateHandler);
|
||||
//}
|
||||
|
||||
//public void newSpeedSensorPacket(DataSourcePacket pckt)
|
||||
//{
|
||||
// double distDiff = pckt.distance - lastDistance;
|
||||
// if(distDiff > 0)
|
||||
// incrementDistanceAndUpdate(distDiff, speedMs: pckt.speed_ms, cadence: calculatedCadence);
|
||||
// lastDistance = pckt.distance;
|
||||
//}
|
||||
|
||||
protected override AntChannelProfile getDefaultSearchProfile()
|
||||
{
|
||||
return new AntChannelProfile()
|
||||
{
|
||||
rfOffset = 57,
|
||||
transType = 0,
|
||||
deviceType = 122,
|
||||
deviceNumber = 0,
|
||||
messagePeriod = 8102,
|
||||
pairingEnabled = false,
|
||||
};
|
||||
}
|
||||
|
||||
public override void handleChannelResponse(ANT_Managed_Library.ANT_Response response)
|
||||
{
|
||||
//商品Manufacturer Information
|
||||
if (response.messageContents[1] == 2)
|
||||
{
|
||||
//Console.WriteLine(string.Join(",",response.messageContents));
|
||||
base.ManufacturerId = response.messageContents[2];
|
||||
}
|
||||
|
||||
if (response.responseID == (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
|
||||
{
|
||||
//In this decode we ignore page change toggle and page type, since the info we need is transmitted on every page
|
||||
|
||||
var page = response.messageContents.Skip(1).ToArray();
|
||||
var cadence = this._rotationData.CalculateRpm(_now, (int)page[4] | (int)page[5] << 8, (int)page[6] | (int)page[7] << 8);
|
||||
|
||||
Cadence = cadence.GetValueOrDefault(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 992e04a304393e841ad0d13498a74587
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -20,7 +20,6 @@ namespace Assets.Scripts.Devices.Ant
|
||||
int lastInstCadence = -1;
|
||||
ushort lastInstPower = 0xFFFF;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 当前坡度,当切换到其他模式的时候,需要把坡度设置为0
|
||||
/// </summary>
|
||||
@@ -29,6 +28,7 @@ namespace Assets.Scripts.Devices.Ant
|
||||
public FitDevice()
|
||||
: base("Ant+ Trainer", racerSportType.Unknown, SensorType.Trainer)
|
||||
{
|
||||
Priority = 0;
|
||||
this.StateChange = (state) =>
|
||||
{
|
||||
if (state == DeviceState.Connected)
|
||||
@@ -85,7 +85,7 @@ namespace Assets.Scripts.Devices.Ant
|
||||
set
|
||||
{
|
||||
_Power = DeviceValueFilter.Power(value);
|
||||
Debug.Log(_Power);
|
||||
//Debug.Log(_Power);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using Assets.Scripts.Devices.Ant.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
public class HeartRateDevice : AbstractAntDevice, IHeartRateDevice
|
||||
{
|
||||
//public const int MAX_NO_EVENT_STOP_COUNT = 12;
|
||||
|
||||
private int _HeartRate;
|
||||
public int HeartRate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _HeartRate;
|
||||
}
|
||||
set
|
||||
{
|
||||
_HeartRate = DeviceValueFilter.HeartRate(value);
|
||||
}
|
||||
}
|
||||
|
||||
//ds_AntPlus_BikeSpd speedSensor;
|
||||
|
||||
public HeartRateDevice()
|
||||
: base("Ant+ HeartRate", racerSportType.Unknown, SensorType.HeartRate)
|
||||
{
|
||||
Priority = 2;
|
||||
}
|
||||
|
||||
protected override AntChannelProfile getDefaultSearchProfile()
|
||||
{
|
||||
return new AntChannelProfile()
|
||||
{
|
||||
rfOffset = 57,
|
||||
transType = 0,
|
||||
deviceType = 120,
|
||||
deviceNumber = 0,
|
||||
messagePeriod = 8070,
|
||||
pairingEnabled = false,
|
||||
};
|
||||
}
|
||||
|
||||
public override void handleChannelResponse(ANT_Managed_Library.ANT_Response response)
|
||||
{
|
||||
//Console.WriteLine(string.Join(",", response.messageContents));
|
||||
//商品Manufacturer Information
|
||||
if (response.messageContents[1] == 2)
|
||||
{
|
||||
base.ManufacturerId = response.messageContents[2];
|
||||
}
|
||||
|
||||
if (response.responseID == (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
|
||||
{
|
||||
var num = response.messageContents[8];
|
||||
|
||||
//PubCommData.HeartRate = num;
|
||||
HeartRate = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab69ac4f4621acc409ac4c6a29893f9f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93809400c8fb6fb41aa3cb44471bf185
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.LegacyPages
|
||||
{
|
||||
public class RotationData
|
||||
{
|
||||
private static readonly TimeSpan TimeBeforeRollover = TimeSpan.FromSeconds(63.0);
|
||||
private const int MaxUpdateValue = 65535;
|
||||
private const int MaxCountValue = 65535;
|
||||
private int? _update;
|
||||
private int? _count;
|
||||
private DateTimeOffset? _lastUpdatedTime;
|
||||
private int _rpm;
|
||||
|
||||
public int? CalculateRpm(DateTimeOffset now, int newUpdate, int newCount)
|
||||
{
|
||||
DateTimeOffset time = now;
|
||||
if (!this._lastUpdatedTime.HasValue)
|
||||
{
|
||||
this._update = new int?(newUpdate);
|
||||
this._count = new int?(newCount);
|
||||
this._lastUpdatedTime = new DateTimeOffset?(now);
|
||||
return new int?();
|
||||
}
|
||||
if (this.HasNotMoved(newUpdate, time))
|
||||
return new int?(0);
|
||||
if (this.HasMoreThanOneRolloverOccurred(time))
|
||||
{
|
||||
this._lastUpdatedTime = new DateTimeOffset?(time);
|
||||
this._update = new int?(newUpdate);
|
||||
this._count = new int?(newCount);
|
||||
return new int?();
|
||||
}
|
||||
if (this.HasNotUpdated(newUpdate))
|
||||
return new int?(this._rpm);
|
||||
if (this.HasUpdateRolledOver(newUpdate))
|
||||
{
|
||||
int? nullable = this._update;
|
||||
this._update = nullable.HasValue ? new int?(nullable.GetValueOrDefault() - (int)ushort.MaxValue) : new int?();
|
||||
}
|
||||
if (this.HasCountRolledOver(newCount))
|
||||
{
|
||||
int? nullable = this._count;
|
||||
this._count = nullable.HasValue ? new int?(nullable.GetValueOrDefault() - (int)ushort.MaxValue) : new int?();
|
||||
}
|
||||
this._rpm = (int)Math.Round((double)(newCount - this._count.Value) / (double)(newUpdate - this._update.Value) * 1024.0 * 60.0);
|
||||
this._lastUpdatedTime = new DateTimeOffset?(time);
|
||||
this._update = new int?(newUpdate);
|
||||
this._count = new int?(newCount);
|
||||
return new int?(this._rpm);
|
||||
}
|
||||
|
||||
private bool HasMoreThanOneRolloverOccurred(DateTimeOffset time)
|
||||
{
|
||||
DateTimeOffset dateTimeOffset = time;
|
||||
DateTimeOffset? nullable1 = this._lastUpdatedTime;
|
||||
TimeSpan? nullable2 = nullable1.HasValue ? new TimeSpan?(dateTimeOffset - nullable1.GetValueOrDefault()) : new TimeSpan?();
|
||||
TimeSpan timeSpan = RotationData.TimeBeforeRollover;
|
||||
if (!nullable2.HasValue)
|
||||
return false;
|
||||
return nullable2.GetValueOrDefault() > timeSpan;
|
||||
}
|
||||
|
||||
private bool HasCountRolledOver(int newCount)
|
||||
{
|
||||
int num = newCount;
|
||||
int? nullable = this._count;
|
||||
int valueOrDefault = nullable.GetValueOrDefault();
|
||||
if (num >= valueOrDefault)
|
||||
return false;
|
||||
return nullable.HasValue;
|
||||
}
|
||||
|
||||
private bool HasUpdateRolledOver(int newUpdate)
|
||||
{
|
||||
int num = newUpdate;
|
||||
int? nullable = this._update;
|
||||
int valueOrDefault = nullable.GetValueOrDefault();
|
||||
if (num >= valueOrDefault)
|
||||
return false;
|
||||
return nullable.HasValue;
|
||||
}
|
||||
|
||||
private bool HasNotUpdated(int newUpdate)
|
||||
{
|
||||
int num = newUpdate;
|
||||
int? nullable = this._update;
|
||||
int valueOrDefault = nullable.GetValueOrDefault();
|
||||
if (num != valueOrDefault)
|
||||
return false;
|
||||
return nullable.HasValue;
|
||||
}
|
||||
|
||||
private bool HasNotMoved(int newUpdate, DateTimeOffset time)
|
||||
{
|
||||
DateTimeOffset dateTimeOffset = time - TimeSpan.FromSeconds(4.0);
|
||||
DateTimeOffset? nullable1 = this._lastUpdatedTime;
|
||||
if ((nullable1.HasValue ? (dateTimeOffset >= nullable1.GetValueOrDefault() ? 1 : 0) : 0) == 0)
|
||||
return false;
|
||||
int num = newUpdate;
|
||||
int? nullable2 = this._update;
|
||||
int valueOrDefault = nullable2.GetValueOrDefault();
|
||||
if (num != valueOrDefault)
|
||||
return false;
|
||||
return nullable2.HasValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 057a1149cfd54d24bb329df54a9c9dfa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// 手动校准命令
|
||||
/// </summary>
|
||||
public class ManualCalibrate : BaseMessage
|
||||
{
|
||||
public ManualCalibrate(byte channel)
|
||||
: base(channel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override ANTMessage GetMessage()
|
||||
{
|
||||
return new ANTMessage()
|
||||
{
|
||||
Id = (byte)79,
|
||||
Size = (byte)3,
|
||||
Data = new byte[3]
|
||||
{
|
||||
this.Channel,
|
||||
(byte) 1,
|
||||
(byte) 170
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30adc878ef1c2cb4fb944e55b2d3d439
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
using Assets.Scripts.Devices.Ant.Pages.CalibrationPages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备校准的处理函数
|
||||
/// </summary>
|
||||
public class CalibrationPageHandler : IPageHandler
|
||||
{
|
||||
private readonly IList<ICalibrationPage> _calibrationPageHandlers = new List<ICalibrationPage>()
|
||||
{
|
||||
new CtfCalibrationPage(),
|
||||
new FecCalibrationPage(),
|
||||
new FailureCalibrationPage(),
|
||||
new SuccessCalibrationPage()
|
||||
};
|
||||
|
||||
public bool CanHandle(byte pageNumber)
|
||||
{
|
||||
if ((int)pageNumber != 1)
|
||||
{
|
||||
return (int)pageNumber == 240;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
var calibrationPage = this._calibrationPageHandlers.FirstOrDefault(ph => ph.CanHandle(dataPayload[1]));
|
||||
if (calibrationPage == null)
|
||||
return;
|
||||
calibrationPage.Handle(dataPayload, device);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75c5b210cd34db1498a311b6656f9ad4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages.CalibrationPages
|
||||
{
|
||||
public class CtfCalibrationPage : ICalibrationPage
|
||||
{
|
||||
public bool CanHandle(byte calibrationId)
|
||||
{
|
||||
return (int)calibrationId == 16;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null || (int)dataPayload[2] != 1)
|
||||
return;
|
||||
//参考类CtfCalibrationResult
|
||||
var offset = (int)((int)dataPayload[7] | (int)dataPayload[6] << 8);
|
||||
powerDevice.DoCalibrationSuccess(offset, AutoZeroStatus.NotSupported);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14c60f86d0918cf4d9656359561b9c7d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages.CalibrationPages
|
||||
{
|
||||
/// <summary>
|
||||
/// 校准失败的处理函数
|
||||
/// </summary>
|
||||
public class FailureCalibrationPage : ICalibrationPage
|
||||
{
|
||||
public bool CanHandle(byte calibrationId)
|
||||
{
|
||||
return (int)calibrationId == 175;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null)
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87c2482dbcf031e488a6dd7cfc3b475b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages.CalibrationPages
|
||||
{
|
||||
/// <summary>
|
||||
/// 校准成功的处理函数
|
||||
/// </summary>
|
||||
public class SuccessCalibrationPage : ICalibrationPage
|
||||
{
|
||||
public bool CanHandle(byte calibrationId)
|
||||
{
|
||||
return (int)calibrationId == 172;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null)
|
||||
return;
|
||||
var autoZeroStatus = (AutoZeroStatus)dataPayload[2];
|
||||
var offset = (int)((int)dataPayload[7] << 8 | (int)dataPayload[6]);
|
||||
powerDevice.DoCalibrationSuccess(offset, autoZeroStatus);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c45f42f53396ece499b5153107ab46da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages
|
||||
{
|
||||
public class CrankPowerPageHandler : IPageHandler
|
||||
{
|
||||
private readonly TorquePowerDataCalculator _torquePowerDataCalculator = new TorquePowerDataCalculator();
|
||||
|
||||
public bool CanHandle(byte pageNumber)
|
||||
{
|
||||
return (int)pageNumber == 18;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null)
|
||||
return;
|
||||
byte eventCount = dataPayload[1];
|
||||
int num = (int)dataPayload[3];
|
||||
ushort period = (ushort)((uint)dataPayload[4] | (uint)dataPayload[5] << 8);
|
||||
ushort accumulatedTorque = (ushort)(dataPayload[6] | (uint)dataPayload[7] << 8);
|
||||
this._torquePowerDataCalculator.Update(eventCount, period, accumulatedTorque);
|
||||
//powerDevice.UpdateCadence(new int?(this._torquePowerDataCalculator.Rpm));
|
||||
//powerDevice.UpdatePower(new int?(this._torquePowerDataCalculator.Power));
|
||||
powerDevice.Cadence = this._torquePowerDataCalculator.Rpm;
|
||||
powerDevice.Power = this._torquePowerDataCalculator.Power;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb07cd617b03b2b4eb8df137b07ae7fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Crank Torque-Frequency Message 曲柄功率计的消息
|
||||
/// </summary>
|
||||
public class CtfPageHandler : IPageHandler
|
||||
{
|
||||
private readonly CrankTorqueFrequencyData _crankTorqueFrequency = new CrankTorqueFrequencyData();
|
||||
|
||||
public bool CanHandle(byte pageNumber)
|
||||
{
|
||||
return (int)pageNumber == 32;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
byte num1 = dataPayload[1];
|
||||
ushort num2 = (ushort)((uint)dataPayload[3] | (uint)dataPayload[2] << 8);
|
||||
ushort num3 = (ushort)((uint)dataPayload[5] | (uint)dataPayload[4] << 8);
|
||||
ushort num4 = (ushort)((uint)dataPayload[7] | (uint)dataPayload[6] << 8);
|
||||
|
||||
if (powerDevice.Offset.HasValue)
|
||||
{
|
||||
int offset = powerDevice.Offset.GetValueOrDefault(0);
|
||||
|
||||
CrankTorqueFrequencyData torqueFrequencyData = this._crankTorqueFrequency;
|
||||
int num5 = (int)num1;
|
||||
int num6 = (int)num3;
|
||||
int num7 = (int)num4;
|
||||
int num8 = (int)num2;
|
||||
|
||||
torqueFrequencyData.Update((byte)num5, (ushort)num6, (ushort)num7, (ushort)num8, offset);
|
||||
|
||||
Console.WriteLine("offset:" + offset);
|
||||
powerDevice.Power = this._crankTorqueFrequency.Power.GetValueOrDefault();
|
||||
}
|
||||
powerDevice.Cadence = this._crankTorqueFrequency.Cadence;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20f678fa75e9edb48a11bed1c1284daf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages
|
||||
{
|
||||
public class PowerOnlyPageHandler : IPageHandler
|
||||
{
|
||||
private DateTime _lastEventChange = DateTime.UtcNow;
|
||||
private byte _previousEventCount;
|
||||
|
||||
public bool CanHandle(byte pageNumber)
|
||||
{
|
||||
return (int)pageNumber == 16;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//var dataPayload = response.messageContents.Skip(1).ToArray();
|
||||
byte currentVal = dataPayload[1];
|
||||
if ((int)ByteExtensions.GetDifference(currentVal, this._previousEventCount) > 0) //ByteExtensions
|
||||
this._lastEventChange = DateTime.UtcNow;
|
||||
this._previousEventCount = currentVal;
|
||||
powerDevice.Power = this.IsNotMovingDueToNoEventChanges() ? 0 : (ushort)((uint)dataPayload[6] | (uint)dataPayload[7] << 8);
|
||||
if ((int)dataPayload[3] != (int)byte.MaxValue)
|
||||
powerDevice.Cadence = (this.IsNotMovingDueToNoEventChanges() ? 0 : (int)dataPayload[3]);
|
||||
else
|
||||
powerDevice.Cadence = 0;
|
||||
//int num1 = (int)dataPayload[2];
|
||||
//int num2 = 128;
|
||||
//bool flag = (uint)(num1 & num2) > 0U;
|
||||
//int num3 = (int)sbyte.MaxValue;
|
||||
//int num4 = num1 & num3;
|
||||
//int num5 = (int)byte.MaxValue;
|
||||
}
|
||||
|
||||
private bool IsNotMovingDueToNoEventChanges()
|
||||
{
|
||||
return this._lastEventChange.AddSeconds(3.0) <= DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 267f065da5b080847b6c2354e6af58f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// 轮盘功率计
|
||||
/// </summary>
|
||||
public class WheelPowerPageHandler : IPageHandler
|
||||
{
|
||||
private readonly TorquePowerDataCalculator _torquePowerDataCalculator = new TorquePowerDataCalculator();
|
||||
|
||||
public bool CanHandle(byte pageNumber)
|
||||
{
|
||||
return pageNumber == 17;
|
||||
}
|
||||
|
||||
public void Handle(byte[] dataPayload, AbstractAntDevice device)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
var powerDevice = device as PowerDevice;
|
||||
if (powerDevice == null)
|
||||
return;
|
||||
|
||||
var eventCount = dataPayload[1];
|
||||
var num = dataPayload[3];
|
||||
|
||||
var period = (ushort)((uint)dataPayload[4] | (uint)dataPayload[5] << 8);
|
||||
var accumulatedTorque = (ushort)((uint)dataPayload[6] | (uint)dataPayload[7] << 8);
|
||||
|
||||
_torquePowerDataCalculator.Update(eventCount, period, accumulatedTorque);
|
||||
|
||||
powerDevice.Power = _torquePowerDataCalculator.Power;
|
||||
powerDevice.Cadence = num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 399061526025e6148ba3f55a5800ed56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,316 @@
|
||||
using Assets.Scripts.Devices.Ant.Interfaces;
|
||||
using Assets.Scripts.Devices.Ant.Messages;
|
||||
using Assets.Scripts.Devices.Ant.Pages;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ant
|
||||
{
|
||||
/// <summary>
|
||||
/// 功率计
|
||||
/// </summary>
|
||||
public class PowerDevice : AbstractAntDevice, IPowerDevice //, ICadenceDevice
|
||||
{
|
||||
private DateTime _lastEventChange = DateTime.UtcNow;
|
||||
//private byte _previousEventCount;
|
||||
private readonly TorquePowerDataCalculator _torquePowerDataCalculator = new TorquePowerDataCalculator();
|
||||
private readonly CrankTorqueFrequencyData _crankTorqueFrequency = new CrankTorqueFrequencyData();
|
||||
private System.Timers.Timer timer;
|
||||
|
||||
//List<IPageHandler> pageHandlers;
|
||||
|
||||
public PowerDevice()
|
||||
: base("Ant+ Power", racerSportType.Biking, SensorType.Power)
|
||||
{
|
||||
Priority = 2;
|
||||
//pageHandlers = new List<IPageHandler>();
|
||||
//pageHandlers.Add(new ManufacturerDataPageHandler());
|
||||
pageHandlers.Add(new PowerOnlyPageHandler());
|
||||
pageHandlers.Add(new CrankPowerPageHandler());
|
||||
pageHandlers.Add(new CtfPageHandler());
|
||||
pageHandlers.Add(new WheelPowerPageHandler());
|
||||
pageHandlers.Add(new CalibrationPageHandler());
|
||||
|
||||
|
||||
this.StateChange = (state) =>
|
||||
{
|
||||
if (state == DeviceState.Connected)
|
||||
{
|
||||
Calibrate();
|
||||
}
|
||||
else if (state == DeviceState.Disconnected)
|
||||
{
|
||||
count = 0;
|
||||
if (timer != null)
|
||||
{
|
||||
timer.Stop();
|
||||
timer = null;
|
||||
DoCalibrationFailure();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private int _Power;
|
||||
public int Power
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Power;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Power = DeviceValueFilter.Power(value);
|
||||
}
|
||||
}
|
||||
private int _Cadence;
|
||||
public int Cadence
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Cadence;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Cadence = DeviceValueFilter.Cadence(value);
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime LastCalibration { get; protected set; }
|
||||
public int? Offset { get; set; }
|
||||
|
||||
public AutoZeroStatus AutoZeroStatus { get; private set; }
|
||||
|
||||
public bool IsCalibrating { get; set; }
|
||||
|
||||
public bool IsCalibrationReady { get; set; }
|
||||
|
||||
public bool CalibrationCompleted { get; set; }
|
||||
|
||||
protected override AntChannelProfile getDefaultSearchProfile()
|
||||
{
|
||||
return new AntChannelProfile()
|
||||
{
|
||||
rfOffset = 57,
|
||||
transType = 0,
|
||||
deviceType = 11,
|
||||
deviceNumber = 0,
|
||||
messagePeriod = 8182,
|
||||
pairingEnabled = false,
|
||||
};
|
||||
}
|
||||
//List<int> list = new List<int>();
|
||||
public override void handleChannelResponse(ANT_Managed_Library.ANT_Response response)
|
||||
{
|
||||
//if (!list.Contains(response.messageContents[1]))
|
||||
//{
|
||||
// list.Add(response.messageContents[1]);
|
||||
// Console.WriteLine(response.messageContents[1]);
|
||||
//}
|
||||
//Console.WriteLine(string.Join(",", response.messageContents));
|
||||
if (response.responseID == (byte)ANT_Managed_Library.ANT_ReferenceLibrary.ANTMessageID.BROADCAST_DATA_0x4E)
|
||||
{
|
||||
var pageNumber = response.messageContents[1];
|
||||
|
||||
foreach (var handler in pageHandlers)
|
||||
{
|
||||
if (handler.CanHandle(pageNumber))
|
||||
{
|
||||
handler.Handle(response.messageContents.Skip(1).ToArray(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.IO.File.AppendAllText(System.Environment.CurrentDirectory + "\\data.txt", string.Join(",", response.messageContents) + ";" + Power+"\r\n");
|
||||
//Console.WriteLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal void DoCalibrationSuccess(int? offset, AutoZeroStatus autoZeroStatus)
|
||||
{
|
||||
this.AutoZeroStatus = autoZeroStatus;
|
||||
this.LastCalibration = DateTime.UtcNow;
|
||||
if (this.Offset.HasValue == false)
|
||||
{
|
||||
this.Offset = offset;
|
||||
//this.Offset = 570;
|
||||
}
|
||||
this.IsCalibrating = false;
|
||||
this.CalibrationCompleted = true;
|
||||
|
||||
//Trace.WriteLine($"校准成功:{ offset }");
|
||||
}
|
||||
|
||||
internal void DoCalibrationFailure()
|
||||
{
|
||||
this.IsCalibrating = false;
|
||||
this.CalibrationCompleted = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送校准命令
|
||||
/// </summary>
|
||||
public void Calibrate()
|
||||
{
|
||||
if (this.IsCalibrating)
|
||||
return;
|
||||
|
||||
this.IsCalibrating = true;
|
||||
var channelId = GetChannelId();
|
||||
|
||||
base.SendMessage(new ManualCalibrate(channelId));
|
||||
|
||||
if (timer == null)
|
||||
{
|
||||
timer = new System.Timers.Timer(10000);
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
/// <summary>
|
||||
/// 检查是否已自动校准,自动发送3次
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (count > 3)
|
||||
{
|
||||
timer.Stop();
|
||||
return;
|
||||
}
|
||||
if (this.CalibrationCompleted)
|
||||
{
|
||||
timer.Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
count++;
|
||||
this.IsCalibrating = false;
|
||||
this.Calibrate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class TorquePowerDataCalculator
|
||||
{
|
||||
private DateTime _lastEventChange = DateTime.UtcNow;
|
||||
private byte _previousEventCount;
|
||||
private ushort _previousPeriod;
|
||||
private ushort _previousAccumulatedTorque;
|
||||
|
||||
public int Power { get; private set; }
|
||||
|
||||
public int Rpm { get; private set; }
|
||||
|
||||
public DateTime LastUpdatedTime { get; private set; }
|
||||
|
||||
public TorquePowerDataCalculator()
|
||||
{
|
||||
this.LastUpdatedTime = DateTime.MinValue;
|
||||
}
|
||||
|
||||
public void Update(byte eventCount, ushort period, ushort accumulatedTorque)
|
||||
{
|
||||
byte difference1 = ByteExtensions.GetDifference(eventCount, this._previousEventCount);
|
||||
ushort difference2 = UshortExtensions.GetDifference(period, this._previousPeriod);
|
||||
if ((int)difference1 > 0)
|
||||
this._lastEventChange = DateTime.UtcNow;
|
||||
if (this.PeriodRolloverPossible() || this.IsNotMovingDueToNoEventChanges() || (int)difference2 == 0 && (int)difference1 > 0)
|
||||
{
|
||||
this.Power = 0;
|
||||
this.Rpm = 0;
|
||||
}
|
||||
else if ((int)difference1 > 0)
|
||||
{
|
||||
this.Power = (int)(402.123859659494 * ((double)UshortExtensions.GetDifference(accumulatedTorque, this._previousAccumulatedTorque) / (double)difference2));
|
||||
this.Rpm = 122880 * (int)difference1 / (int)difference2;
|
||||
}
|
||||
this.LastUpdatedTime = DateTime.UtcNow;
|
||||
this._previousEventCount = eventCount;
|
||||
this._previousPeriod = period;
|
||||
this._previousAccumulatedTorque = accumulatedTorque;
|
||||
}
|
||||
|
||||
private bool PeriodRolloverPossible()
|
||||
{
|
||||
return DateTime.UtcNow - this.LastUpdatedTime > TimeSpan.FromSeconds(32.0);
|
||||
}
|
||||
|
||||
private bool IsNotMovingDueToNoEventChanges()
|
||||
{
|
||||
return this._lastEventChange.AddSeconds(3.0) <= DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
public class CrankTorqueFrequencyData
|
||||
{
|
||||
private byte _previousEventCount;
|
||||
private ushort _previousTimestamp;
|
||||
private ushort _previousTorqueTicksStamp;
|
||||
private int _noEventCount;
|
||||
|
||||
public int? Power { get; private set; }
|
||||
|
||||
public int Cadence { get; private set; }
|
||||
|
||||
public DateTime LastUpdatedTime { get; set; }
|
||||
|
||||
public CrankTorqueFrequencyData()
|
||||
{
|
||||
this.LastUpdatedTime = DateTime.MinValue;
|
||||
}
|
||||
|
||||
public void Update(byte eventCount, ushort timestamp, ushort torqueTicksStamp, ushort slope, int offset)
|
||||
{
|
||||
byte difference1 = ByteExtensions.GetDifference(eventCount, this._previousEventCount);
|
||||
ushort difference2 = UshortExtensions.GetDifference(timestamp, this._previousTimestamp);
|
||||
ushort difference3 = UshortExtensions.GetDifference(torqueTicksStamp, this._previousTorqueTicksStamp);
|
||||
this._previousEventCount = eventCount;
|
||||
this._previousTimestamp = timestamp;
|
||||
this._previousTorqueTicksStamp = torqueTicksStamp;
|
||||
if (this.HasMoreThanOneRolloverOccured())
|
||||
{
|
||||
this.LastUpdatedTime = DateTime.UtcNow;
|
||||
this.Power = new int?(0);
|
||||
this.Cadence = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.LastUpdatedTime = DateTime.UtcNow;
|
||||
if ((int)difference1 > 0)
|
||||
{
|
||||
this._noEventCount = 0;
|
||||
double num = (double)difference2 / (double)difference1 * 0.0005;
|
||||
if ((int)difference2 == 0)
|
||||
return;
|
||||
this.Cadence = (int)Math.Round(60.0 / num);
|
||||
if ((int)difference3 == 0)
|
||||
this.Power = new int?();
|
||||
else
|
||||
this.Power = new int?((int)((1.0 / ((double)difference2 * 0.0005 / (double)difference3) - (double)offset) / ((double)slope / 10.0) * (double)this.Cadence * 3.14159265358979 / 30.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
int num = this._noEventCount + 1;
|
||||
this._noEventCount = num;
|
||||
if (num < 12)
|
||||
return;
|
||||
this.Power = new int?(0);
|
||||
this.Cadence = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasMoreThanOneRolloverOccured()
|
||||
{
|
||||
return DateTime.UtcNow - this.LastUpdatedTime > TimeSpan.FromSeconds(32.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ffde5f7de300274b8b12fe730cb7de1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user