From 4cb51a38cba703027fc27be0a04de01f6cdbba24 Mon Sep 17 00:00:00 2001
From: NuanRMxi <2308425927@qq.com>
Date: Sat, 9 Aug 2025 21:11:41 +0800
Subject: [PATCH] Refactoring UI
---
MainPage.xaml | 191 ++++---
MainPage.xaml.cs | 390 ++++++--------
.../AndroidBackgroundServiceStarter.cs | 56 ++
.../Android/HeartRateKeepAliveService.cs | 491 ++++++++----------
Platforms/Android/MainApplication.cs | 9 +
Services/HeartRateDataService.cs | 232 +++++++++
Services/IHeartRateDataService.cs | 74 +++
7 files changed, 864 insertions(+), 579 deletions(-)
create mode 100644 Platforms/Android/AndroidBackgroundServiceStarter.cs
create mode 100644 Services/HeartRateDataService.cs
create mode 100644 Services/IHeartRateDataService.cs
diff --git a/MainPage.xaml b/MainPage.xaml
index d7bc002..8a5a667 100644
--- a/MainPage.xaml
+++ b/MainPage.xaml
@@ -2,34 +2,84 @@
+ BackgroundColor="#F8F9FA"
+ Title="心率监测">
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -37,75 +87,76 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MainPage.xaml.cs b/MainPage.xaml.cs
index 432f5d6..ff6f3dd 100644
--- a/MainPage.xaml.cs
+++ b/MainPage.xaml.cs
@@ -8,318 +8,224 @@ 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 const int UIUpdateIntervalMs = 1000; // 每秒更新一次UI
- // 图表更新定时器
- private IDispatcherTimer _graphUpdateTimer;
+ // UI更新定时器
+ private IDispatcherTimer _uiUpdateTimer;
- // WebSocket相关
- private WebSocketService.HeartRateWebSocketClient _webSocketClient;
- private bool _isWebSocketEnabled = false;
- private string _webSocketUrl = DefaultWebsocketUrl;
+ // 数据��务
+ private readonly IHeartRateDataService _dataService;
- // 后台模式标志
- private bool _isRunningInBackground = false;
-
- // 服务
- private readonly BluetoothService _bluetoothService;
-
- // 心率数据模型
- private readonly HeartRateSessionData _sessionData = new();
+ // 心率数据图表
private readonly HeartRateGraphDrawable _heartRateGraph = new();
+ // 会话开始时间
+ private DateTime _sessionStartTime = DateTime.Now;
+
public MainPage()
{
InitializeComponent();
- // 初始化蓝牙服务
- _bluetoothService = new BluetoothService();
- _bluetoothService.StatusUpdated += UpdateStatus;
- _bluetoothService.HeartRateUpdated += UpdateHeartRate;
- _bluetoothService.DeviceDiscovered += OnHeartRateDeviceDiscovered;
+ // 获取数据服务实例
+ _dataService = HeartRateDataService.Instance;
// 初始化图表
heartRateGraphicsView.Drawable = _heartRateGraph;
- // 初始化图表更新定时器
- InitializeGraphUpdateTimer();
+ // 订阅服务事件
+ SubscribeToServiceEvents();
- // 检查蓝牙状态
- _bluetoothService.CheckBluetoothState();
+ // 初始化UI更新定时器
+ InitializeUITimer();
+
+ // 启动后台服务
+ _ = StartBackgroundServiceAsync();
}
///
- /// 初始化图表更新定时器
+ /// 订阅服务事件
///
- private void InitializeGraphUpdateTimer()
+ private void SubscribeToServiceEvents()
{
- _graphUpdateTimer = Dispatcher.CreateTimer();
- _graphUpdateTimer.Interval = TimeSpan.FromMilliseconds(GraphUpdateIntervalMs);
- _graphUpdateTimer.Tick += async (s, e) => await UpdateGraph();
- _graphUpdateTimer.Start();
+ _dataService.HeartRateDataReceived += OnHeartRateDataReceived;
+ _dataService.ServiceStatusChanged += OnServiceStatusChanged;
+ _dataService.DeviceStatusChanged += OnDeviceStatusChanged;
}
///
- /// 更新图表和通知
+ /// 初始化UI更新定时器
///
- private async Task UpdateGraph()
+ private void InitializeUITimer()
{
- // 发送心率数据到服务器
- await SendHeartRateToServerAsync(_sessionData.LatestHeartRate);
+ _uiUpdateTimer = Dispatcher.CreateTimer();
+ _uiUpdateTimer.Interval = TimeSpan.FromMilliseconds(UIUpdateIntervalMs);
+ _uiUpdateTimer.Tick += async (s, e) => await UpdateUI();
+ _uiUpdateTimer.Start();
+ }
+ ///
+ /// 启动后台服务
+ ///
+ private async Task StartBackgroundServiceAsync()
+ {
+ try
+ {
+ UpdateServiceStatusUI("正在启动后台服务...", false);
+ await _dataService.StartBackgroundServiceAsync();
+ Debug.WriteLine($"{Tag}: 后台服务启动请求已发送");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 启动后台服务失败: {ex.Message}");
+ UpdateServiceStatusUI("服务启动失败", false);
+ }
+ }
+
+ ///
+ /// 更新UI界面
+ ///
+ private async Task UpdateUI()
+ {
+ var sessionData = _dataService.GetCurrentSessionData();
+
// 更新图表
- _heartRateGraph.UpdateData(_sessionData.HeartRateData);
- heartRateGraphicsView.Invalidate();
-
- // 重置新数据标记
- _sessionData.ResetNewDataFlag();
-
- // 如果在后台运行且有数据,更新通知
- if (_isRunningInBackground && _sessionData.HeartRateData.Count > 0)
+ if (sessionData.HasNewHeartRateData)
{
- var duration = _sessionData.GetSessionDuration();
- NotificationService.ShowHeartRateNotification(
- _sessionData.LatestHeartRate,
- _sessionData.AverageHeartRate,
- _sessionData.MinHeartRate,
- _sessionData.MaxHeartRate,
- duration);
+ _heartRateGraph.UpdateData(sessionData.HeartRateData);
+ heartRateGraphicsView.Invalidate();
+ sessionData.ResetNewDataFlag();
}
+
+ // 更新会话时长
+ var duration = DateTime.Now - _sessionStartTime;
+ durationLabel.Text = $"{duration:hh\\:mm\\:ss}";
+
+ // 更新数据点数
+ dataPointsLabel.Text = sessionData.HeartRateData.Count.ToString();
+
+ await Task.CompletedTask;
}
///
- /// 更新状态标签
+ /// 心率数据接收事件处理
///
- private void UpdateStatus(string status)
+ private void OnHeartRateDataReceived(int heartRate)
{
MainThread.BeginInvokeOnMainThread(() => {
- statusLabel.Text = status;
+ try
+ {
+ var sessionData = _dataService.GetCurrentSessionData();
+
+ // 更新当前心率显示
+ heartRateLabel.Text = $"{heartRate} bpm";
+ lastUpdateLabel.Text = $"更新时间: {DateTime.Now:HH:mm:ss}";
+
+ // 隐藏无数据提示
+ if (sessionData.HeartRateData.Count >= 1)
+ {
+ noDataLayout.IsVisible = false;
+ }
+
+ // 更新统计信息
+ minHeartRateLabel.Text = sessionData.MinHeartRate.ToString();
+ maxHeartRateLabel.Text = sessionData.MaxHeartRate.ToString();
+ avgHeartRateLabel.Text = sessionData.AverageHeartRate.ToString("0");
+
+ //Debug.WriteLine($"{Tag}: UI已更新心率数据: {heartRate} bpm");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 更新心率UI失败: {ex.Message}");
+ }
});
}
///
- /// 更新心率数据
+ /// 服务状态变化事件处理
///
- private void UpdateHeartRate(int heartRate)
+ private void OnServiceStatusChanged(ServiceStatus status)
{
MainThread.BeginInvokeOnMainThread(() => {
- // 更新UI上的心率显示
- heartRateLabel.Text = $"心率: {heartRate} BPM";
-
- // 添加新的心率数据点
- _sessionData.AddHeartRate(heartRate);
-
- // 如果是第一个数据点,隐藏提示标签
- if (_sessionData.HeartRateData.Count == 1)
+ try
{
- noDataLabel.IsVisible = false;
+ UpdateServiceStatusUI(status.StatusMessage, status.IsRunning);
+ UpdateUploadStatusUI(status.IsWebSocketConnected ? "已连接" : "未连接", status.IsWebSocketConnected);
+
+ Debug.WriteLine($"{Tag}: 服务状态已更新: {status.StatusMessage}");
}
-
- // 更新统计信息显示
- 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)
+ catch (Exception ex)
{
- _sessionData.ResetData();
- minHeartRateLabel.Text = "--";
- maxHeartRateLabel.Text = "--";
- avgHeartRateLabel.Text = "--";
- noDataLabel.IsVisible = true;
- heartRateGraphicsView.Invalidate();
+ Debug.WriteLine($"{Tag}: 更新服务状态UI失败: {ex.Message}");
}
});
}
///
- /// 后台运行按钮点击事件
+ /// 设备状态变化事件处理
///
- private async void OnBackgroundClicked(object sender, EventArgs e)
+ private void OnDeviceStatusChanged(DeviceConnectionStatus status)
{
- if (_bluetoothService.ConnectedDevice == null)
- {
- await DisplayAlert("提示", "请先连接心率设备", "确定");
- return;
- }
-
- _isRunningInBackground = !_isRunningInBackground;
-
- if (_isRunningInBackground)
- {
- backgroundButton.Text = "停止后台运行";
-
- // 显示通知
- if (_sessionData.HeartRateData.Count > 0)
+ MainThread.BeginInvokeOnMainThread(() => {
+ try
{
- TimeSpan duration = _sessionData.GetSessionDuration();
- NotificationService.ShowHeartRateNotification(
- _sessionData.LatestHeartRate,
- _sessionData.AverageHeartRate,
- _sessionData.MinHeartRate,
- _sessionData.MaxHeartRate,
- duration);
+ connectionStatusLabel.Text = status.ConnectionMessage;
+
+ // 如果设备重新连接,重置会话开始时间
+ if (status.IsConnected && !string.IsNullOrEmpty(status.DeviceName))
+ {
+ _sessionStartTime = DateTime.Now;
+
+ // 重置UI��示
+ minHeartRateLabel.Text = "--";
+ maxHeartRateLabel.Text = "--";
+ avgHeartRateLabel.Text = "--";
+ noDataLayout.IsVisible = true;
+ heartRateGraphicsView.Invalidate();
+ }
+
+ Debug.WriteLine($"{Tag}: 设备状态已更新: {status.ConnectionMessage}");
}
- else
+ catch (Exception ex)
{
- NotificationService.ShowHeartRateNotification(0, 0, 0, 0, TimeSpan.Zero);
+ Debug.WriteLine($"{Tag}: 更新设��状态UI失败: {ex.Message}");
}
-
- // 通知用户应用将在后台运行
- await DisplayAlert("后台运行", "应用将在后台继续监测心率。可以通过通知栏查看实时数据。", "确定");
- }
- else
- {
- backgroundButton.Text = "后台运行";
-
- // 取消通知
- Services.NotificationService.CancelNotification();
- }
+ });
}
///
- /// WebSocket设置按钮点击事件
+ /// 更新服务状态UI
///
- private async void OnWebSocketSettingsClicked(object sender, EventArgs e)
+ private void UpdateServiceStatusUI(string status, bool isRunning)
{
- 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;
- }
+ serviceStatusLabel.Text = status;
+ statusIndicator.Fill = isRunning ? Color.FromArgb("#28A745") : Color.FromArgb("#DC3545");
}
///
- /// 初始化WebSocket客户端
+ /// 更新数据上传状态UI
///
- private async Task InitializeWebSocketClientAsync(string url = null)
+ private void UpdateUploadStatusUI(string status, bool isConnected)
{
- // 释放现有的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}");
- }
+ uploadStatusLabel.Text = status;
+ uploadStatusLabel.TextColor = isConnected ? Color.FromArgb("#28A745") : Color.FromArgb("#DC3545");
}
///
/// 页面卸载时清理资源
///
- ~MainPage()
+ protected override void OnDisappearing()
{
- if (_webSocketClient != null)
- {
- _webSocketClient.Dispose();
- _webSocketClient = null;
- }
+ base.OnDisappearing();
+
+ // 停止定时器
+ _uiUpdateTimer?.Stop();
- _bluetoothService.Dispose();
+ // 取消订阅事件
+ if (_dataService != null)
+ {
+ _dataService.HeartRateDataReceived -= OnHeartRateDataReceived;
+ _dataService.ServiceStatusChanged -= OnServiceStatusChanged;
+ _dataService.DeviceStatusChanged -= OnDeviceStatusChanged;
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Platforms/Android/AndroidBackgroundServiceStarter.cs b/Platforms/Android/AndroidBackgroundServiceStarter.cs
new file mode 100644
index 0000000..d55705e
--- /dev/null
+++ b/Platforms/Android/AndroidBackgroundServiceStarter.cs
@@ -0,0 +1,56 @@
+using Android.Content;
+using HeartRateMonitorAndroid.Services;
+using Application = Android.App.Application;
+namespace HeartRateMonitorAndroid.Platforms.Android
+{
+ ///
+ /// Android平台的后台服务启动器实现
+ ///
+ public class AndroidBackgroundServiceStarter : IBackgroundServiceStarter
+ {
+ public async Task StartServiceAsync()
+ {
+ try
+ {
+ var context = Platform.CurrentActivity?.ApplicationContext ?? Application.Context;
+ var intent = new Intent(context, typeof(HeartRateKeepAliveService));
+ context.StartForegroundService(intent);
+ await Task.CompletedTask;
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"AndroidBackgroundServiceStarter: 启动服务失败: {ex.Message}");
+ throw;
+ }
+ }
+
+ public async Task StopServiceAsync()
+ {
+ try
+ {
+ var context = Platform.CurrentActivity?.ApplicationContext ?? Application.Context;
+ var intent = new Intent(context, typeof(HeartRateKeepAliveService));
+ context.StopService(intent);
+ await Task.CompletedTask;
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"AndroidBackgroundServiceStarter: 停止服务失败: {ex.Message}");
+ throw;
+ }
+ }
+ }
+
+ ///
+ /// Android平台的服务助手实现
+ ///
+ public class AndroidServiceHelper : IServiceHelper
+ {
+ public IBackgroundServiceStarter BackgroundServiceStarter { get; }
+
+ public AndroidServiceHelper()
+ {
+ BackgroundServiceStarter = new AndroidBackgroundServiceStarter();
+ }
+ }
+}
diff --git a/Platforms/Android/HeartRateKeepAliveService.cs b/Platforms/Android/HeartRateKeepAliveService.cs
index 871accd..75b7e70 100644
--- a/Platforms/Android/HeartRateKeepAliveService.cs
+++ b/Platforms/Android/HeartRateKeepAliveService.cs
@@ -21,12 +21,18 @@ namespace HeartRateMonitorAndroid.Platforms.Android
private const int NOTIFICATION_ID = 1001;
private const string CHANNEL_ID = "HeartRateMonitorChannel";
private const string CHANNEL_NAME = "心率监测服务";
+ private const int REPORT_INTERVAL_MS = 1000; // 1秒汇报间隔
private PowerManager.WakeLock _wakeLock;
- private System.Timers.Timer _heartRateTimer;
private WebSocketService.HeartRateWebSocketClient _webSocketClient;
private BluetoothService _bluetoothService;
+ private HeartRateDataService _dataService;
private bool _isServiceRunning = false;
+
+ // 定时汇报相关
+ private System.Threading.Timer _reportTimer;
+ private int _latestHeartRate = 0;
+ private readonly object _heartRateLock = new object();
public override void OnCreate()
{
@@ -41,8 +47,6 @@ namespace HeartRateMonitorAndroid.Platforms.Android
if (!_isServiceRunning)
{
StartForegroundService();
- StartHeartRateMonitoring();
- ScheduleJobService();
_isServiceRunning = true;
}
@@ -83,7 +87,7 @@ namespace HeartRateMonitorAndroid.Platforms.Android
var notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentTitle("心率监测服务")
.SetContentText("正在后台监测心率数据")
- .SetSmallIcon(Resource.Drawable.abc_dialog_material_background) // 使用系统图标
+ .SetSmallIcon(Resource.Drawable.abc_dialog_material_background)
.SetContentIntent(pendingIntent)
.SetOngoing(true)
.SetPriority(NotificationCompat.PriorityLow)
@@ -106,276 +110,242 @@ namespace HeartRateMonitorAndroid.Platforms.Android
{
System.Diagnostics.Debug.WriteLine("KeepAliveService: 开始初始化服务");
- // 获取服务实例
- var serviceProvider = MauiApplication.Current?.Services;
- _bluetoothService = serviceProvider?.GetService();
-
- if (_bluetoothService == null)
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 无法获取BluetoothService实例,创建新实例");
- _bluetoothService = new BluetoothService();
- }
- else
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 成功获取BluetoothService实例");
- }
+ // 获取数据服务实例
+ _dataService = HeartRateDataService.Instance;
+ _dataService.UpdateServiceStatus(false, "正在初始化服务...", false);
+
+ // 初始化蓝牙服务
+ _bluetoothService = new BluetoothService();
+ _bluetoothService.StatusUpdated += OnBluetoothStatusUpdated;
+ _bluetoothService.HeartRateUpdated += OnHeartRateDataReceived;
+ _bluetoothService.DeviceDiscovered += OnDeviceDiscovered;
+
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 蓝牙服务已初始化");
// 初始化WebSocket客户端
- var serverUrl = GetServerUrl();
- if (!string.IsNullOrEmpty(serverUrl))
- {
- _webSocketClient = new WebSocketService.HeartRateWebSocketClient(serverUrl);
- System.Diagnostics.Debug.WriteLine($"KeepAliveService: WebSocket客户端已初始化,服务器: {serverUrl}");
- }
- else
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 无法获取服务器URL");
- }
+ Task.Run(async () => await InitializeWebSocketAsync());
- // 如果蓝牙服务可用,尝试重新连接之前连接的设备
- if (_bluetoothService != null)
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 启动蓝牙重连任务");
- Task.Run(async () => await ReconnectBluetoothDevice());
- }
- else
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 蓝牙服务不可用,跳过蓝牙重连");
- }
+ // 启动蓝牙连接
+ Task.Run(async () => await StartBluetoothMonitoringAsync());
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine($"InitializeServices Error: {ex.Message}");
+ _dataService?.UpdateServiceStatus(false, "服务初始化失败", false);
}
}
- private async Task ReconnectBluetoothDevice()
+ private async Task InitializeWebSocketAsync()
{
try
{
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 尝试重新连接蓝牙设备");
-
- // 检查蓝牙状态
- var bluetoothState = _bluetoothService.CheckBluetoothState();
- if (!bluetoothState.Contains("准备就绪"))
+ var serverUrl = GetServerUrl();
+ if (!string.IsNullOrEmpty(serverUrl))
{
- System.Diagnostics.Debug.WriteLine($"KeepAliveService: 蓝牙状态不可用: {bluetoothState}");
- return;
- }
-
- // 尝试获取上次连接的设备地址
- var lastConnectedDeviceAddress = _bluetoothService.GetLastConnectedDeviceAddress();
- if (!string.IsNullOrEmpty(lastConnectedDeviceAddress))
- {
- System.Diagnostics.Debug.WriteLine($"KeepAliveService: 尝试连接上次的设备: {lastConnectedDeviceAddress}");
+ _webSocketClient = new WebSocketService.HeartRateWebSocketClient(serverUrl);
+ await _webSocketClient.ConnectAsync();
- // 首先尝试直接连接到已知设备
- var directConnectSuccess = await _bluetoothService.ConnectToDeviceByAddressAsync(lastConnectedDeviceAddress);
-
- if (!directConnectSuccess)
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 直接连接失败,开始扫描寻找设备");
-
- // 注册临时设备发现事件处理器
- bool deviceFound = false;
- Action tempDeviceHandler = (device) =>
- {
- if (device.Id.ToString() == lastConnectedDeviceAddress)
- {
- deviceFound = true;
- System.Diagnostics.Debug.WriteLine($"KeepAliveService: 在扫描中找到目标设备: {device.Name}");
- Task.Run(async () => await _bluetoothService.ConnectToDeviceAsync(device));
- }
- };
-
- _bluetoothService.DeviceDiscovered += tempDeviceHandler;
-
- try
- {
- // 开始扫描
- await _bluetoothService.StartScanAsync();
-
- // 等待10秒寻找目标设备
- for (int i = 0; i < 100 && !deviceFound; i++)
- {
- await Task.Delay(100);
- }
-
- // 停止扫描
- await _bluetoothService.StopScanAsync();
-
- if (deviceFound)
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 成功找到并连接目标设备");
- }
- else
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 未找到目标设备");
- }
- }
- finally
- {
- _bluetoothService.DeviceDiscovered -= tempDeviceHandler;
- }
- }
- else
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 直接连接成功");
- }
+ _dataService?.UpdateServiceStatus(true, "后台服务运行中", true, serverUrl);
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: WebSocket连接成功: {serverUrl}");
}
else
{
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 没有找到上次连接的设备信息,开始新的扫描");
-
- // 注册临时设备发现事件处理器
- bool anyDeviceFound = false;
- Action tempDeviceHandler = (device) =>
- {
- if (!anyDeviceFound)
- {
- anyDeviceFound = true;
- System.Diagnostics.Debug.WriteLine($"KeepAliveService: 发现心率设备: {device.Name}");
- Task.Run(async () => await _bluetoothService.ConnectToDeviceAsync(device));
- }
- };
-
- _bluetoothService.DeviceDiscovered += tempDeviceHandler;
-
- try
- {
- // 如果没有上次连接的设备信息,开始扫描
- await _bluetoothService.StartScanAsync();
-
- // 扫描15秒后停止
- await Task.Delay(15000);
- await _bluetoothService.StopScanAsync();
-
- if (anyDeviceFound)
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 找到并连接了新设备");
- }
- else
- {
- System.Diagnostics.Debug.WriteLine("KeepAliveService: 未找到任何心率设备");
- }
- }
- finally
- {
- _bluetoothService.DeviceDiscovered -= tempDeviceHandler;
- }
+ _dataService?.UpdateServiceStatus(true, "后台服务运行中", false);
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 无法获取服务器URL,WebSocket未连接");
}
}
catch (System.Exception ex)
{
- System.Diagnostics.Debug.WriteLine($"ReconnectBluetoothDevice Error: {ex.Message}");
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: WebSocket连接失败: {ex.Message}");
+ _dataService?.UpdateServiceStatus(true, "后台服务运行中", false);
}
}
- private string GetLastConnectedDeviceAddress()
+ private async Task StartBluetoothMonitoringAsync()
{
try
{
- // 使用MAUI的Preferences API获取设备地址
- return Microsoft.Maui.Storage.Preferences.Get("LastConnectedDevice", null);
- }
- catch (System.Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"GetLastConnectedDeviceAddress Error: {ex.Message}");
- return null;
- }
- }
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 开始蓝牙监测");
- private void SaveLastConnectedDeviceAddress(string deviceAddress)
- {
- try
- {
- var sharedPreferences = GetSharedPreferences("HeartRateMonitor", FileCreationMode.Private);
- var editor = sharedPreferences.Edit();
- editor.PutString("LastConnectedDevice", deviceAddress);
- editor.Apply();
- System.Diagnostics.Debug.WriteLine($"KeepAliveService: 保存设备地址: {deviceAddress}");
- }
- catch (System.Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"SaveLastConnectedDeviceAddress Error: {ex.Message}");
- }
- }
-
- private string GetServerUrl()
- {
- try
- {
- // 从Resources/Raw/token.txt读取服务器URL
- using var stream = FileSystem.OpenAppPackageFileAsync("server.txt").Result;
- using var reader = new StreamReader(stream);
-
- var contents = reader.ReadToEnd();
- return contents;
- }
- catch
- {
- return "wss:///ws.nuanr-mxi.com/ws"; // 默认URL
- }
- }
-
- private void StartHeartRateMonitoring()
- {
- _heartRateTimer = new System.Timers.Timer(1000); // 30秒间隔
- _heartRateTimer.Elapsed += async (sender, e) =>
- {
- try
+ // 检查蓝牙状态
+ _bluetoothService.CheckBluetoothState();
+
+ if (_bluetoothService.IsBluetoothAvailable)
{
- await MonitorHeartRate();
- }
- catch (System.Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"Heart rate monitoring error: {ex.Message}");
- }
- };
- _heartRateTimer.Start();
- }
-
- private async Task MonitorHeartRate()
- {
- try
- {
- // 确保WebSocket连接
- if (_webSocketClient != null)
- {
- await _webSocketClient.ConnectAsync();
+ _dataService?.UpdateDeviceStatus(false, "", "正在扫描心率设备...");
- // 从蓝牙设备获取心率数据
- var heartRate = await GetCurrentHeartRate();
- if (heartRate > 0)
- {
- await _webSocketClient.SendHeartRateAsync(heartRate);
- UpdateNotification($"最新心率: {heartRate} BPM");
- }
+ // 开始扫描心率设备
+ await _bluetoothService.StartScanAsync();
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 蓝牙扫描已启动");
+ }
+ else
+ {
+ _dataService?.UpdateDeviceStatus(false, "", "蓝牙不可用");
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 蓝牙不可用");
}
}
catch (System.Exception ex)
{
- System.Diagnostics.Debug.WriteLine($"MonitorHeartRate Error: {ex.Message}");
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 蓝牙监测启动失败: {ex.Message}");
+ _dataService?.UpdateDeviceStatus(false, "", "蓝牙监测启动失败");
}
}
- private async Task GetCurrentHeartRate()
+ private void OnBluetoothStatusUpdated(string status)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 蓝牙状态更新: {status}");
+ _dataService?.UpdateDeviceStatus(false, "", status);
+ }
+
+ private void OnHeartRateDataReceived(int heartRate)
{
try
{
- // 只从蓝牙设备获取真实心率数据
- if (_bluetoothService?.ConnectedDevice != null)
+ //System.Diagnostics.Debug.WriteLine($"KeepAliveService: 收到心率数据: {heartRate} bpm");
+
+ // 只更新最新心率值,不立即发送数据
+ lock (_heartRateLock)
{
- // 从BluetoothService获取最新的心率值
- return _bluetoothService.LastHeartRate;
+ _latestHeartRate = heartRate;
}
- // 如果没有连接设备,返回0表示无数据
- return 0;
+ //System.Diagnostics.Debug.WriteLine($"KeepAliveService: 心率数据已更新: {heartRate} bpm");
}
- catch
+ catch (System.Exception ex)
{
- return 0;
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 处理心率数据失败: {ex.Message}");
+ }
+ }
+
+ private async void OnDeviceDiscovered(Plugin.BLE.Abstractions.Contracts.IDevice device)
+ {
+ try
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 发现设备: {device.Name ?? "未知设备"}");
+
+ _dataService?.UpdateDeviceStatus(false, device.Name ?? "未知设备", $"发现设备: {device.Name ?? "未知设备"}");
+
+ // 尝试连接设备
+ await _bluetoothService.ConnectToDeviceAsync(device);
+
+ if (_bluetoothService.ConnectedDevice != null)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 设备连接成功: {device.Name}");
+
+ _dataService?.UpdateDeviceStatus(true, device.Name ?? "未知设备", $"已连接: {device.Name ?? "未知设备"}");
+ _dataService?.ResetSessionData(); // 重置会话数据
+
+ // 启动定时汇报
+ StartPeriodicReporting();
+ }
+ }
+ catch (System.Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 设备连接失败: {ex.Message}");
+ _dataService?.UpdateDeviceStatus(false, "", "设备连接失败");
+ }
+ }
+
+ ///
+ /// 启动定时汇报(每秒一次)
+ ///
+ private void StartPeriodicReporting()
+ {
+ try
+ {
+ // 停止现有定时器
+ StopPeriodicReporting();
+
+ // 启动新的定时器
+ _reportTimer = new System.Threading.Timer(OnPeriodicReport, null,
+ TimeSpan.FromMilliseconds(REPORT_INTERVAL_MS),
+ TimeSpan.FromMilliseconds(REPORT_INTERVAL_MS));
+
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 定时汇报已启动,间隔1秒");
+ }
+ catch (System.Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 启动定时汇报失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 停止定时汇报
+ ///
+ private void StopPeriodicReporting()
+ {
+ try
+ {
+ _reportTimer?.Dispose();
+ _reportTimer = null;
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 定时汇报已停止");
+ }
+ catch (System.Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 停止定时汇报失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 定时汇报回调方法
+ ///
+ private async void OnPeriodicReport(object state)
+ {
+ try
+ {
+ if (!_isServiceRunning) return;
+
+ int currentHeartRate;
+ lock (_heartRateLock)
+ {
+ currentHeartRate = _latestHeartRate;
+ }
+
+ // 无论心率数据是否更新,都进行汇报
+ //System.Diagnostics.Debug.WriteLine($"KeepAliveService: 定时汇报 - 心率: {currentHeartRate} bpm");
+
+ // 更新数据服务(触发UI更新)
+ if (currentHeartRate > 0)
+ {
+ _dataService?.UpdateHeartRateData(currentHeartRate);
+ }
+
+ // 发送到WebSocket服务器
+ if (_webSocketClient != null)
+ {
+ await SendHeartRateToServerAsync(currentHeartRate);
+ }
+
+ // 更新通知
+ var message = currentHeartRate > 0 ? $"最新心率: {currentHeartRate} BPM" : "等待心率数据...";
+ UpdateNotification(message);
+ }
+ catch (System.Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 定时汇报失败: {ex.Message}");
+ }
+ }
+
+ private async Task SendHeartRateToServerAsync(int heartRate)
+ {
+ try
+ {
+ if (_webSocketClient == null) return;
+
+ var data = new WebSocketService.HeartRateData
+ {
+ HeartRate = heartRate,
+ Timestamp = DateTime.Now,
+ DeviceName = _bluetoothService?.ConnectedDevice?.Name ?? "未知设备"
+ };
+
+ await _webSocketClient.SendHeartRateDataAsync(data);
+ //System.Diagnostics.Debug.WriteLine($"KeepAliveService: 心率数据已发送到服务器: {heartRate} bpm");
+ }
+ catch (System.Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 发送心率数据失败: {ex.Message}");
+ _dataService?.UpdateServiceStatus(true, "后台服务运行中", false);
}
}
@@ -390,7 +360,7 @@ namespace HeartRateMonitorAndroid.Platforms.Android
var notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentTitle("心率监测服务")
.SetContentText(message)
- .SetSmallIcon(Resource.Drawable.abc_dialog_material_background) // 使用系统图标
+ .SetSmallIcon(Resource.Drawable.abc_dialog_material_background)
.SetContentIntent(pendingIntent)
.SetOngoing(true)
.Build();
@@ -404,65 +374,52 @@ namespace HeartRateMonitorAndroid.Platforms.Android
}
}
- private void ScheduleJobService()
+ private string GetServerUrl()
{
try
{
- var jobScheduler = GetSystemService(JobSchedulerService) as JobScheduler;
- var jobInfo = new JobInfo.Builder(1002, new ComponentName(this, Java.Lang.Class.FromType(typeof(HeartRateJobService))))
- .SetRequiredNetworkType(NetworkType.Any)
- .SetPersisted(true)
- .SetPeriodic(15 * 60 * 1000) // 15分钟
- .SetRequiresCharging(false)
- .SetRequiresDeviceIdle(false)
- .Build();
-
- jobScheduler?.Schedule(jobInfo);
+ // 从资源文件读取服���器地址
+ using var stream = Assets.Open("server.txt");
+ using var reader = new System.IO.StreamReader(stream);
+ return reader.ReadToEnd().Trim();
}
- catch (System.Exception ex)
+ catch
{
- System.Diagnostics.Debug.WriteLine($"ScheduleJobService Error: {ex.Message}");
+ return "wss://ws.nuanr-mxi.com/ws"; // 默认服务器地址
}
}
public override void OnDestroy()
- {
- _isServiceRunning = false;
- _heartRateTimer?.Stop();
- _heartRateTimer?.Dispose();
- _webSocketClient?.Dispose();
- _wakeLock?.Release();
-
- // 服务被销毁时,立即重启
- RestartService();
-
- base.OnDestroy();
- }
-
- private void RestartService()
{
try
{
- var intent = new Intent(this, typeof(HeartRateKeepAliveService));
- if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
- {
- StartForegroundService(intent);
- }
- else
- {
- StartService(intent);
- }
+ _isServiceRunning = false;
+
+ // 停止定时汇报
+ StopPeriodicReporting();
+
+ // 清理资源
+ _bluetoothService?.Dispose();
+ _webSocketClient?.Dispose();
+ _wakeLock?.Release();
+
+ _dataService?.UpdateServiceStatus(false, "服务已停止", false);
+
+ System.Diagnostics.Debug.WriteLine("KeepAliveService: 服务已停止");
}
catch (System.Exception ex)
{
- System.Diagnostics.Debug.WriteLine($"RestartService Error: {ex.Message}");
+ System.Diagnostics.Debug.WriteLine($"KeepAliveService: 服务停止时发生错误: {ex.Message}");
}
+
+ base.OnDestroy();
}
public override void OnTaskRemoved(Intent rootIntent)
{
// 当任务被移除时重启服务
- RestartService();
+ var intent = new Intent(this, typeof(HeartRateKeepAliveService));
+ StartForegroundService(intent);
base.OnTaskRemoved(rootIntent);
}
}
diff --git a/Platforms/Android/MainApplication.cs b/Platforms/Android/MainApplication.cs
index 209e336..9abf24c 100644
--- a/Platforms/Android/MainApplication.cs
+++ b/Platforms/Android/MainApplication.cs
@@ -1,5 +1,6 @@
using Android.App;
using Android.Runtime;
+using HeartRateMonitorAndroid.Services;
namespace HeartRateMonitorAndroid;
@@ -12,4 +13,12 @@ public class MainApplication : MauiApplication
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+
+ public override void OnCreate()
+ {
+ base.OnCreate();
+
+ // 设置Android平台特定的服务助手
+ ServiceHelper.Current = new Platforms.Android.AndroidServiceHelper();
+ }
}
\ No newline at end of file
diff --git a/Services/HeartRateDataService.cs b/Services/HeartRateDataService.cs
new file mode 100644
index 0000000..5949c40
--- /dev/null
+++ b/Services/HeartRateDataService.cs
@@ -0,0 +1,232 @@
+using HeartRateMonitorAndroid.Models;
+using System.Diagnostics;
+
+namespace HeartRateMonitorAndroid.Services
+{
+ ///
+ /// 心率数据服务实现,作为前端与后台服务的桥梁
+ ///
+ public class HeartRateDataService : IHeartRateDataService
+ {
+ private const string Tag = "HeartRateDataService";
+
+ // 静态实例,用于在后台服务和前端之间共享数据
+ private static HeartRateDataService _instance;
+ private static readonly object _lock = new object();
+
+ // 事件
+ public event Action HeartRateDataReceived;
+ public event Action ServiceStatusChanged;
+ public event Action DeviceStatusChanged;
+
+ // 数据存储
+ private readonly HeartRateSessionData _sessionData = new();
+ private ServiceStatus _serviceStatus = new();
+ private DeviceConnectionStatus _deviceStatus = new();
+
+ private HeartRateDataService()
+ {
+ // 私有构造函数,确保单例模式
+ }
+
+ ///
+ /// 获取单例实例
+ ///
+ public static HeartRateDataService Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ lock (_lock)
+ {
+ if (_instance == null)
+ {
+ _instance = new HeartRateDataService();
+ }
+ }
+ }
+ return _instance;
+ }
+ }
+
+ ///
+ /// 获取当前心率数据
+ ///
+ public HeartRateSessionData GetCurrentSessionData()
+ {
+ return _sessionData;
+ }
+
+ ///
+ /// 获取服务状态
+ ///
+ public ServiceStatus GetServiceStatus()
+ {
+ return _serviceStatus;
+ }
+
+ ///
+ /// 获取设备连接状态
+ ///
+ public DeviceConnectionStatus GetDeviceStatus()
+ {
+ return _deviceStatus;
+ }
+
+ ///
+ /// 启动后台服务(平台特定实现将在调用时提供)
+ ///
+ public async Task StartBackgroundServiceAsync()
+ {
+ try
+ {
+ // 通过依赖注入获取平台特定的服务启动器
+ var serviceStarter = ServiceHelper.Current?.BackgroundServiceStarter;
+ if (serviceStarter != null)
+ {
+ await serviceStarter.StartServiceAsync();
+ Debug.WriteLine($"{Tag}: 后台服务启动请求已发送");
+ }
+ else
+ {
+ Debug.WriteLine($"{Tag}: 无法获取平台特定的服务启动器");
+ throw new PlatformNotSupportedException("当前平台不支持后台服务");
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 启动后台服务失败: {ex.Message}");
+ throw;
+ }
+ }
+
+ ///
+ /// 停止后台服务
+ ///
+ public async Task StopBackgroundServiceAsync()
+ {
+ try
+ {
+ var serviceStarter = ServiceHelper.Current?.BackgroundServiceStarter;
+ if (serviceStarter != null)
+ {
+ await serviceStarter.StopServiceAsync();
+ Debug.WriteLine($"{Tag}: 后台服务停止请求已发送");
+ }
+ else
+ {
+ Debug.WriteLine($"{Tag}: 无法获取平台特定的服务启动器");
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 停止后台服务失败: {ex.Message}");
+ throw;
+ }
+ }
+
+ // 以下方法供后台服务调用,用于更新数据和状态
+
+ ///
+ /// 更新心率数据(由后台服务调用)
+ ///
+ public void UpdateHeartRateData(int heartRate)
+ {
+ try
+ {
+ _sessionData.AddHeartRate(heartRate);
+ HeartRateDataReceived?.Invoke(heartRate);
+ //Debug.WriteLine($"{Tag}: 心率数据已更新: {heartRate} bpm");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 更新心率数据失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 更新服务状态(由后台服务调用)
+ ///
+ public void UpdateServiceStatus(bool isRunning, string statusMessage, bool isWebSocketConnected, string webSocketUrl = "")
+ {
+ try
+ {
+ _serviceStatus.IsRunning = isRunning;
+ _serviceStatus.StatusMessage = statusMessage;
+ _serviceStatus.IsWebSocketConnected = isWebSocketConnected;
+ _serviceStatus.WebSocketUrl = webSocketUrl;
+ _serviceStatus.LastUpdateTime = DateTime.Now;
+
+ ServiceStatusChanged?.Invoke(_serviceStatus);
+ Debug.WriteLine($"{Tag}: 服务状态已更新: {statusMessage}");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 更新服务状态失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 更新设备连接状态(由后台服务调用)
+ ///
+ public void UpdateDeviceStatus(bool isConnected, string deviceName, string connectionMessage)
+ {
+ try
+ {
+ _deviceStatus.IsConnected = isConnected;
+ _deviceStatus.DeviceName = deviceName;
+ _deviceStatus.ConnectionMessage = connectionMessage;
+ _deviceStatus.LastConnectionTime = DateTime.Now;
+
+ DeviceStatusChanged?.Invoke(_deviceStatus);
+ Debug.WriteLine($"{Tag}: 设备状态已更新: {connectionMessage}");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 更新设备状态失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 重置会话数据(由后台服务调用)
+ ///
+ public void ResetSessionData()
+ {
+ try
+ {
+ _sessionData.ResetData();
+ Debug.WriteLine($"{Tag}: 会话数据已重置");
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"{Tag}: 重置会话数据失败: {ex.Message}");
+ }
+ }
+ }
+
+ ///
+ /// 平台特定服务启动器接口
+ ///
+ public interface IBackgroundServiceStarter
+ {
+ Task StartServiceAsync();
+ Task StopServiceAsync();
+ }
+
+ ///
+ /// 服务助手类,用于获取平台特定的服务
+ ///
+ public static class ServiceHelper
+ {
+ public static IServiceHelper Current { get; set; }
+ }
+
+ ///
+ /// 服务助手接口
+ ///
+ public interface IServiceHelper
+ {
+ IBackgroundServiceStarter BackgroundServiceStarter { get; }
+ }
+}
diff --git a/Services/IHeartRateDataService.cs b/Services/IHeartRateDataService.cs
new file mode 100644
index 0000000..8fd51df
--- /dev/null
+++ b/Services/IHeartRateDataService.cs
@@ -0,0 +1,74 @@
+using HeartRateMonitorAndroid.Models;
+
+namespace HeartRateMonitorAndroid.Services
+{
+ ///
+ /// 心率数据服务接口,用于前端与后台服务通信
+ ///
+ public interface IHeartRateDataService
+ {
+ ///
+ /// 心率数据更新事件
+ ///
+ event Action HeartRateDataReceived;
+
+ ///
+ /// 服务状态更新事件
+ ///
+ event Action ServiceStatusChanged;
+
+ ///
+ /// 设备连接状态更新事件
+ ///
+ event Action DeviceStatusChanged;
+
+ ///
+ /// 获取当前心率数据
+ ///
+ HeartRateSessionData GetCurrentSessionData();
+
+ ///
+ /// 获取服务状态
+ ///
+ ServiceStatus GetServiceStatus();
+
+ ///
+ /// 获取设备连接状态
+ ///
+ DeviceConnectionStatus GetDeviceStatus();
+
+ ///
+ /// 启动后台服务
+ ///
+ Task StartBackgroundServiceAsync();
+
+ ///
+ /// 停止后台服务
+ ///
+ Task StopBackgroundServiceAsync();
+ }
+
+ ///
+ /// 服务状态
+ ///
+ public class ServiceStatus
+ {
+ public bool IsRunning { get; set; }
+ public string StatusMessage { get; set; } = "";
+ public bool IsWebSocketConnected { get; set; }
+ public string WebSocketUrl { get; set; } = "";
+ public DateTime LastUpdateTime { get; set; }
+ }
+
+ ///
+ /// 设备连接状态
+ ///
+ public class DeviceConnectionStatus
+ {
+ public bool IsConnected { get; set; }
+ public string DeviceName { get; set; } = "";
+ public string ConnectionMessage { get; set; } = "";
+ public DateTime LastConnectionTime { get; set; }
+ public int SignalStrength { get; set; } // 信号强度,如果支持的话
+ }
+}