using Assets.Scenes.Ride.Scripts; using Assets.Scripts; using Assets.Scripts.Apis.Models; using Assets.Scripts.Ble.Service; using Assets.Scripts.Devices; using Assets.Scripts.Devices.Ant; using Assets.Scripts.Devices.Ant.Interfaces; using Assets.Scripts.Devices.Ble; using Assets.Scripts.Devices.Ble.Characteristic; using Assets.Scripts.Devices.Ble.Devices; using ChartAndGraph; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; public class RowerHomeScript : PFUIPanel { private class TempRowerCalc { public int power { get; set; } public ushort pace { get; set; } public uint rate { get; set; } public int heartRate { get; set; } } /// /// 划船机数据 /// private FtmsRowerData RowerData { get { var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected) && d.Sensor == SensorType.Rower); if (device != null) { return ((IRowerDevice)device).rowerData; } return null; } } protected override void OnDestroy() { Debug.Log("銷毀"); } private IRowerDevice Rower { get { var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected || d.State == DeviceState.Connecting) && d.Sensor == SensorType.Rower); if (device != null) { return (IRowerDevice)device; } return null; } } /// /// 心率数据 /// private int? HeartRate { get { var device = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected || d.State == DeviceState.Connecting) && d.Sensor == SensorType.HeartRate); if (device != null) { return ((IHeartRateDevice)device).HeartRate; } return null; } } GameObject btnStart; Transform left, bottom; float timer = 1.0f; EventHandler PaintPullCurveDelegate; List pullList = new List(); Dictionary spriteDict; List records; List values; DateTime startTime,createTime; double Kj = 0; int seconds = 0; bool isPause = false; /// /// 计算停止的秒数,如果超过5秒,除了累加值都变成--,这些值记录为0,提示用户如果超过90秒,将直接保存数据 /// 如果5-90秒有拉力,则继续滑行 /// 如果超过90秒都没有拉力,则直接保存 /// int stopSeconds = 0; uint totalDistance = 0; protected override void Start() { var nav = transform.Find("MainNav-mobile").GetComponent(); nav.SetButtonActive(new List {1,4,6 }, null, new NewMainNav.CustomButton(Resources.Load("Images/Rower/骑行"), () => { ReturnHome(); })); } protected override void Awake() { spriteDict = new Dictionary() { {"Start",Resources.Load("Images/Rower/System_play")}, {"Untagged",Resources.Load("Images/Rower/System_pause")}, {0,Resources.Load("Images/Rower/序列帧/划船机0001") }, {1,Resources.Load("Images/Rower/序列帧/划船机0002") }, {2,Resources.Load("Images/Rower/序列帧/划船机0003") }, {3,Resources.Load("Images/Rower/序列帧/划船机0004") }, {4,Resources.Load("Images/Rower/序列帧/划船机0005") }, {5,Resources.Load("Images/Rower/序列帧/划船机0006") }, {6,Resources.Load("Images/Rower/序列帧/划船机0007") }, {7,Resources.Load("Images/Rower/序列帧/划船机0008") }, {8,Resources.Load("Images/Rower/序列帧/划船机0009") }, {9,Resources.Load("Images/Rower/序列帧/划船机0010") }, {10,Resources.Load("Images/Rower/序列帧/划船机0011") }, {11,Resources.Load("Images/Rower/序列帧/划船机0012") }, {12,Resources.Load("Images/Rower/序列帧/划船机0013") }, {13,Resources.Load("Images/Rower/序列帧/划船机0014") }, {14,Resources.Load("Images/Rower/序列帧/划船机0015") }, }; GetComponent().localScale = Vector3.one; GetComponent().localPosition = Vector3.zero; //mainNav.ShowExit(); var btnHome = transform.Find("Other/BtnHome").gameObject; UIManager.AddEvent(btnHome, UnityEngine.EventSystems.EventTriggerType.PointerClick, b => ReturnHome()); btnStart = transform.Find("Other1/BtnStart").gameObject; UIManager.AddEvent(btnStart, UnityEngine.EventSystems.EventTriggerType.PointerClick, b => HandleStartOrPause()); left = transform.Find("Left"); bottom = transform.Find("Bottom"); PaintPullCurveDelegate = new EventHandler(PaintPullCurve); transform.Find("PFUISlider").GetComponent().SetValueChanged(r => { var v = (ushort)(r * 65535); if (Rower != null) { Rower.SetResistanceLevel(v); //RowerData. } }); Init(); } public override void Show() { base.Show(); var mainNav = this.transform.Find("MainNav").GetComponent(); mainNav.ShowRowerTab(); transform.MyDOFade(); Debug.Log("140,开始扫描"); App.MainDeviceAdapter.StartScan(); Init(); //transform.Find("Left/Rower").GetComponent().StartAnimation(); } void Disconnect() { foreach(var d in App.MainDeviceAdapter.GetDevices()) { if ((d.State == DeviceState.Connected || d.State == DeviceState.Connecting) && (d.Sensor == SensorType.Rower || d.Sensor == SensorType.HeartRate)) { d.Disconnect(); } } App.MainDeviceAdapter.StopScan(); } void HandleDiscardDirect() { openTimer = false; isPause = true; Debug.Log(RowerData); btnStart.GetComponent().sprite = spriteDict["Start"]; btnStart.tag = "Start"; Init(); } void HandleSaveDirect() { openTimer = false; isPause = true; btnStart.GetComponent().sprite = spriteDict["Start"]; btnStart.tag = "Start"; Save(); Init(); } private void HandleStartOrPause() { //UIManager.ShowRowerResult(); //return; if (btnStart.CompareTag("Start")) { #if !UNITY_EDITOR if (RowerData == null) { Utils.showToast(null, "Please connect the device!", isLowest: true); return; } #endif UIManager.ShowCountDownAnimation(() => { if (RowerData != null) { RowerData.PullChanged -= PaintPullCurveDelegate; RowerData.PullChanged += PaintPullCurveDelegate; } if (!isPause) { startTime = UIManager.Now.GetDateTime(); } TimerTicks(); openTimer = true; timer = 1.0f; btnStart.GetComponent().sprite = spriteDict["Untagged"]; btnStart.tag = "Untagged"; }, ()=> { if (Rower != null && !isPause) { Rower.Reset(); } }); } else { openTimer = false; isPause = true; btnStart.GetComponent().sprite = spriteDict["Start"]; btnStart.tag = "Start"; UIManager.ShowConfirm3("Quit", "Do you want to keep the record?", () => { UIManager.CloseConfirm3(); Save(); Init(); }, ()=> { Init(); }, ()=> { }); } Debug.Log(RowerData); //StartCoroutine(); } private void Save() { createTime = UIManager.Now.GetDateTime(); var bleDevice = App.MainDeviceAdapter.GetDevices().FirstOrDefault(d => (d.State == DeviceState.Connected || d.State == DeviceState.Connecting) && d.Sensor == SensorType.Rower) as BleDevice; RowerRecordModel model = new RowerRecordModel(); model.Ticks = records.Count; if (bleDevice != null) { model.ManufacturerName = bleDevice.Name + " " + bleDevice.Network + " " + bleDevice.Sensor; model.DeviceNumber = $"{ bleDevice.Address },{ bleDevice.Sensor }"; } model.Id = Guid.NewGuid().ToString(); model.Weight = App.CurrentUser.Weight; model.Kj = RowerData.TotalEnergy; model.StartTime = startTime; model.CreateTime = createTime; Debug.Log(values.Count); if (values.Count > 0) { model.MaxPower = values.Max(x => x.power); if (values.Count(x => x.pace > 0) > 0) { model.MaxPace = values.Where(x => x.pace > 0).Min(x => x.pace); model.AvgPace = values.Where(x => x.pace > 0).Average(x => x.pace); } model.MaxRate = values.Max(x => x.rate); model.MaxHeartRate = values.Max(x => x.heartRate); model.AvgPower = values.Average(x => x.power); model.AvgRate = values.Average(x => x.rate); model.AvgHeartRate = (int)values.Average(x => x.heartRate); } model.StrokeCount = RowerData.StrokeCount; model.TotalTime = RowerData.ElapsedTime; model.TotalDistance = RowerData.TotalDistance; var path = PFConstants.RowerRecordFolder + "/" + model.Id; Helper.CreateDirectoryIfNotExsit(path); var files = new List(); try { var fname = path + "/" + model.Id + ".txt"; using (var fs = new FileInfo(fname).OpenWrite()) { var stream = new StreamWriter(fs); stream.BaseStream.Seek(0, SeekOrigin.End); foreach (var item in records) { stream.Write(item + "\r\n"); } stream.Flush(); stream.Close(); files.Add(fname); } } catch (Exception ex) { Helper.DelectDir(path); Debug.Log(ex.Message); } UIManager.ShowRowerWelldone(model); Disconnect(); Task.Run(()=> { var res = ConfigHelper.rowerApi.Add(model, files); }); } private void Init() { if (RowerData != null) { RowerData.Reset(); } if (Rower != null) { Rower.Reset(); } btnStart.tag = "Start"; btnStart.GetComponent().sprite = spriteDict["Start"]; left.Find("Rower").GetComponent().sprite = spriteDict[0]; left.Find("LeftImage/Value").GetComponent().fillAmount = 0; left.Find("RightImage/Value").GetComponent().fillAmount = 0; left.Find("Times/Value").GetComponent().text = "---"; left.Find("Calories/Value").GetComponent().text = "---"; pullList = new List(); transform.Find("Mid/GraphChart").GetComponent().SetData(pullList); openTimer = false; bottom.Find("Time/Value").GetComponent().text = "---"; bottom.Find("TrueTime/Value").GetComponent().text = "---"; bottom.Find("KM/Value").GetComponent().text = "---"; bottom.Find("W/Value").GetComponent().text = "---"; bottom.Find("W/AvgValue").GetComponent().text = "---"; bottom.Find("500/Value").GetComponent().text = "---"; bottom.Find("500/AvgValue").GetComponent().text = "---"; bottom.Find("MS/Value").GetComponent().text = "---"; bottom.Find("MS/AvgValue").GetComponent().text = "---"; bottom.Find("BPM/Value").GetComponent().text = "---"; records = new List(); values = new List(); Kj = 0; x = 0; seconds = 0; totalDistance = 0; stopSeconds = 0; isPause = false; } private void ReturnHome() { if (seconds > 0) { Utils.showToast(null, "Please end this training.", isLowest: true); return; } Disconnect(); UIManager.ShowHomePanel(); } // Update is called once per frame bool openTimer = false; double x = 0f; //List tempList = new List() //{ // 0,1230,4,500,12,13,16,0,0,0,20,30,40,50,60,500 //}; //int tempx = 0; void TimerTicks() { //Debug.Log(123); //PaintPullCurve(tempList[(tempx++) % tempList.Count]); #if !UNITY_EDITOR if (Rower == null) { HandleDiscardDirect(); return; } #endif if (RowerData == null) return; var heartRate = HeartRate ?? 0; bottom.Find("BPM/Value").GetComponent().text = heartRate.ToString(); if (totalDistance == RowerData.TotalDistance) { //判定一次停止 stopSeconds++; } else { stopSeconds = 0; } if (stopSeconds >= 91) { Debug.Log("保存"); HandleSaveDirect(); return; } else if (stopSeconds == 81) { Utils.showToast(null, "Record will be saved!", duration: 10, stopFunc: () => stopSeconds < 6, isLowest: true,showSeconds:true); return; } else if (stopSeconds >= 6) { if (stopSeconds == 6) { Utils.showToast(null, "Please keep rowing...", duration: 60, stopFunc: () => stopSeconds < 6, isLowest: true); } bottom.Find("Time/Value").GetComponent().text = TimeSpan.FromSeconds(seconds++).ToString(); bottom.Find("W/Value").GetComponent().text = "---"; bottom.Find("W/AvgValue").GetComponent().text = "---"; bottom.Find("500/Value").GetComponent().text = "---"; bottom.Find("500/AvgValue").GetComponent().text = "---"; bottom.Find("MS/Value").GetComponent().text = "---"; bottom.Find("MS/AvgValue").GetComponent().text = "---"; records.Add($"{RowerData.StrokeCount},{RowerData.ElapsedTime},{RowerData.TotalDistance},0,0,0,{RowerData.ResistanceLevel},{heartRate}"); values.Add(new TempRowerCalc() { pace = 0, power = 0, rate = 0, heartRate = heartRate }); return; } totalDistance = RowerData.TotalDistance; bottom.Find("Time/Value").GetComponent().text = TimeSpan.FromSeconds(seconds++).ToString(); bottom.Find("TrueTime/Value").GetComponent().text = TimeSpan.FromSeconds(RowerData.ElapsedTime).ToString(); bottom.Find("KM/Value").GetComponent().text = totalDistance.ToString(); var power = RowerData.InstantaneousPower; bottom.Find("W/Value").GetComponent().text = power.ToString(); bottom.Find("W/AvgValue").GetComponent().text = RowerData.AveragePower.ToString(); var pace = RowerData.InstantaneousPace; bottom.Find("500/Value").GetComponent().text = TimeSpan.FromSeconds(pace).ToString(@"mm\:ss"); bottom.Find("500/AvgValue").GetComponent().text = TimeSpan.FromSeconds(RowerData.AveragePace).ToString(@"mm\:ss"); var rate = RowerData.StrokeRate; bottom.Find("MS/Value").GetComponent().text = rate.ToString(); bottom.Find("MS/AvgValue").GetComponent().text = RowerData.AverageStrokeRate.ToString(); var strokeCount = RowerData.StrokeCount; //if (ushort.TryParse(left.Find("Times/Value").GetComponent().text, out ushort originStroke)) //{ // if (strokeCount != originStroke) // { // left.Find("Rower").GetComponent().StartAnimation(); // } //} left.Find("Times/Value").GetComponent().text = strokeCount.ToString(); left.Find("Calories/Value").GetComponent().text = RowerData.TotalEnergy.ToString(); records.Add($"{RowerData.StrokeCount},{RowerData.ElapsedTime},{RowerData.TotalDistance},{RowerData.InstantaneousPower},{RowerData.InstantaneousPace},{RowerData.StrokeRate},{RowerData.ResistanceLevel},{heartRate}"); values.Add(new TempRowerCalc() { pace = pace, power = power, rate = rate,heartRate = heartRate }); //Debug.Log(1); } void PaintPullCurve(object sender, EventArgs e) { var ftms = (FtmsRowerData)sender; //Debug.Log(ftms.PullValue); PaintPullCurve(ftms.PullValue); } bool isPlay = false; void PaintPullCurve(ushort y) { Debug.Log("收到拉力" + y); #if !UNITY_EDITOR if (!openTimer) { RowerData.PullChanged -= PaintPullCurveDelegate; return; } #endif //if (y > 1200) y = 1200; //拉力条 var rate = ((float)y) * 2 / 1200; if (rate > 1) rate = 1f; left.Find("LeftImage/Value").GetComponent().fillAmount = rate; left.Find("RightImage/Value").GetComponent().fillAmount = rate; //动画 //left.Find("Rower").GetComponent().sprite = spriteDict[y / 67]; //曲线 if (y == 0) { if (pullList.Count == 0) { isPlay = true; x = 0; pullList.Add(new DoubleVector2(x, y)); transform.Find("Mid/GraphChart").GetComponent().SetData(pullList); } else if (pullList.Count > 1) { x += 0.1; pullList.Add(new DoubleVector2(x, y)); transform.Find("Mid/GraphChart").GetComponent().SetData(pullList); pullList.Clear(); x = 0; isPlay = true; pullList.Add(new DoubleVector2(x, y)); } else { //只有0并且两秒没拉,曲线消失 if (stopSeconds == 1) { transform.Find("Mid/GraphChart").GetComponent().SetData(new List()); } } } else { x += 0.1; pullList.Add(new DoubleVector2(x, y)); if (pullList.Count > 5 && isPlay) { Debug.Log("开始动画"); isPlay = false; left.Find("Rower").GetComponent().StartAnimation(); } transform.Find("Mid/GraphChart").GetComponent().SetData(pullList); } //Debug.Log($"{x},{y}"); //transform.Find("Mid/GraphChart").GetComponent().SetData(pullList); //pullList.Add(new DoubleVector2(x, y)); //if (pullList.Count >= 75) //{ // pullList.RemoveAt(0); // pullList = pullList.Select(val => new DoubleVector2(val.x - 0.1, val.y)).ToList(); //} //else //{ // x += 0.1f; //} } void Update() { if (openTimer) { timer -= Time.deltaTime; if (timer <= 0) { TimerTicks(); timer = 1f + timer; } } } }