405 lines
14 KiB
C#
405 lines
14 KiB
C#
using Assets.Scripts.Ble;
|
|
using Assets.Scripts.Devices.Ant;
|
|
using Assets.Scripts.Devices.Ble.Interfaces;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace Assets.Scripts.Devices.Ble.Characteristic
|
|
{
|
|
public class FtmsRowerData : ICharacteristic, IRowerCommonData
|
|
{
|
|
/// <summary>
|
|
/// 划桨频率
|
|
/// </summary>
|
|
public uint StrokeRate { get; private set; } = 0;
|
|
/// <summary>
|
|
/// 划桨次数
|
|
/// </summary>
|
|
public UInt16 StrokeCount { get; private set; } = 0;
|
|
/// <summary>
|
|
/// 平均划桨频率
|
|
/// </summary>
|
|
public int AverageStrokeRate { get; private set; } = 0;
|
|
|
|
public UInt32 TotalDistance { get; private set; } = 0;
|
|
/// <summary>
|
|
/// 即时配速
|
|
/// </summary>
|
|
public UInt16 InstantaneousPace { get; private set; } = 0;
|
|
/// <summary>
|
|
/// 平均配速
|
|
/// </summary>
|
|
public UInt16 AveragePace { get; private set; } = 0;
|
|
|
|
public int InstantaneousPower { get; private set; } = 0;
|
|
|
|
public int AveragePower { get; private set; } = 0;
|
|
public static event EventHandler RowerResChanged;
|
|
private int commonRes = 50;
|
|
private int thinkRes = 50;
|
|
|
|
public int ResistanceLevel
|
|
{
|
|
get
|
|
{
|
|
var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected) && d.Sensor == SensorType.Rower);
|
|
if (device == null) return 0;
|
|
if (device.Name.Contains("Think"))
|
|
{
|
|
return thinkRes;
|
|
}
|
|
else
|
|
{
|
|
return commonRes;
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 运行时间
|
|
/// </summary>
|
|
public int ElapsedTime { get; private set; } = 0;
|
|
|
|
public int TotalEnergy { get; private set; } = 0;
|
|
|
|
public int EnergyPerHour { get; private set; } = 0;
|
|
|
|
public int EnergyPerMinute { get; private set; } = 0;
|
|
public double PeakDriveForce { get; set; } = 0;
|
|
public double AverageDriveForce { get; set; } = 0;
|
|
|
|
public Guid Uuid => ServiceUuids.Characteristics.RowerData;
|
|
|
|
public Guid ServiceUuid => ServiceUuids.Get(ServiceUuids.Ftms).IdGuid;
|
|
|
|
public bool IsOptional => false;
|
|
|
|
public RowerDataFlag Flags;
|
|
//拉力相关
|
|
public event EventHandler PullChanged;
|
|
private ushort _pullValue;
|
|
public ushort PullValue
|
|
{
|
|
get { return _pullValue; }
|
|
set
|
|
{
|
|
_pullValue = value;
|
|
if (this.PullChanged != null)
|
|
{
|
|
this.PullChanged(this, new EventArgs());
|
|
}
|
|
}
|
|
}
|
|
public bool MoreDataFlag
|
|
{
|
|
get
|
|
{
|
|
return this.Flags.HasFlag(RowerDataFlag.MoreData);
|
|
}
|
|
}
|
|
|
|
public void HandleAttributeReceived(byte[] data)
|
|
{
|
|
if (data == null || data.Length < 2)
|
|
{
|
|
throw new ArgumentException("数据异常" + string.Join(",", data));
|
|
}
|
|
//throw new NotImplementedException();
|
|
//if(data[0] == 1)
|
|
//{
|
|
// return;
|
|
//}
|
|
var output = "";
|
|
output += "收到消息:" + string.Join("\t", data);
|
|
|
|
|
|
this.Flags = (RowerDataFlag)BitConverter.ToUInt16(data, 0);
|
|
int b = 2;
|
|
if (!this.MoreDataFlag)
|
|
{
|
|
//this.instantSpeed = new double?((double)BitConverter.ToUInt16(data, (int)b) * 0.01);
|
|
this.StrokeRate = (uint)Math.Round(BitConvertHelper.ToUInt8(data, b) / 2d);
|
|
b += 1;
|
|
this.StrokeCount = BitConvertHelper.ToUInt16(data, b);
|
|
b += 2;
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.MoreData);
|
|
}
|
|
//平均浆频
|
|
if (this.Flags.HasFlag(RowerDataFlag.AverageStrokeRate))
|
|
{
|
|
var vvv = BitConvertHelper.ToUInt8(data, (int)b) / 2;
|
|
//Debug.WriteLine($"平均浆频:{ vvv }");
|
|
output += $" 平均浆频:{ vvv }";
|
|
this.AverageStrokeRate = vvv;
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.AverageStrokeRate);
|
|
|
|
//output += $" 次数:{ BitConvertHelper.ToUInt16(data, b) }";
|
|
//b += 3;
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.TotalDistance))
|
|
{
|
|
var vvv = BitConvertHelper.ToUInt24(data, (int)b);
|
|
output += $" 总距离{ vvv }米";
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.TotalDistance);
|
|
|
|
this.TotalDistance = vvv;
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.InstantaneousPace))
|
|
{
|
|
//this.InstantCadence = new int?((int)(BitConvertHelper.ToUInt16(data, (int)b) / 2));
|
|
this.InstantaneousPace = BitConvertHelper.ToUInt16(data, b);
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.InstantaneousPace);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.AveragePace))
|
|
{
|
|
this.AveragePace = BitConvertHelper.ToUInt16(data, b);
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.AveragePace);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.InstantPower))
|
|
{
|
|
var power = new int?((int)BitConvertHelper.ToInt16(data, (int)b));
|
|
output += $" 功率:{ power }";
|
|
this.InstantaneousPower = power.GetValueOrDefault(0);
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.InstantPower);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.AveragePower))
|
|
{
|
|
//var power = new int?((int)BitConverter.ToInt16(data, (int)b));
|
|
this.AveragePower = BitConvertHelper.ToInt16(data, b);
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.AveragePower);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.ResistanceLevel))
|
|
{
|
|
this.commonRes = BitConvertHelper.ToInt16(data, b);
|
|
var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected) && d.Sensor == SensorType.Rower);
|
|
if (device != null && !device.Name.Contains("Think") && RowerResChanged != null)
|
|
{
|
|
RowerResChanged.Invoke(this.commonRes, null);
|
|
}
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.ResistanceLevel);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.ExpendedEnergy))
|
|
{
|
|
this.TotalEnergy = BitConvertHelper.ToInt16(data, b);
|
|
b += 2;
|
|
this.EnergyPerHour = BitConvertHelper.ToInt16(data, b);
|
|
b += 2;
|
|
this.EnergyPerMinute = data[b];
|
|
b += 1;
|
|
//b += this.SizeOfDataForFlag(RowerDataFlag.ExpendedEnergy);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.HeartRate))
|
|
{
|
|
//this.HeartRate = new int?((int)BitConverter.ToUInt8(data, (int)b));
|
|
//(int)data[(int)b];
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.HeartRate);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.MetabolicEquivalent))
|
|
{
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.MetabolicEquivalent);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.ElapsedTime))
|
|
{
|
|
this.ElapsedTime = BitConvertHelper.ToInt16(data, b);
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.ElapsedTime);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.RemainingTime))
|
|
{
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.RemainingTime);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.ThinkDragFactor))
|
|
{
|
|
this.thinkRes = BitConvertHelper.ToInt16(data, b + 1);
|
|
var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected) && d.Sensor == SensorType.Rower);
|
|
if (device != null && device.Name.Contains("Think") && RowerResChanged != null)
|
|
{
|
|
RowerResChanged.Invoke(this.thinkRes, null);
|
|
}
|
|
b += this.SizeOfDataForFlag(RowerDataFlag.ThinkDragFactor);
|
|
}
|
|
if (this.Flags.HasFlag(RowerDataFlag.Pull))
|
|
{
|
|
List<ushort> list = new List<ushort>();
|
|
for (int pullB = 4; pullB < data.Length; pullB += 2)
|
|
{
|
|
var val = BitConverter.ToUInt16(data, pullB);
|
|
val = Convert.ToUInt16(((double)val) /9.8f);
|
|
list.Add(val);
|
|
PullValue = val;
|
|
|
|
}
|
|
if (pullList == null) pullList = new List<ushort>();
|
|
foreach (var pull in list)
|
|
{
|
|
if (pull == 0)
|
|
{
|
|
if (pullList.Count != 0)
|
|
{
|
|
PeakDriveForce = pullList.Max();
|
|
AverageDriveForce = (double)pullList.Average(x=>x);
|
|
}
|
|
pullList.Clear();
|
|
}
|
|
pullList.Add(pull);
|
|
}
|
|
Debug.Log("拉力:" + string.Join(",",list));
|
|
}
|
|
}
|
|
List<ushort> pullList;
|
|
public void Reset()
|
|
{
|
|
this.StrokeRate = 0;
|
|
this.StrokeCount = 0;
|
|
this.AverageStrokeRate = 0;
|
|
this.TotalDistance = 0;
|
|
this.InstantaneousPace = 0;
|
|
this.AveragePace = 0;
|
|
this.InstantaneousPower = 0;
|
|
this.AveragePower = 0;
|
|
//this.commonRes = 50;
|
|
//this.thinkRes = 50;
|
|
//this.ResistanceLevel = 0;
|
|
this.TotalEnergy = 0;
|
|
this.EnergyPerHour = 0;
|
|
this.EnergyPerMinute = 0;
|
|
this.ElapsedTime = 0;
|
|
}
|
|
|
|
public int SizeOfDataForFlag(RowerDataFlag flag)
|
|
{
|
|
int num = 0;
|
|
switch (flag)
|
|
{
|
|
//case RowerDataFlag.MoreData:
|
|
// break;
|
|
case RowerDataFlag.AverageStrokeRate:
|
|
num = 1;
|
|
break;
|
|
case RowerDataFlag.TotalDistance:
|
|
num = 3;
|
|
break;
|
|
case RowerDataFlag.InstantaneousPace:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.AveragePace:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.InstantPower:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.AveragePower:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.ResistanceLevel:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.ExpendedEnergy:
|
|
num = 5;
|
|
break;
|
|
case RowerDataFlag.HeartRate:
|
|
num = 1;
|
|
break;
|
|
case RowerDataFlag.MetabolicEquivalent:
|
|
num = 1;
|
|
break;
|
|
case RowerDataFlag.ElapsedTime:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.RemainingTime:
|
|
num = 2;
|
|
break;
|
|
case RowerDataFlag.ThinkDragFactor:
|
|
num = 5;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
public void SetUnavailable()
|
|
{
|
|
//throw new NotImplementedException();
|
|
}
|
|
//254 0是前七字節 1 41是第二包 1 64是拉力
|
|
[Flags]
|
|
public enum RowerDataFlag
|
|
{
|
|
MoreData = 1,
|
|
AverageStrokeRate = 2,
|
|
TotalDistance = 4,
|
|
InstantaneousPace = 8,
|
|
AveragePace = 16,
|
|
InstantPower = 32,
|
|
AveragePower = 64,
|
|
ResistanceLevel = 128,
|
|
ExpendedEnergy = 256,
|
|
HeartRate = 512,
|
|
MetabolicEquivalent = 1024,
|
|
ElapsedTime = 2048,
|
|
RemainingTime = 4096,
|
|
//单周期能耗
|
|
SingleEnergy = 8192,
|
|
//拉力曲綫
|
|
Pull = 16384,
|
|
//Think 阻力
|
|
ThinkDragFactor = 32768
|
|
}
|
|
|
|
|
|
|
|
private byte SizeOfDataForFlag1(RowerDataFlag flag)
|
|
{
|
|
if (flag <= RowerDataFlag.InstantPower)
|
|
{
|
|
//if (flag <= RowerDataFlag.AverageCadence)
|
|
//{
|
|
// if (flag - RowerDataFlag.MoreData > 1 && flag != RowerDataFlag.InstantCadence && flag != RowerDataFlag.AverageCadence)
|
|
// {
|
|
// return 0;
|
|
// }
|
|
//}
|
|
//else
|
|
{
|
|
if (flag == RowerDataFlag.TotalDistance)
|
|
{
|
|
return 3;
|
|
}
|
|
if (flag != RowerDataFlag.ResistanceLevel && flag != RowerDataFlag.InstantPower)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else if (flag <= RowerDataFlag.HeartRate)
|
|
{
|
|
if (flag != RowerDataFlag.AveragePower)
|
|
{
|
|
if (flag == RowerDataFlag.ExpendedEnergy)
|
|
{
|
|
return 5;
|
|
}
|
|
if (flag != RowerDataFlag.HeartRate)
|
|
{
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (flag != RowerDataFlag.MetabolicEquivalent && flag != RowerDataFlag.ElapsedTime && flag != RowerDataFlag.RemainingTime)
|
|
{
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
}
|