using System.Diagnostics; using HeartRateMonitorAndroid.Models; using HeartRateMonitorAndroid.Services; using HeartRateMonitorAndroid.UI; namespace HeartRateMonitorAndroid; public partial class MainPage : ContentPage { private const string Tag = "HeartRateMonitor"; private const int GraphUpdateIntervalMs = 1000; // 每秒更新一次图表 private const string DefaultWebsocketUrl = "wss://ws.nuanr-mxi.com/ws"; // 默认WebSocket服务器地址 // 图表更新定时器 private IDispatcherTimer _graphUpdateTimer; // WebSocket相关 private WebSocketService.HeartRateWebSocketClient _webSocketClient; private bool _isWebSocketEnabled = false; private string _webSocketUrl = DefaultWebsocketUrl; // 后台模式标志 private bool _isRunningInBackground = false; // 服务 private readonly BluetoothService _bluetoothService; // 心率数据模型 private readonly HeartRateSessionData _sessionData = new(); private readonly HeartRateGraphDrawable _heartRateGraph = new(); public MainPage() { InitializeComponent(); // 初始化蓝牙服务 _bluetoothService = new BluetoothService(); _bluetoothService.StatusUpdated += UpdateStatus; _bluetoothService.HeartRateUpdated += UpdateHeartRate; _bluetoothService.DeviceDiscovered += OnHeartRateDeviceDiscovered; // 初始化图表 heartRateGraphicsView.Drawable = _heartRateGraph; // 初始化图表更新定时器 InitializeGraphUpdateTimer(); // 检查蓝牙状态 _bluetoothService.CheckBluetoothState(); } /// /// 初始化图表更新定时器 /// private void InitializeGraphUpdateTimer() { _graphUpdateTimer = Dispatcher.CreateTimer(); _graphUpdateTimer.Interval = TimeSpan.FromMilliseconds(GraphUpdateIntervalMs); _graphUpdateTimer.Tick += async (s, e) => await UpdateGraph(); _graphUpdateTimer.Start(); } /// /// 更新图表和通知 /// private async Task UpdateGraph() { // 发送心率数据到服务器 await SendHeartRateToServerAsync(_sessionData.LatestHeartRate); // 更新图表 _heartRateGraph.UpdateData(_sessionData.HeartRateData); heartRateGraphicsView.Invalidate(); // 重置新数据标记 _sessionData.ResetNewDataFlag(); // 如果在后台运行且有数据,更新通知 if (_isRunningInBackground && _sessionData.HeartRateData.Count > 0) { var duration = _sessionData.GetSessionDuration(); NotificationService.ShowHeartRateNotification( _sessionData.LatestHeartRate, _sessionData.AverageHeartRate, _sessionData.MinHeartRate, _sessionData.MaxHeartRate, duration); } } /// /// 更新状态标签 /// private void UpdateStatus(string status) { MainThread.BeginInvokeOnMainThread(() => { statusLabel.Text = status; }); } /// /// 更新心率数据 /// private void UpdateHeartRate(int heartRate) { MainThread.BeginInvokeOnMainThread(() => { // 更新UI上的心率显示 heartRateLabel.Text = $"心率: {heartRate} BPM"; // 添加新的心率数据点 _sessionData.AddHeartRate(heartRate); // 如果是第一个数据点,隐藏提示标签 if (_sessionData.HeartRateData.Count == 1) { noDataLabel.IsVisible = false; } // 更新统计信息显示 minHeartRateLabel.Text = _sessionData.MinHeartRate.ToString(); maxHeartRateLabel.Text = _sessionData.MaxHeartRate.ToString(); avgHeartRateLabel.Text = _sessionData.AverageHeartRate.ToString("0"); }); } /// /// 扫描按钮点击事件 /// private async void OnScanClicked(object sender, EventArgs e) { await _bluetoothService.StartScanAsync(); } /// /// 心率设备发现事件处理 /// private async void OnHeartRateDeviceDiscovered(Plugin.BLE.Abstractions.Contracts.IDevice device) { await MainThread.InvokeOnMainThreadAsync(async () => { statusLabel.Text = $"检测到心率设备: {device.Name ?? "未知设备"}"; await _bluetoothService.ConnectToDeviceAsync(device); // 连接成功后重置心率数据显示 if (_bluetoothService.ConnectedDevice != null) { _sessionData.ResetData(); minHeartRateLabel.Text = "--"; maxHeartRateLabel.Text = "--"; avgHeartRateLabel.Text = "--"; noDataLabel.IsVisible = true; heartRateGraphicsView.Invalidate(); } }); } /// /// 后台运行按钮点击事件 /// private async void OnBackgroundClicked(object sender, EventArgs e) { if (_bluetoothService.ConnectedDevice == null) { await DisplayAlert("提示", "请先连接心率设备", "确定"); return; } _isRunningInBackground = !_isRunningInBackground; if (_isRunningInBackground) { backgroundButton.Text = "停止后台运行"; // 显示通知 if (_sessionData.HeartRateData.Count > 0) { TimeSpan duration = _sessionData.GetSessionDuration(); NotificationService.ShowHeartRateNotification( _sessionData.LatestHeartRate, _sessionData.AverageHeartRate, _sessionData.MinHeartRate, _sessionData.MaxHeartRate, duration); } else { NotificationService.ShowHeartRateNotification(0, 0, 0, 0, TimeSpan.Zero); } // 通知用户应用将在后台运行 await DisplayAlert("后台运行", "应用将在后台继续监测心率。可以通过通知栏查看实时数据。", "确定"); } else { backgroundButton.Text = "后台运行"; // 取消通知 Services.NotificationService.CancelNotification(); } } /// /// WebSocket设置按钮点击事件 /// private async void OnWebSocketSettingsClicked(object sender, EventArgs e) { string result = await DisplayPromptAsync( "配置数据上传", "请输入WebSocket服务器地址:\n格式:wss://example.com/ws", "确定", "取消", _webSocketUrl, maxLength: 100, keyboard: Keyboard.Url); if (string.IsNullOrWhiteSpace(result)) return; if (!result.StartsWith("ws://") && !result.StartsWith("wss://")) { // fallback到默认websocket服务器 result = _webSocketUrl; } try { // 更新按钮状态,显示正在连接 webSocketButton.Text = "正在连接..."; webSocketButton.IsEnabled = false; // 初始化WebSocket客户端 await InitializeWebSocketClientAsync(result); if (_isWebSocketEnabled) { webSocketButton.Text = "数据上传已启用"; webSocketButton.BackgroundColor = Color.FromArgb("#28A745"); // 绿色 await DisplayAlert("连接成功", "心率数据将会实时上传到服务器", "确定"); // 禁用按钮 webSocketButton.IsEnabled = false; } else { webSocketButton.Text = "配置数据上传"; webSocketButton.BackgroundColor = Color.FromArgb("#6C757D"); // 灰色 await DisplayAlert("连接失败", "无法连接到指定的WebSocket服务器,请检查地址或网络连接", "确定"); } } catch (Exception ex) { webSocketButton.Text = "配置数据上传"; webSocketButton.BackgroundColor = Color.FromArgb("#6C757D"); // 灰色 await DisplayAlert("错误", $"配置WebSocket时出错: {ex.Message}", "确定"); } finally { webSocketButton.IsEnabled = true; } } /// /// 初始化WebSocket客户端 /// private async Task InitializeWebSocketClientAsync(string url = null) { // 释放现有的WebSocket客户端 if (_webSocketClient != null) { _webSocketClient.Dispose(); _webSocketClient = null; } // 使用提供的URL或默认URL _webSocketUrl = string.IsNullOrEmpty(url) ? DefaultWebsocketUrl : url; try { _webSocketClient = new Services.WebSocketService.HeartRateWebSocketClient(_webSocketUrl); await _webSocketClient.ConnectAsync(); _isWebSocketEnabled = true; Debug.WriteLine($"{Tag}: WebSocket客户端已初始化,连接到 {_webSocketUrl}"); } catch (Exception ex) { Debug.WriteLine($"{Tag}: 初始化WebSocket客户端失败: {ex.Message}"); _isWebSocketEnabled = false; } } /// /// 发送心率数据到WebSocket服务器 /// private async Task SendHeartRateToServerAsync(int heartRate) { if (!_isWebSocketEnabled || _webSocketClient == null) return; try { var data = new WebSocketService.HeartRateData { HeartRate = heartRate, Timestamp = DateTime.Now, DeviceName = _bluetoothService.ConnectedDevice?.Name ?? "未知设备" }; await _webSocketClient.SendHeartRateDataAsync(data); } catch (Exception ex) { Debug.WriteLine($"发送心率数据失败: {ex.Message}"); } } /// /// 页面卸载时清理资源 /// ~MainPage() { if (_webSocketClient != null) { _webSocketClient.Dispose(); _webSocketClient = null; } _bluetoothService.Dispose(); } }