最新打包配置;适配wahoo
This commit is contained in:
1 parent
74bdd26924
commit
b830b5961a
20 files changed
+280
-189
No files matched your search
@@ -294,6 +294,7 @@ namespace Assets.Scripts.Devices.Ant
|
||||
|
||||
void antChannel_channelResponse_FeSearch(ANT_Response response)
|
||||
{
|
||||
|
||||
//删除扫描不到的设备
|
||||
var now = DateTime.Now;
|
||||
var needRemoveList = discoveredDevices.Where(c => (now - c.LastActiveTime).TotalSeconds > 5 && c.State == DeviceState.Disconnected).ToList();
|
||||
@@ -430,7 +431,7 @@ namespace Assets.Scripts.Devices.Ant
|
||||
u.DeviceTypeId == device.searchProfile.deviceType.ToString()))
|
||||
return;
|
||||
|
||||
if (device.Sensor == SensorType.Trainer || device.Sensor == SensorType.Power)
|
||||
if (device.Sensor == SensorType.Trainer || device.Sensor == SensorType.FtmsTrainer || device.Sensor == SensorType.Power)
|
||||
{
|
||||
if (discoveredDevices.Any(s => s.Sensor == device.Sensor && (s.State == DeviceState.Connected || s.State == DeviceState.Connecting)))
|
||||
{
|
||||
|
||||
@@ -5,48 +5,24 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
{
|
||||
|
||||
[Flags]
|
||||
public enum TrainerDataFlag
|
||||
{
|
||||
MoreData = 1,
|
||||
Cadence = 4,
|
||||
Power = 64
|
||||
}
|
||||
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 int? InstantPower { get; set; }
|
||||
public int? InstantCadence { get; set; }
|
||||
public double? InstantSpeed { get; set; }
|
||||
|
||||
|
||||
public Guid Uuid => ServiceUuids.Characteristics.IndoorBikeData;
|
||||
@@ -55,43 +31,27 @@ namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
|
||||
public bool IsOptional => false;
|
||||
|
||||
public TrainerDataFlag Flags;
|
||||
public void HandleAttributeReceived(byte[] data)
|
||||
{
|
||||
if(data.Length < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<FtmsIndoorBikeData.IndoorBikeDataField> list = new List<FtmsIndoorBikeData.IndoorBikeDataField>();
|
||||
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);
|
||||
this.Flags = (TrainerDataFlag)BitConverter.ToUInt16(data, 0);
|
||||
int b = 2;
|
||||
if (Flags.HasFlag(TrainerDataFlag.Cadence))
|
||||
{
|
||||
this.InstantSpeed = BitConverter.ToUInt16(data, b) / 100f;
|
||||
this.InstantCadence = (ushort)(BitConverter.ToUInt16(data, b + 2) / 2);
|
||||
b += this.SizeOfDataForFlag(TrainerDataFlag.Cadence);
|
||||
}
|
||||
if (Flags.HasFlag(TrainerDataFlag.Power))
|
||||
{
|
||||
this.InstantPower = BitConverter.ToUInt16(data, b);
|
||||
b += this.SizeOfDataForFlag(TrainerDataFlag.Power);
|
||||
}
|
||||
//Debug.Log("速度:" + this.InstantSpeed + "踏频:" + this.InstantCadence + "功率:" + this.InstantPower);
|
||||
}
|
||||
|
||||
public void SetUnavailable()
|
||||
@@ -99,58 +59,6 @@ namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
//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;
|
||||
@@ -216,5 +124,22 @@ namespace Assets.Scripts.Devices.Ble.Characteristic
|
||||
ElapsedTime,
|
||||
RemainingTime,
|
||||
}
|
||||
|
||||
|
||||
public int SizeOfDataForFlag(TrainerDataFlag flag)
|
||||
{
|
||||
int num = 0;
|
||||
switch (flag)
|
||||
{
|
||||
//case RowerDataFlag.MoreData:
|
||||
// break;
|
||||
case TrainerDataFlag.MoreData: num = 2; break;
|
||||
case TrainerDataFlag.Power: num = 2; break;
|
||||
case TrainerDataFlag.Cadence: num = 4; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,18 +8,18 @@ using UnityEngine;
|
||||
|
||||
namespace Assets.Scripts.Devices.Ble.Devices
|
||||
{
|
||||
public class Ftms : BleDevice, ISpeedDevice, IPowerDevice, ICadenceDevice, ITrainerDevice
|
||||
public class Ftms : BleDevice, ISpeedDevice, IPowerDevice, ICadenceDevice, ITrainerDevice, IRequiresRiderWeight
|
||||
{
|
||||
|
||||
public int Power { get => _ftmsIndoorBikeData.InstantPower.GetValueOrDefault(0); set => throw new NotImplementedException(); }
|
||||
public double Speed { get => _ftmsIndoorBikeData.InstantSpeed.GetValueOrDefault(0); set => throw new NotImplementedException(); }
|
||||
public int Cadence { get => _ftmsIndoorBikeData.InstantCadence.GetValueOrDefault(0); set => throw new NotImplementedException(); }
|
||||
|
||||
public double RiderWeight { get; set; }
|
||||
private FtmsIndoorBikeData _ftmsIndoorBikeData;
|
||||
|
||||
private List<BleServiceInfo> Services;
|
||||
private BleCharacteristicInfo controlPointCharacteristic;
|
||||
public Ftms(BlePeripheralInfo peripheralInfo, IBleWinHwInterface bleWinHwInterface) :base(peripheralInfo, bleWinHwInterface, Ant.SensorType.Trainer)
|
||||
public Ftms(BlePeripheralInfo peripheralInfo, IBleWinHwInterface bleWinHwInterface) :base(peripheralInfo, bleWinHwInterface, Ant.SensorType.FtmsTrainer)
|
||||
{
|
||||
this._ftmsIndoorBikeData = new FtmsIndoorBikeData();
|
||||
base.Characteristics.Add(this._ftmsIndoorBikeData);
|
||||
@@ -39,7 +39,7 @@ namespace Assets.Scripts.Devices.Ble.Devices
|
||||
{
|
||||
if (character.MatchGuid(ServiceUuids.Characteristics.IndoorBikeData))
|
||||
{
|
||||
//Debug.Log("功率功能");
|
||||
//Debug.Log("Ftms功率功能");
|
||||
|
||||
this.hwInterface.SubscribeCharacteristic(character, (hw, cha, res) =>
|
||||
{
|
||||
@@ -80,11 +80,12 @@ namespace Assets.Scripts.Devices.Ble.Devices
|
||||
|
||||
public void SetResistanceMode(double value)
|
||||
{
|
||||
|
||||
//throw new NotImplementedException();
|
||||
var data = new byte[]
|
||||
{
|
||||
(byte)4,
|
||||
(byte)0.1
|
||||
(byte)(value * 10)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -99,24 +100,35 @@ namespace Assets.Scripts.Devices.Ble.Devices
|
||||
/// <param name="grade"></param>
|
||||
public void SetTrackResistance(double grade)
|
||||
{
|
||||
if (this.State != Ant.DeviceState.Connected)
|
||||
return;
|
||||
if (controlPointCharacteristic == null)
|
||||
return;
|
||||
if (grade < 0) grade = 0;
|
||||
if (grade > 10) grade = 10;
|
||||
if (this.controlPointCharacteristic != null)
|
||||
{
|
||||
var data = new byte[]
|
||||
{
|
||||
(byte)4,
|
||||
(byte)(grade * 10)
|
||||
};
|
||||
this.hwInterface.WriteCharacteristic(this.controlPointCharacteristic, data);
|
||||
}
|
||||
//if (this.State != Ant.DeviceState.Connected)
|
||||
// return;
|
||||
//if (controlPointCharacteristic == null)
|
||||
// return;
|
||||
|
||||
short windSpeed = 0;
|
||||
short value2 = (short)(grade);
|
||||
byte rollingResistanceCoefficient = (byte)(0.004 * 10000);
|
||||
byte windResistanceCoefficient = 0;
|
||||
var data = new List<byte>();// { 17, (byte)windSpeed, (byte)value2, rollingResistanceCoefficient, windResistanceCoefficient };
|
||||
data.Add(17);
|
||||
data.AddRange(BitConverter.GetBytes(windSpeed));
|
||||
data.AddRange(BitConverter.GetBytes(value2));
|
||||
data.AddRange(BitConverter.GetBytes(rollingResistanceCoefficient));
|
||||
data.AddRange(BitConverter.GetBytes(windResistanceCoefficient));
|
||||
//short windSpeed = 0;
|
||||
//short value2 = (short)(grade);
|
||||
//byte rollingResistanceCoefficient = (byte)(0.004 * 10000);
|
||||
//byte windResistanceCoefficient = 0;
|
||||
//var data = new List<byte>();// { 17, (byte)windSpeed, (byte)value2, rollingResistanceCoefficient, windResistanceCoefficient };
|
||||
//data.Add(17);
|
||||
//data.AddRange(BitConverter.GetBytes(windSpeed));
|
||||
//data.AddRange(BitConverter.GetBytes(value2));
|
||||
//data.AddRange(BitConverter.GetBytes(rollingResistanceCoefficient));
|
||||
//data.AddRange(BitConverter.GetBytes(windResistanceCoefficient));
|
||||
|
||||
|
||||
this.hwInterface.WriteCharacteristic(this.controlPointCharacteristic, data.ToArray());
|
||||
//this.hwInterface.WriteCharacteristic(this.controlPointCharacteristic, data.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,7 @@ namespace Assets.Scripts.Ble
|
||||
}
|
||||
if(item.IdByteArray == ServiceUuids.Ftms)
|
||||
{
|
||||
sensor = SensorType.Trainer;
|
||||
sensor = SensorType.FtmsTrainer;
|
||||
}
|
||||
else if(item.IdByteArray == ServiceUuids.HeartRate)
|
||||
{
|
||||
|
||||
@@ -195,6 +195,8 @@ namespace Assets.Scripts.Ble
|
||||
return Get(ServiceUuids.PowerBeam).IdGuid;
|
||||
case SensorType.Trainer:
|
||||
return Get(ServiceUuids.TacxBle).IdGuid;
|
||||
case SensorType.FtmsTrainer:
|
||||
return Get(ServiceUuids.Ftms).IdGuid;
|
||||
default:
|
||||
return Guid.Empty;
|
||||
}
|
||||
|
||||
@@ -151,6 +151,10 @@ namespace Assets.Scripts.Ble
|
||||
{
|
||||
sensor = SensorType.Trainer;
|
||||
}
|
||||
else if (item.IdByteArray == ServiceUuids.Ftms)
|
||||
{
|
||||
sensor = SensorType.FtmsTrainer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user