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 { /// /// 划桨频率 /// public uint StrokeRate { get; set; } = 0; /// /// 划桨次数 /// public UInt16 StrokeCount { get; set; } = 0; /// /// 平均划桨频率 /// public int AverageStrokeRate { get; set; } = 0; private UInt32 _totalDistance = 1; public UInt32 TotalDistance { get => _totalDistance; set { if (_totalDistance == 0 && value != 0 && StartEvent != null) { StartEvent.Invoke(this, null); } _totalDistance = value; } } //private UInt16 _instantaneousPace = 1; /// /// 即时配速 /// public UInt16 InstantaneousPace { get; set; } = 0; /// /// 平均配速 /// public UInt16 AveragePace { get; set; } = 0; public int InstantaneousPower { get; set; } = 0; public int AveragePower { get; set; } = 0; public 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") || device.Name.Contains("PF")) { return thinkRes; } else { return commonRes; } } set { } } /// /// 运行时间 /// public int ElapsedTime { get; set; } = 0; public int TotalEnergy { get; set; } = 0; public int EnergyPerHour { get; set; } = 0; public int EnergyPerMinute { get; 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; //开始事件 public event EventHandler StartEvent; //结束事件 public event EventHandler CompleteEvent; //日志事件 public event EventHandler LogEvent; private ushort _pullValue; public ushort PullValue { get { return _pullValue; } set { _pullValue = value; if (this.PullChanged != null) { this.PullChanged(this, null); } } } public bool MoreDataFlag { get { return this.Flags.HasFlag(RowerDataFlag.MoreData); } } private string[] deviceNamePool = new string[] {"Think","PF" }; private List tempPullList = new List(); 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(",", 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 }米"; if (vvv < 10) { LogEvent?.Invoke(DateTime.Now.ToString() + ":" + output,null); //App.cacheList.Add(DateTime.Now.ToString() + ":" + output); } 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)) { var newRes = BitConvertHelper.ToInt16(data, b); var resChanged = newRes != this.commonRes; this.commonRes = newRes; var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected) && d.Sensor == SensorType.Rower); if (resChanged && device != null && deviceNamePool.FirstOrDefault(x => device.Name.ToLower().Contains(x.ToLower())) == null && RowerResChanged != null) { RowerResChanged.Invoke(this, 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)) { var originRes = BitConvertHelper.ToInt16(data, b + 1); var thinkResChanged = originRes != this.thinkRes; this.thinkRes = BitConvertHelper.ToInt16(data, b + 1); var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected) && d.Sensor == SensorType.Rower); if (thinkResChanged && device != null && deviceNamePool.FirstOrDefault(x=>device.Name.ToLower().Contains(x.ToLower()))!=null && RowerResChanged != null) { RowerResChanged.Invoke(this, null); } b += this.SizeOfDataForFlag(RowerDataFlag.ThinkDragFactor); } if (this.Flags.HasFlag(RowerDataFlag.Pull)) { for (int pullB = 4; pullB < data.Length; pullB += 2) { var val = BitConverter.ToUInt16(data, pullB); val = Convert.ToUInt16(((double)val) /9.8f); tempPullList.Add(val); PullValue = val; } Debug.Log("拉力列表:" + string.Join(",", tempPullList)); if (pullList == null) pullList = new List(); foreach (var pull in tempPullList) { if (pull == 0) { if (pullList.Count != 0) { PeakDriveForce = pullList.Max(); AverageDriveForce = (double)pullList.Average(x=>x); } pullList.Clear(); } pullList.Add(pull); } tempPullList.Clear(); } } List pullList { get; set; } 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; } } }